github.com/sagernet/sing-box@v1.9.0-rc.20/common/redir/redir_linux.go (about) 1 package redir 2 3 import ( 4 "encoding/binary" 5 "net" 6 "net/netip" 7 "os" 8 "syscall" 9 10 "github.com/sagernet/sing/common" 11 "github.com/sagernet/sing/common/control" 12 M "github.com/sagernet/sing/common/metadata" 13 ) 14 15 func GetOriginalDestination(conn net.Conn) (destination netip.AddrPort, err error) { 16 syscallConn, ok := common.Cast[syscall.Conn](conn) 17 if !ok { 18 return netip.AddrPort{}, os.ErrInvalid 19 } 20 err = control.Conn(syscallConn, func(fd uintptr) error { 21 const SO_ORIGINAL_DST = 80 22 if conn.RemoteAddr().(*net.TCPAddr).IP.To4() != nil { 23 raw, err := syscall.GetsockoptIPv6Mreq(int(fd), syscall.IPPROTO_IP, SO_ORIGINAL_DST) 24 if err != nil { 25 return err 26 } 27 destination = netip.AddrPortFrom(M.AddrFromIP(raw.Multiaddr[4:8]), uint16(raw.Multiaddr[2])<<8+uint16(raw.Multiaddr[3])) 28 } else { 29 raw, err := syscall.GetsockoptIPv6MTUInfo(int(fd), syscall.IPPROTO_IPV6, SO_ORIGINAL_DST) 30 if err != nil { 31 return err 32 } 33 var port [2]byte 34 binary.BigEndian.PutUint16(port[:], raw.Addr.Port) 35 destination = netip.AddrPortFrom(M.AddrFromIP(raw.Addr.Addr[:]), binary.LittleEndian.Uint16(port[:])) 36 } 37 return nil 38 }) 39 return 40 }