diff --git a/transport/internet/tcp/sockopt_linux.go b/transport/internet/tcp/sockopt_linux.go index 10b88d209..5c3a2565d 100644 --- a/transport/internet/tcp/sockopt_linux.go +++ b/transport/internet/tcp/sockopt_linux.go @@ -3,27 +3,35 @@ package tcp import ( - "net" "syscall" v2net "v2ray.com/core/common/net" "v2ray.com/core/transport/internet" - "v2ray.com/core/transport/internet/internal" ) const SO_ORIGINAL_DST = 80 func GetOriginalDestination(conn internet.Connection) (v2net.Destination, error) { - fd, err := internal.GetSysFd(conn.(net.Conn)) + sysrawconn, f := conn.(syscall.Conn) + if !f { + return v2net.Destination{}, newError("unable to get syscall.Conn") + } + rawConn, err := sysrawconn.SyscallConn() + if err != nil { + return v2net.Destination{}, newError("failed to get sys fd").Base(err) + } + var dest v2net.Destination + err := rawConn.Control(func(fd uintptr) { + addr, err := syscall.GetsockoptIPv6Mreq(int(fd), syscall.IPPROTO_IP, SO_ORIGINAL_DST) + if err != nil { + return v2net.Destination{}, newError("failed to call getsockopt").Base(err) + } + ip := v2net.IPAddress(addr.Multiaddr[4:8]) + port := uint16(addr.Multiaddr[2])<<8 + uint16(addr.Multiaddr[3]) + addr = v2net.TCPDestination(ip, v2net.Port(port)) + }) if err != nil { return v2net.Destination{}, newError("failed to get original destination").Base(err) } - - addr, err := syscall.GetsockoptIPv6Mreq(fd, syscall.IPPROTO_IP, SO_ORIGINAL_DST) - if err != nil { - return v2net.Destination{}, newError("failed to call getsockopt").Base(err) - } - ip := v2net.IPAddress(addr.Multiaddr[4:8]) - port := uint16(addr.Multiaddr[2])<<8 + uint16(addr.Multiaddr[3]) - return v2net.TCPDestination(ip, v2net.Port(port)), nil + return dest, nil } diff --git a/transport/internet/udp/hub_linux_test.go b/transport/internet/udp/hub_linux_test.go deleted file mode 100644 index 042bf476c..000000000 --- a/transport/internet/udp/hub_linux_test.go +++ /dev/null @@ -1,41 +0,0 @@ -// +build linux - -package udp_test - -import ( - "os" - "syscall" - "testing" - - "v2ray.com/core/common/buf" - v2net "v2ray.com/core/common/net" - "v2ray.com/core/testing/assert" - "v2ray.com/core/transport/internet/internal" - . "v2ray.com/core/transport/internet/udp" -) - -func TestHubSocksOption(t *testing.T) { - assert := assert.On(t) - if os.Geteuid() != 0 { - // This test case requires root permission. - return - } - - hub, err := ListenUDP(v2net.LocalHostIP, v2net.Port(0), ListenOption{ - Callback: func(*buf.Buffer, v2net.Destination, v2net.Destination) {}, - ReceiveOriginalDest: true, - }) - assert.Error(err).IsNil() - conn := hub.Connection() - - fd, err := internal.GetSysFd(conn) - assert.Error(err).IsNil() - - val, err := syscall.GetsockoptInt(fd, syscall.SOL_IP, syscall.IP_TRANSPARENT) - assert.Error(err).IsNil() - assert.Int(val).Equals(1) - - val, err = syscall.GetsockoptInt(fd, syscall.SOL_IP, syscall.IP_RECVORIGDSTADDR) - assert.Error(err).IsNil() - assert.Int(val).Equals(1) -}