github.com/inazumav/sing-box@v0.0.0-20230926072359-ab51429a14f1/common/redir/tproxy_linux.go (about) 1 package redir 2 3 import ( 4 "encoding/binary" 5 "net/netip" 6 "syscall" 7 8 "github.com/sagernet/sing/common/control" 9 E "github.com/sagernet/sing/common/exceptions" 10 M "github.com/sagernet/sing/common/metadata" 11 12 "golang.org/x/sys/unix" 13 ) 14 15 func TProxy(fd uintptr, isIPv6 bool) error { 16 err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1) 17 if err == nil { 18 err = syscall.SetsockoptInt(int(fd), syscall.SOL_IP, syscall.IP_TRANSPARENT, 1) 19 } 20 if err == nil && isIPv6 { 21 err = syscall.SetsockoptInt(int(fd), syscall.SOL_IPV6, unix.IPV6_TRANSPARENT, 1) 22 } 23 if err == nil { 24 err = syscall.SetsockoptInt(int(fd), syscall.SOL_IP, syscall.IP_RECVORIGDSTADDR, 1) 25 } 26 if err == nil && isIPv6 { 27 err = syscall.SetsockoptInt(int(fd), syscall.SOL_IPV6, unix.IPV6_RECVORIGDSTADDR, 1) 28 } 29 return err 30 } 31 32 func TProxyWriteBack() control.Func { 33 return func(network, address string, conn syscall.RawConn) error { 34 return control.Raw(conn, func(fd uintptr) error { 35 if M.ParseSocksaddr(address).Addr.Is6() { 36 return syscall.SetsockoptInt(int(fd), syscall.SOL_IPV6, unix.IPV6_TRANSPARENT, 1) 37 } else { 38 return syscall.SetsockoptInt(int(fd), syscall.SOL_IP, syscall.IP_TRANSPARENT, 1) 39 } 40 }) 41 } 42 } 43 44 func GetOriginalDestinationFromOOB(oob []byte) (netip.AddrPort, error) { 45 controlMessages, err := unix.ParseSocketControlMessage(oob) 46 if err != nil { 47 return netip.AddrPort{}, err 48 } 49 for _, message := range controlMessages { 50 if message.Header.Level == unix.SOL_IP && message.Header.Type == unix.IP_RECVORIGDSTADDR { 51 return netip.AddrPortFrom(M.AddrFromIP(message.Data[4:8]), binary.BigEndian.Uint16(message.Data[2:4])), nil 52 } else if message.Header.Level == unix.SOL_IPV6 && message.Header.Type == unix.IPV6_RECVORIGDSTADDR { 53 return netip.AddrPortFrom(M.AddrFromIP(message.Data[8:24]), binary.BigEndian.Uint16(message.Data[2:4])), nil 54 } 55 } 56 return netip.AddrPort{}, E.New("not found") 57 }