Browse Source

Fix tproxy tcp control

世界 5 months ago
parent
commit
d4f6bdf792

+ 3 - 0
common/listener/listener.go

@@ -32,6 +32,7 @@ type Listener struct {
 	disablePacketOutput      bool
 	disablePacketOutput      bool
 	setSystemProxy           bool
 	setSystemProxy           bool
 	systemProxySOCKS         bool
 	systemProxySOCKS         bool
+	tproxy                   bool
 
 
 	tcpListener          net.Listener
 	tcpListener          net.Listener
 	systemProxy          settings.SystemProxy
 	systemProxy          settings.SystemProxy
@@ -54,6 +55,7 @@ type Options struct {
 	DisablePacketOutput      bool
 	DisablePacketOutput      bool
 	SetSystemProxy           bool
 	SetSystemProxy           bool
 	SystemProxySOCKS         bool
 	SystemProxySOCKS         bool
+	TProxy                   bool
 }
 }
 
 
 func New(
 func New(
@@ -71,6 +73,7 @@ func New(
 		disablePacketOutput:      options.DisablePacketOutput,
 		disablePacketOutput:      options.DisablePacketOutput,
 		setSystemProxy:           options.SetSystemProxy,
 		setSystemProxy:           options.SetSystemProxy,
 		systemProxySOCKS:         options.SystemProxySOCKS,
 		systemProxySOCKS:         options.SystemProxySOCKS,
+		tproxy:                   options.TProxy,
 	}
 	}
 }
 }
 
 

+ 9 - 0
common/listener/listener_tcp.go

@@ -3,9 +3,11 @@ package listener
 import (
 import (
 	"net"
 	"net"
 	"net/netip"
 	"net/netip"
+	"syscall"
 	"time"
 	"time"
 
 
 	"github.com/sagernet/sing-box/adapter"
 	"github.com/sagernet/sing-box/adapter"
+	"github.com/sagernet/sing-box/common/redir"
 	C "github.com/sagernet/sing-box/constant"
 	C "github.com/sagernet/sing-box/constant"
 	"github.com/sagernet/sing-box/log"
 	"github.com/sagernet/sing-box/log"
 	"github.com/sagernet/sing/common/control"
 	"github.com/sagernet/sing/common/control"
@@ -51,6 +53,13 @@ func (l *Listener) ListenTCP() (net.Listener, error) {
 		}
 		}
 		setMultiPathTCP(&listenConfig)
 		setMultiPathTCP(&listenConfig)
 	}
 	}
+	if l.tproxy {
+		listenConfig.Control = control.Append(listenConfig.Control, func(network, address string, conn syscall.RawConn) error {
+			return control.Raw(conn, func(fd uintptr) error {
+				return redir.TProxy(fd, M.ParseSocksaddr(address).IsIPv6(), false)
+			})
+		})
+	}
 	tcpListener, err := ListenNetworkNamespace[net.Listener](l.listenOptions.NetNs, func() (net.Listener, error) {
 	tcpListener, err := ListenNetworkNamespace[net.Listener](l.listenOptions.NetNs, func() (net.Listener, error) {
 		if l.listenOptions.TCPFastOpen {
 		if l.listenOptions.TCPFastOpen {
 			var tfoConfig tfo.ListenConfig
 			var tfoConfig tfo.ListenConfig

+ 9 - 0
common/listener/listener_udp.go

@@ -5,8 +5,10 @@ import (
 	"net"
 	"net"
 	"net/netip"
 	"net/netip"
 	"os"
 	"os"
+	"syscall"
 
 
 	"github.com/sagernet/sing-box/adapter"
 	"github.com/sagernet/sing-box/adapter"
+	"github.com/sagernet/sing-box/common/redir"
 	"github.com/sagernet/sing/common/buf"
 	"github.com/sagernet/sing/common/buf"
 	"github.com/sagernet/sing/common/control"
 	"github.com/sagernet/sing/common/control"
 	E "github.com/sagernet/sing/common/exceptions"
 	E "github.com/sagernet/sing/common/exceptions"
@@ -36,6 +38,13 @@ func (l *Listener) ListenUDP() (net.PacketConn, error) {
 	if !udpFragment {
 	if !udpFragment {
 		listenConfig.Control = control.Append(listenConfig.Control, control.DisableUDPFragment())
 		listenConfig.Control = control.Append(listenConfig.Control, control.DisableUDPFragment())
 	}
 	}
+	if l.tproxy {
+		listenConfig.Control = control.Append(listenConfig.Control, func(network, address string, conn syscall.RawConn) error {
+			return control.Raw(conn, func(fd uintptr) error {
+				return redir.TProxy(fd, M.ParseSocksaddr(address).IsIPv6(), true)
+			})
+		})
+	}
 	udpConn, err := ListenNetworkNamespace[net.PacketConn](l.listenOptions.NetNs, func() (net.PacketConn, error) {
 	udpConn, err := ListenNetworkNamespace[net.PacketConn](l.listenOptions.NetNs, func() (net.PacketConn, error) {
 		return listenConfig.ListenPacket(l.ctx, M.NetworkFromNetAddr(N.NetworkUDP, bindAddr.Addr), bindAddr.String())
 		return listenConfig.ListenPacket(l.ctx, M.NetworkFromNetAddr(N.NetworkUDP, bindAddr.Addr), bindAddr.String())
 	})
 	})

+ 8 - 6
common/redir/tproxy_linux.go

@@ -12,7 +12,7 @@ import (
 	"golang.org/x/sys/unix"
 	"golang.org/x/sys/unix"
 )
 )
 
 
-func TProxy(fd uintptr, isIPv6 bool) error {
+func TProxy(fd uintptr, isIPv6 bool, isUDP bool) error {
 	err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1)
 	err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1)
 	if err == nil {
 	if err == nil {
 		err = syscall.SetsockoptInt(int(fd), syscall.SOL_IP, syscall.IP_TRANSPARENT, 1)
 		err = syscall.SetsockoptInt(int(fd), syscall.SOL_IP, syscall.IP_TRANSPARENT, 1)
@@ -20,11 +20,13 @@ func TProxy(fd uintptr, isIPv6 bool) error {
 	if err == nil && isIPv6 {
 	if err == nil && isIPv6 {
 		err = syscall.SetsockoptInt(int(fd), syscall.SOL_IPV6, unix.IPV6_TRANSPARENT, 1)
 		err = syscall.SetsockoptInt(int(fd), syscall.SOL_IPV6, unix.IPV6_TRANSPARENT, 1)
 	}
 	}
-	if err == nil {
-		err = syscall.SetsockoptInt(int(fd), syscall.SOL_IP, syscall.IP_RECVORIGDSTADDR, 1)
-	}
-	if err == nil && isIPv6 {
-		err = syscall.SetsockoptInt(int(fd), syscall.SOL_IPV6, unix.IPV6_RECVORIGDSTADDR, 1)
+	if isUDP {
+		if err == nil {
+			err = syscall.SetsockoptInt(int(fd), syscall.SOL_IP, syscall.IP_RECVORIGDSTADDR, 1)
+		}
+		if err == nil && isIPv6 {
+			err = syscall.SetsockoptInt(int(fd), syscall.SOL_IPV6, unix.IPV6_RECVORIGDSTADDR, 1)
+		}
 	}
 	}
 	return err
 	return err
 }
 }

+ 1 - 1
common/redir/tproxy_other.go

@@ -9,7 +9,7 @@ import (
 	"github.com/sagernet/sing/common/control"
 	"github.com/sagernet/sing/common/control"
 )
 )
 
 
-func TProxy(fd uintptr, isIPv6 bool) error {
+func TProxy(fd uintptr, isIPv6 bool, isUDP bool) error {
 	return os.ErrInvalid
 	return os.ErrInvalid
 }
 }
 
 

+ 6 - 27
protocol/redirect/tproxy.go

@@ -4,7 +4,6 @@ import (
 	"context"
 	"context"
 	"net"
 	"net"
 	"net/netip"
 	"net/netip"
-	"syscall"
 	"time"
 	"time"
 
 
 	"github.com/sagernet/sing-box/adapter"
 	"github.com/sagernet/sing-box/adapter"
@@ -17,7 +16,6 @@ import (
 	"github.com/sagernet/sing/common"
 	"github.com/sagernet/sing/common"
 	"github.com/sagernet/sing/common/buf"
 	"github.com/sagernet/sing/common/buf"
 	"github.com/sagernet/sing/common/control"
 	"github.com/sagernet/sing/common/control"
-	E "github.com/sagernet/sing/common/exceptions"
 	M "github.com/sagernet/sing/common/metadata"
 	M "github.com/sagernet/sing/common/metadata"
 	N "github.com/sagernet/sing/common/network"
 	N "github.com/sagernet/sing/common/network"
 	"github.com/sagernet/sing/common/udpnat2"
 	"github.com/sagernet/sing/common/udpnat2"
@@ -57,6 +55,7 @@ func NewTProxy(ctx context.Context, router adapter.Router, logger log.ContextLog
 		Listen:            options.ListenOptions,
 		Listen:            options.ListenOptions,
 		ConnectionHandler: tproxy,
 		ConnectionHandler: tproxy,
 		OOBPacketHandler:  tproxy,
 		OOBPacketHandler:  tproxy,
+		TProxy:            true,
 	})
 	})
 	return tproxy, nil
 	return tproxy, nil
 }
 }
@@ -65,27 +64,7 @@ func (t *TProxy) Start(stage adapter.StartStage) error {
 	if stage != adapter.StartStateStart {
 	if stage != adapter.StartStateStart {
 		return nil
 		return nil
 	}
 	}
-	err := t.listener.Start()
-	if err != nil {
-		return err
-	}
-	if listener := t.listener.TCPListener(); listener != nil {
-		err = control.Conn(common.MustCast[syscall.Conn](listener), func(fd uintptr) error {
-			return redir.TProxy(fd, M.SocksaddrFromNet(listener.Addr()).Addr.Is6())
-		})
-		if err != nil {
-			return E.Cause(err, "configure tproxy TCP listener")
-		}
-	}
-	if conn := t.listener.UDPConn(); conn != nil {
-		err = control.Conn(conn, func(fd uintptr) error {
-			return redir.TProxy(fd, M.SocksaddrFromNet(conn.LocalAddr()).Addr.Is6())
-		})
-		if err != nil {
-			return E.Cause(err, "configure tproxy UDP listener")
-		}
-	}
-	return nil
+	return t.listener.Start()
 }
 }
 
 
 func (t *TProxy) Close() error {
 func (t *TProxy) Close() error {
@@ -154,10 +133,10 @@ func (w *tproxyPacketWriter) WritePacket(buffer *buf.Buffer, destination M.Socks
 			return err
 			return err
 		}
 		}
 	}
 	}
-	var listener net.ListenConfig
-	listener.Control = control.Append(listener.Control, control.ReuseAddr())
-	listener.Control = control.Append(listener.Control, redir.TProxyWriteBack())
-	packetConn, err := w.listener.ListenPacket(listener, w.ctx, "udp", destination.String())
+	var listenConfig net.ListenConfig
+	listenConfig.Control = control.Append(listenConfig.Control, control.ReuseAddr())
+	listenConfig.Control = control.Append(listenConfig.Control, redir.TProxyWriteBack())
+	packetConn, err := w.listener.ListenPacket(listenConfig, w.ctx, "udp", destination.String())
 	if err != nil {
 	if err != nil {
 		return err
 		return err
 	}
 	}