Browse Source

Fix ping domain

世界 1 month ago
parent
commit
0546d8c1b2
4 changed files with 66 additions and 12 deletions
  1. 1 1
      go.mod
  2. 2 2
      go.sum
  3. 61 7
      route/route.go
  4. 2 2
      transport/wireguard/device_nat.go

+ 1 - 1
go.mod

@@ -33,7 +33,7 @@ require (
 	github.com/sagernet/sing-shadowsocks v0.2.8
 	github.com/sagernet/sing-shadowsocks2 v0.2.1
 	github.com/sagernet/sing-shadowtls v0.2.1-0.20250503051639-fcd445d33c11
-	github.com/sagernet/sing-tun v0.8.0-beta.8
+	github.com/sagernet/sing-tun v0.8.0-beta.8.0.20250911105100-0381a06643bc
 	github.com/sagernet/sing-vmess v0.2.8-0.20250909125414-3aed155119a1
 	github.com/sagernet/smux v1.5.34-mod.2
 	github.com/sagernet/tailscale v1.80.3-sing-box-1.13-mod.2

+ 2 - 2
go.sum

@@ -179,8 +179,8 @@ github.com/sagernet/sing-shadowsocks2 v0.2.1 h1:dWV9OXCeFPuYGHb6IRqlSptVnSzOelnq
 github.com/sagernet/sing-shadowsocks2 v0.2.1/go.mod h1:RnXS0lExcDAovvDeniJ4IKa2IuChrdipolPYWBv9hWQ=
 github.com/sagernet/sing-shadowtls v0.2.1-0.20250503051639-fcd445d33c11 h1:tK+75l64tm9WvEFrYRE1t0YxoFdWQqw/h7Uhzj0vJ+w=
 github.com/sagernet/sing-shadowtls v0.2.1-0.20250503051639-fcd445d33c11/go.mod h1:sWqKnGlMipCHaGsw1sTTlimyUpgzP4WP3pjhCsYt9oA=
-github.com/sagernet/sing-tun v0.8.0-beta.8 h1:K/tPAiuW4Qf1usZvdqjAMVwaxAVE/fb64YqO9SCvcTg=
-github.com/sagernet/sing-tun v0.8.0-beta.8/go.mod h1:DCGwHe70ujuzmQ3bvUnf9u1FFRoRvBQ1dDpqZov1ZDA=
+github.com/sagernet/sing-tun v0.8.0-beta.8.0.20250911105100-0381a06643bc h1:u6MwQ35W6gIVWRAVjKx3TtaNIhO39Bsz5LkvkWGnnuk=
+github.com/sagernet/sing-tun v0.8.0-beta.8.0.20250911105100-0381a06643bc/go.mod h1:DCGwHe70ujuzmQ3bvUnf9u1FFRoRvBQ1dDpqZov1ZDA=
 github.com/sagernet/sing-vmess v0.2.8-0.20250909125414-3aed155119a1 h1:aSwUNYUkVyVvdmBSufR8/nRFonwJeKSIROxHcm5br9o=
 github.com/sagernet/sing-vmess v0.2.8-0.20250909125414-3aed155119a1/go.mod h1:P11scgTxMxVVQ8dlM27yNm3Cro40mD0+gHbnqrNGDuY=
 github.com/sagernet/smux v1.5.34-mod.2 h1:gkmBjIjlJ2zQKpLigOkFur5kBKdV6bNRoFu2WkltRQ4=

+ 61 - 7
route/route.go

@@ -17,6 +17,7 @@ import (
 	R "github.com/sagernet/sing-box/route/rule"
 	"github.com/sagernet/sing-mux"
 	"github.com/sagernet/sing-tun"
+	"github.com/sagernet/sing-tun/ping"
 	"github.com/sagernet/sing-vmess"
 	"github.com/sagernet/sing/common"
 	"github.com/sagernet/sing/common/buf"
@@ -271,6 +272,7 @@ func (r *Router) PreMatch(metadata adapter.InboundContext, routeContext tun.Dire
 	if err != nil {
 		return nil, err
 	}
+	var directRouteOutbound adapter.DirectRouteOutbound
 	if selectedRule != nil {
 		switch action := selectedRule.Action().(type) {
 		case *R.RuleActionReject:
@@ -296,17 +298,69 @@ func (r *Router) PreMatch(metadata adapter.InboundContext, routeContext tun.Dire
 			if !common.Contains(outbound.Network(), metadata.Network) {
 				return nil, E.New(metadata.Network, " is not supported by outbound: ", action.Outbound)
 			}
-			return outbound.(adapter.DirectRouteOutbound).NewDirectRouteConnection(metadata, routeContext, timeout)
+			directRouteOutbound = outbound.(adapter.DirectRouteOutbound)
 		}
 	}
-	if selectedRule != nil || metadata.Network != N.NetworkICMP {
-		return nil, nil
+	if directRouteOutbound == nil {
+		if selectedRule != nil || metadata.Network != N.NetworkICMP {
+			return nil, nil
+		}
+		defaultOutbound := r.outbound.Default()
+		if !common.Contains(defaultOutbound.Network(), metadata.Network) {
+			return nil, E.New(metadata.Network, " is not supported by default outbound: ", defaultOutbound.Tag())
+		}
+		directRouteOutbound = defaultOutbound.(adapter.DirectRouteOutbound)
 	}
-	defaultOutbound := r.outbound.Default()
-	if !common.Contains(defaultOutbound.Network(), metadata.Network) {
-		return nil, E.New(metadata.Network, " is not supported by default outbound: ", defaultOutbound.Tag())
+	if metadata.Destination.IsFqdn() {
+		if len(metadata.DestinationAddresses) == 0 {
+			var strategy C.DomainStrategy
+			if metadata.Source.IsIPv4() {
+				strategy = C.DomainStrategyIPv4Only
+			} else {
+				strategy = C.DomainStrategyIPv6Only
+			}
+			err = r.actionResolve(r.ctx, &metadata, &R.RuleActionResolve{
+				Strategy: strategy,
+			})
+			if err != nil {
+				return nil, err
+			}
+		}
+		var newDestination netip.Addr
+		if metadata.Source.IsIPv4() {
+			for _, address := range metadata.DestinationAddresses {
+				if address.Is4() {
+					newDestination = address
+					break
+				}
+			}
+		} else {
+			for _, address := range metadata.DestinationAddresses {
+				if address.Is6() {
+					newDestination = address
+					break
+				}
+			}
+		}
+		if !newDestination.IsValid() {
+			if metadata.Source.IsIPv4() {
+				return nil, E.New("no IPv4 address found for domain: ", metadata.Destination.Fqdn)
+			} else {
+				return nil, E.New("no IPv6 address found for domain: ", metadata.Destination.Fqdn)
+			}
+		}
+		metadata.Destination = M.Socksaddr{
+			Addr: newDestination,
+		}
+		routeContext = ping.NewContextDestinationWriter(routeContext, metadata.OriginDestination.Addr)
+		var routeDestination tun.DirectRouteDestination
+		routeDestination, err = directRouteOutbound.NewDirectRouteConnection(metadata, routeContext, timeout)
+		if err != nil {
+			return nil, err
+		}
+		return ping.NewDestinationWriter(routeDestination, newDestination), nil
 	}
-	return defaultOutbound.(adapter.DirectRouteOutbound).NewDirectRouteConnection(metadata, routeContext, timeout)
+	return directRouteOutbound.NewDirectRouteConnection(metadata, routeContext, timeout)
 }
 
 func (r *Router) matchRule(

+ 2 - 2
transport/wireguard/device_nat.go

@@ -20,7 +20,7 @@ type natDeviceWrapper struct {
 	ctx            context.Context
 	logger         logger.ContextLogger
 	packetOutbound chan *buf.Buffer
-	rewriter       *ping.Rewriter
+	rewriter       *ping.SourceRewriter
 	buffer         [][]byte
 }
 
@@ -30,7 +30,7 @@ func NewNATDevice(ctx context.Context, logger logger.ContextLogger, upstream Dev
 		ctx:            ctx,
 		logger:         logger,
 		packetOutbound: make(chan *buf.Buffer, 256),
-		rewriter:       ping.NewRewriter(ctx, logger, upstream.Inet4Address(), upstream.Inet6Address()),
+		rewriter:       ping.NewSourceRewriter(ctx, logger, upstream.Inet4Address(), upstream.Inet6Address()),
 	}
 	return wrapper
 }