From 5f851c05b14a1adf3240f6be0d73c39e5c146162 Mon Sep 17 00:00:00 2001 From: mzz Date: Thu, 25 Mar 2021 16:42:58 +0800 Subject: [PATCH] fix(tproxy): the problem that cannot find ipv6 destination in redirect mode of tproxy (#815) * fix(tproxy): the problem that cannot find ipv6 destination in redirect mode of tproxy * chore(lint): reformat the code * chore(lint): Codacy Static Code Analysis --- transport/internet/tcp/sockopt_linux.go | 35 ++++++++++++++++++++----- 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/transport/internet/tcp/sockopt_linux.go b/transport/internet/tcp/sockopt_linux.go index c7c44b5b2..1af96960a 100644 --- a/transport/internet/tcp/sockopt_linux.go +++ b/transport/internet/tcp/sockopt_linux.go @@ -23,14 +23,37 @@ func GetOriginalDestination(conn internet.Connection) (net.Destination, error) { } var dest net.Destination err = rawConn.Control(func(fd uintptr) { - addr, err := syscall.GetsockoptIPv6Mreq(int(fd), syscall.IPPROTO_IP, SO_ORIGINAL_DST) - if err != nil { - newError("failed to call getsockopt").Base(err).WriteToLog() + var remoteIP net.IP + switch addr := conn.RemoteAddr().(type) { + case *net.TCPAddr: + remoteIP = addr.IP + case *net.UDPAddr: + remoteIP = addr.IP + default: + newError("failed to call getsockopt").WriteToLog() return } - ip := net.IPAddress(addr.Multiaddr[4:8]) - port := uint16(addr.Multiaddr[2])<<8 + uint16(addr.Multiaddr[3]) - dest = net.TCPDestination(ip, net.Port(port)) + if remoteIP.To4() != nil { + // ipv4 + addr, err := syscall.GetsockoptIPv6Mreq(int(fd), syscall.IPPROTO_IP, SO_ORIGINAL_DST) + if err != nil { + newError("failed to call getsockopt").Base(err).WriteToLog() + return + } + ip := net.IPAddress(addr.Multiaddr[4:8]) + port := uint16(addr.Multiaddr[2])<<8 + uint16(addr.Multiaddr[3]) + dest = net.TCPDestination(ip, net.Port(port)) + } else { + // ipv6 + addr, err := syscall.GetsockoptIPv6MTUInfo(int(fd), syscall.IPPROTO_IPV6, SO_ORIGINAL_DST) + if err != nil { + newError("failed to call getsockopt").Base(err).WriteToLog() + return + } + ip := net.IPAddress(addr.Addr.Addr[:]) + port := net.PortFromBytes([]byte{byte(addr.Addr.Port), byte(addr.Addr.Port >> 8)}) + dest = net.TCPDestination(ip, port) + } }) if err != nil { return net.Destination{}, newError("failed to control connection").Base(err)