diff --git a/redir_iptables.go b/redir_iptables.go index ccf641c..23c1fef 100644 --- a/redir_iptables.go +++ b/redir_iptables.go @@ -1,4 +1,4 @@ -// +build linux +// +build linux,!cgo package obfssh diff --git a/redir_iptables_2.go b/redir_iptables_2.go new file mode 100644 index 0000000..6a2abb5 --- /dev/null +++ b/redir_iptables_2.go @@ -0,0 +1,108 @@ +// +build linux,cgo + +package obfssh + +/* +#include +#include +#include +#include +#include +#include +#include + +int get_original_dst4(int fd, void *addr); +int get_original_dst6(int fd, void *addr); + +unsigned short _ntohs(unsigned short a); + +int get_original_dst4(int fd, void *addr){ + int ret; + int l = sizeof(struct sockaddr_in); + ret = getsockopt(fd, SOL_IP, SO_ORIGINAL_DST, + (struct sockaddr_in *)addr, &l); + return ret; +} + +int get_original_dst6(int fd, void *addr){ + int ret; + int l = sizeof(struct sockaddr_in6); + ret = getsockopt(fd, SOL_IPV6, IP6T_SO_ORIGINAL_DST, + (struct sockaddr_in6 *)addr, &l); + return ret; +} + +unsigned short _ntohs(unsigned short a) { + return ntohs(a); +} + +*/ +import "C" + +import ( + "fmt" + //"log" + "net" + "syscall" + "unsafe" +) + +func getOriginDst(c net.Conn) (net.Addr, error) { + var addr net.Addr + var err error + + if _, ok := c.(*net.TCPConn); !ok { + return nil, fmt.Errorf("only tcp socket supported") + } + + ip := c.LocalAddr().(*net.TCPAddr).IP + + if ip.To4() != nil { // ipv4 + addr, err = getOriginDst4(c) + } else { + addr, err = getOriginDst6(c) + } + return addr, err +} + +func getOriginDst4(c net.Conn) (net.Addr, error) { + + c1 := c.(*net.TCPConn) + + f, _ := c1.File() + + defer f.Close() + + var addr4 syscall.RawSockaddrInet4 + + ret := C.get_original_dst4(C.int(f.Fd()), unsafe.Pointer(&addr4)) + if int(ret) != 0 { + return nil, fmt.Errorf("ipv4 getsockopt SO_ORIGINAL_DST return %v", int(ret)) + } + + port := int(C._ntohs(C.ushort(addr4.Port))) + ip := net.IP(addr4.Addr[0:]) + + return &net.TCPAddr{IP: ip, Port: port}, nil +} + +func getOriginDst6(c net.Conn) (net.Addr, error) { + + c1 := c.(*net.TCPConn) + + f, _ := c1.File() + + defer f.Close() + + var addr6 syscall.RawSockaddrInet6 + + ret := C.get_original_dst6(C.int(f.Fd()), unsafe.Pointer(&addr6)) + if int(ret) != 0 { + return nil, fmt.Errorf("ipv6 getsockopt IP6T_ORIGINAL_DST return %v", int(ret)) + } + + port := int(C._ntohs(C.ushort(addr6.Port))) + ip := net.IP(addr6.Addr[0:]) + + return &net.TCPAddr{IP: ip, Port: port}, nil +}