From e43c60b56401be7515d7fbfdfe3e4e56d1886a23 Mon Sep 17 00:00:00 2001 From: Mikhail Osipov Date: Tue, 26 May 2020 03:22:32 +0300 Subject: add tproxy listen option --- pkg/server/socket/sys.go | 44 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 41 insertions(+), 3 deletions(-) (limited to 'pkg/server/socket/sys.go') diff --git a/pkg/server/socket/sys.go b/pkg/server/socket/sys.go index d09df12..70b59a6 100644 --- a/pkg/server/socket/sys.go +++ b/pkg/server/socket/sys.go @@ -47,16 +47,18 @@ func ioctl(fd int, req int, ptr unsafe.Pointer) error { return nil } -func getRawConn(conn net.Conn) (syscall.RawConn, error) { +func getRawConn(conn interface{}) (syscall.RawConn, error) { switch c := conn.(type) { case *net.TCPConn: return c.SyscallConn() + case *net.TCPListener: + return c.SyscallConn() default: return nil, errors.New("unknown connection type") } } -func withConnControl(conn net.Conn, f func(fd int) error) (err error) { +func withConnControl(conn interface{}, f func(fd int) error) (err error) { var c syscall.RawConn var ferr error @@ -75,12 +77,16 @@ func withConnControl(conn net.Conn, f func(fd int) error) (err error) { return } +func getSocketDomain(fd int) (int, error) { + return unix.GetsockoptInt(fd, unix.SOL_SOCKET, unix.SO_DOMAIN) +} + func getSocketOriginalDst(fd int, sa *unix.RawSockaddrAny) error { const SO_ORIGINAL_DST = 80 p, n := unsafe.Pointer(sa), int(unsafe.Sizeof(*sa)) - family, err := unix.GetsockoptInt(fd, unix.SOL_SOCKET, unix.SO_DOMAIN) + family, err := getSocketDomain(fd) if err != nil { return err } @@ -129,3 +135,35 @@ func getConnOriginalAddr(conn net.Conn, addr *string) error { return nil } + +func setSocketTransparent(fd int) error { + family, err := getSocketDomain(fd) + if err != nil { + return err + } + + var level, opt int + + switch family { + case unix.AF_INET6: + level, opt = unix.SOL_IPV6, unix.IPV6_TRANSPARENT + case unix.AF_INET: + level, opt = unix.SOL_IP, unix.IP_TRANSPARENT + default: + return errors.New("unknown address family") + } + + return unix.SetsockoptInt(fd, level, opt, 1) +} + +func setConnTransparent(conn interface{}) error { + f := func(fd int) error { + return setSocketTransparent(fd) + } + + if err := withConnControl(conn, f); err != nil { + return fmt.Errorf("set-transparent: %w", err) + } + + return nil +} -- cgit v1.2.3-70-g09d2