From 9e542f41cc2883cc6b86d9e3a313863d858ae3fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=96=E7=95=8C?= Date: Thu, 11 Sep 2025 19:08:23 +0800 Subject: [PATCH] Fix ping domain --- go.mod | 2 +- go.sum | 4 +- route/route.go | 68 +++++++++++++++++++++++++++---- transport/wireguard/device_nat.go | 4 +- 4 files changed, 66 insertions(+), 12 deletions(-) diff --git a/go.mod b/go.mod index 0a26fe3a5..e2935044e 100644 --- a/go.mod +++ b/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.1 diff --git a/go.sum b/go.sum index 263568423..bc94fc35d 100644 --- a/go.sum +++ b/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= diff --git a/route/route.go b/route/route.go index 7e87e97fb..1d6663d8d 100644 --- a/route/route.go +++ b/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( diff --git a/transport/wireguard/device_nat.go b/transport/wireguard/device_nat.go index e5a28c1b1..d214b737b 100644 --- a/transport/wireguard/device_nat.go +++ b/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 }