From 0ced98da4d704c51c76123fd947b4c3f7df59708 Mon Sep 17 00:00:00 2001 From: wwqgtxx Date: Wed, 27 Aug 2025 18:00:25 +0800 Subject: [PATCH] feat: support sending ping requests via direct in tun mode --- component/dialer/bind_darwin.go | 6 +++--- component/dialer/dialer.go | 29 ++++++++++++++++++++++++++++ go.mod | 6 +++--- go.sum | 12 ++++++------ listener/sing_tun/prepare.go | 34 +++++++++++++++++++++++++++++++++ listener/sing_tun/server.go | 7 ++++--- 6 files changed, 79 insertions(+), 15 deletions(-) create mode 100644 listener/sing_tun/prepare.go diff --git a/component/dialer/bind_darwin.go b/component/dialer/bind_darwin.go index fdea24bf..159d3d27 100644 --- a/component/dialer/bind_darwin.go +++ b/component/dialer/bind_darwin.go @@ -21,10 +21,10 @@ func bindControl(ifaceIdx int) controlFn { var innerErr error err = c.Control(func(fd uintptr) { switch network { - case "tcp4", "udp4": - innerErr = unix.SetsockoptInt(int(fd), unix.IPPROTO_IP, unix.IP_BOUND_IF, ifaceIdx) - case "tcp6", "udp6": + case "tcp6", "udp6", "ip6": innerErr = unix.SetsockoptInt(int(fd), unix.IPPROTO_IPV6, unix.IPV6_BOUND_IF, ifaceIdx) + default: + innerErr = unix.SetsockoptInt(int(fd), unix.IPPROTO_IP, unix.IP_BOUND_IF, ifaceIdx) } }) diff --git a/component/dialer/dialer.go b/component/dialer/dialer.go index 4402f774..d490dca3 100644 --- a/component/dialer/dialer.go +++ b/component/dialer/dialer.go @@ -9,6 +9,7 @@ import ( "os" "strings" "sync" + "syscall" "time" "github.com/metacubex/mihomo/component/keepalive" @@ -177,6 +178,34 @@ func dialContext(ctx context.Context, network string, destination netip.Addr, po return dialer.DialContext(ctx, network, address) } +func ICMPControl(destination netip.Addr) func(network, address string, conn syscall.RawConn) error { + return func(network, address string, conn syscall.RawConn) error { + if DefaultSocketHook != nil { + return DefaultSocketHook(network, address, conn) + } + dialer := &net.Dialer{} + interfaceName := DefaultInterface.Load() + if interfaceName == "" { + if finder := DefaultInterfaceFinder.Load(); finder != nil { + interfaceName = finder.FindInterfaceName(destination) + } + } + if interfaceName != "" { + if err := bindIfaceToDialer(interfaceName, dialer, network, destination); err != nil { + return err + } + } + routingMark := int(DefaultRoutingMark.Load()) + if routingMark != 0 { + bindMarkToDialer(routingMark, dialer, network, destination) + } + if dialer.ControlContext != nil { + return dialer.ControlContext(context.TODO(), network, address, conn) + } + return nil + } +} + func serialSingleStackDialContext(ctx context.Context, network string, ips []netip.Addr, port string, opt option) (net.Conn, error) { return serialDialContext(ctx, network, ips, port, opt) } diff --git a/go.mod b/go.mod index 834bac83..f7a63fa7 100644 --- a/go.mod +++ b/go.mod @@ -24,13 +24,13 @@ require ( github.com/metacubex/quic-go v0.54.1-0.20250730114134-a1ae705fe295 github.com/metacubex/randv2 v0.2.0 github.com/metacubex/restls-client-go v0.1.7 - github.com/metacubex/sing v0.5.5 + github.com/metacubex/sing v0.5.6-0.20250826072929-f69b475e017b github.com/metacubex/sing-mux v0.3.3-0.20250813083925-d7c9aeaeeaac github.com/metacubex/sing-quic v0.0.0-20250718154553-1b193bec4cbb github.com/metacubex/sing-shadowsocks v0.2.12 github.com/metacubex/sing-shadowsocks2 v0.2.6 github.com/metacubex/sing-shadowtls v0.0.0-20250503063515-5d9f966d17a2 - github.com/metacubex/sing-tun v0.4.7 + github.com/metacubex/sing-tun v0.4.8-0.20250827085914-fc5681b9fc9f github.com/metacubex/sing-vmess v0.2.4-0.20250822020810-4856053566f0 github.com/metacubex/sing-wireguard v0.0.0-20250503063753-2dc62acc626f github.com/metacubex/smux v0.0.0-20250503055512-501391591dee @@ -89,7 +89,7 @@ require ( github.com/mailru/easyjson v0.7.7 // indirect github.com/mdlayher/socket v0.4.1 // indirect github.com/metacubex/ascon v0.1.0 // indirect - github.com/metacubex/gvisor v0.0.0-20250324165734-5857f47bd43b // indirect + github.com/metacubex/gvisor v0.0.0-20250826025146-23043f716a2c // indirect github.com/metacubex/nftables v0.0.0-20250503052935-30a69ab87793 // indirect github.com/oasisprotocol/deoxysii v0.0.0-20220228165953-2091330c22b7 // indirect github.com/onsi/ginkgo/v2 v2.9.5 // indirect diff --git a/go.sum b/go.sum index 15b38771..9b62944f 100644 --- a/go.sum +++ b/go.sum @@ -106,8 +106,8 @@ github.com/metacubex/fswatch v0.1.1 h1:jqU7C/v+g0qc2RUFgmAOPoVvfl2BXXUXEumn6oQux github.com/metacubex/fswatch v0.1.1/go.mod h1:czrTT7Zlbz7vWft8RQu9Qqh+JoX+Nnb+UabuyN1YsgI= github.com/metacubex/gopacket v1.1.20-0.20230608035415-7e2f98a3e759 h1:cjd4biTvOzK9ubNCCkQ+ldc4YSH/rILn53l/xGBFHHI= github.com/metacubex/gopacket v1.1.20-0.20230608035415-7e2f98a3e759/go.mod h1:UHOv2xu+RIgLwpXca7TLrXleEd4oR3sPatW6IF8wU88= -github.com/metacubex/gvisor v0.0.0-20250324165734-5857f47bd43b h1:RUh4OdVPz/jDrM9MQ2ySuqu2aeBqcA8rtfWUYLZ8RtI= -github.com/metacubex/gvisor v0.0.0-20250324165734-5857f47bd43b/go.mod h1:8LpS0IJW1VmWzUm3ylb0e2SK5QDm5lO/2qwWLZgRpBU= +github.com/metacubex/gvisor v0.0.0-20250826025146-23043f716a2c h1:N9m7IAKfBuGDieY/JT2wjfdyURgTNpFNOFpqq+RF0i4= +github.com/metacubex/gvisor v0.0.0-20250826025146-23043f716a2c/go.mod h1:8LpS0IJW1VmWzUm3ylb0e2SK5QDm5lO/2qwWLZgRpBU= github.com/metacubex/nftables v0.0.0-20250503052935-30a69ab87793 h1:1Qpuy+sU3DmyX9HwI+CrBT/oLNJngvBorR2RbajJcqo= github.com/metacubex/nftables v0.0.0-20250503052935-30a69ab87793/go.mod h1:RjRNb4G52yAgfR+Oe/kp9G4PJJ97Fnj89eY1BFO3YyA= github.com/metacubex/quic-go v0.54.1-0.20250730114134-a1ae705fe295 h1:8JVlYuE8uSJAvmyCd4TjvDxs57xjb0WxEoaWafK5+qs= @@ -117,8 +117,8 @@ github.com/metacubex/randv2 v0.2.0/go.mod h1:kFi2SzrQ5WuneuoLLCMkABtiBu6VRrMrWFq github.com/metacubex/restls-client-go v0.1.7 h1:eCwiXCTQb5WJu9IlgYvDBA1OgrINv58dEe7hcN5H15k= github.com/metacubex/restls-client-go v0.1.7/go.mod h1:BN/U52vPw7j8VTSh2vleD/MnmVKCov84mS5VcjVHH4g= github.com/metacubex/sing v0.5.2/go.mod h1:ypf0mjwlZm0sKdQSY+yQvmsbWa0hNPtkeqyRMGgoN+w= -github.com/metacubex/sing v0.5.5 h1:m5U8iHvRAUxlme3FZlE/LPIGHjU8oMCUzXWGbQQAC1E= -github.com/metacubex/sing v0.5.5/go.mod h1:ypf0mjwlZm0sKdQSY+yQvmsbWa0hNPtkeqyRMGgoN+w= +github.com/metacubex/sing v0.5.6-0.20250826072929-f69b475e017b h1:ukK1IMo7LJ+VmPWQPIdoslHBv4Tr3E2zE34ilQCH2i4= +github.com/metacubex/sing v0.5.6-0.20250826072929-f69b475e017b/go.mod h1:ypf0mjwlZm0sKdQSY+yQvmsbWa0hNPtkeqyRMGgoN+w= github.com/metacubex/sing-mux v0.3.3-0.20250813083925-d7c9aeaeeaac h1:wDH/Jh/yqWbzPktqJP+Y1cUG8hchcrzKzUxJiSpnaQs= github.com/metacubex/sing-mux v0.3.3-0.20250813083925-d7c9aeaeeaac/go.mod h1:3rt1soewn0O6j89GCLmwAQFsq257u0jf2zQSPhTL3Bw= github.com/metacubex/sing-quic v0.0.0-20250718154553-1b193bec4cbb h1:U/m3h8lp/j7i8zFgfvScLdZa1/Y8dd74oO7iZaQq80s= @@ -129,8 +129,8 @@ github.com/metacubex/sing-shadowsocks2 v0.2.6 h1:ZR1kYT0f0Vi64iQSS09OdhFfppiNkh7 github.com/metacubex/sing-shadowsocks2 v0.2.6/go.mod h1:vOEbfKC60txi0ca+yUlqEwOGc3Obl6cnSgx9Gf45KjE= github.com/metacubex/sing-shadowtls v0.0.0-20250503063515-5d9f966d17a2 h1:gXU+MYPm7Wme3/OAY2FFzVq9d9GxPHOqu5AQfg/ddhI= github.com/metacubex/sing-shadowtls v0.0.0-20250503063515-5d9f966d17a2/go.mod h1:mbfboaXauKJNIHJYxQRa+NJs4JU9NZfkA+I33dS2+9E= -github.com/metacubex/sing-tun v0.4.7 h1:ZDY/W+1c7PeWWKeKRyUo18fySF/TWjB0i5ui81Ar778= -github.com/metacubex/sing-tun v0.4.7/go.mod h1:xHecZRwBnKWe6zG9amAK9cXf91lF6blgjBqm+VvOrmU= +github.com/metacubex/sing-tun v0.4.8-0.20250827085914-fc5681b9fc9f h1:1MV/pFn2vjnyvH/0u6sJST0kmaoZXgbUytCCfuelhl8= +github.com/metacubex/sing-tun v0.4.8-0.20250827085914-fc5681b9fc9f/go.mod h1:FQ9zXA+kVhdzqgFqeJdi/AUhJgUgw+SUXqrR++GvbnM= github.com/metacubex/sing-vmess v0.2.4-0.20250822020810-4856053566f0 h1:WZepq4TOZa6WewB8tGAZrrL+bL2R2ivoBzuEgAeolWc= github.com/metacubex/sing-vmess v0.2.4-0.20250822020810-4856053566f0/go.mod h1:21R5R1u90uUvBQF0owoooEu96/SAYYD56nDrwm6nFaM= github.com/metacubex/sing-wireguard v0.0.0-20250503063753-2dc62acc626f h1:Sr/DYKYofKHKc4GF3qkRGNuj6XA6c0eqPgEDN+VAsYU= diff --git a/listener/sing_tun/prepare.go b/listener/sing_tun/prepare.go new file mode 100644 index 00000000..b3e1e0b2 --- /dev/null +++ b/listener/sing_tun/prepare.go @@ -0,0 +1,34 @@ +package sing_tun + +import ( + "context" + "time" + + "github.com/metacubex/mihomo/component/dialer" + "github.com/metacubex/mihomo/component/resolver" + "github.com/metacubex/mihomo/log" + + tun "github.com/metacubex/sing-tun" + "github.com/metacubex/sing-tun/ping" + M "github.com/metacubex/sing/common/metadata" + N "github.com/metacubex/sing/common/network" +) + +func (h *ListenerHandler) PrepareConnection(network string, source M.Socksaddr, destination M.Socksaddr, routeContext tun.DirectRouteContext, timeout time.Duration) (tun.DirectRouteDestination, error) { + switch network { + case N.NetworkICMP: // our fork only send those type to PrepareConnection now + if resolver.IsFakeIP(destination.Addr) { // skip fakeip + log.Infoln("[ICMP] %s %s --> %s using fake ping echo", network, source, destination) + return nil, nil + } + log.Infoln("[ICMP] %s %s --> %s using DIRECT", network, source, destination) + directRouteDestination, err := ping.ConnectDestination(context.TODO(), log.SingLogger, dialer.ICMPControl(destination.Addr), destination.Addr, routeContext, timeout) + if err != nil { + log.Warnln("[ICMP] failed to connect to %s", destination) + return nil, err + } + log.Debugln("[ICMP] success connect to %s", destination) + return directRouteDestination, nil + } + return nil, nil +} diff --git a/listener/sing_tun/server.go b/listener/sing_tun/server.go index 416cf30c..6bee7ffc 100644 --- a/listener/sing_tun/server.go +++ b/listener/sing_tun/server.go @@ -11,6 +11,7 @@ import ( "strconv" "strings" "sync" + "time" "github.com/metacubex/mihomo/adapter/inbound" "github.com/metacubex/mihomo/component/dialer" @@ -174,11 +175,11 @@ func New(options LC.Tun, tunnel C.Tunnel, additions ...inbound.Addition) (l *Lis if tunMTU == 0 { tunMTU = 9000 } - var udpTimeout int64 + var udpTimeout time.Duration if options.UDPTimeout != 0 { - udpTimeout = options.UDPTimeout + udpTimeout = time.Second * time.Duration(options.UDPTimeout) } else { - udpTimeout = int64(sing.UDPTimeout.Seconds()) + udpTimeout = sing.UDPTimeout } tableIndex := options.IPRoute2TableIndex if tableIndex == 0 {