From 9d838d25e69c7eafadd4d37bb1b5378637feedf3 Mon Sep 17 00:00:00 2001 From: coyove Date: Mon, 1 Jan 2018 16:09:20 +0800 Subject: [PATCH] Split sources --- proxy/httpmux.go | 85 ---------------------------------------- proxy/ssvpn_interop.go | 88 ++++++++++++++++++++++++++++++++++++++++++ proxy/ssvpn_windows.go | 7 ++++ 3 files changed, 95 insertions(+), 85 deletions(-) create mode 100644 proxy/ssvpn_interop.go create mode 100644 proxy/ssvpn_windows.go diff --git a/proxy/httpmux.go b/proxy/httpmux.go index b46f384..0f4b99a 100644 --- a/proxy/httpmux.go +++ b/proxy/httpmux.go @@ -1,14 +1,8 @@ package proxy import ( - "encoding/binary" - "errors" - "strconv" - "syscall" "time" - "unsafe" - "github.com/coyove/goflyway/pkg/fd" "github.com/coyove/goflyway/pkg/logg" "github.com/coyove/tcpmux" @@ -59,82 +53,3 @@ CONTINUE: return wrapper, err } } - -func vpnDial(address string) (net.Conn, error) { - sock, err := fd.Socket(syscall.AF_INET) - if err != nil { - return nil, err - } - - if err := protectFD(sock); err != nil { - return nil, err - } - - return fd.DialWithFD(sock, address) -} - -func protectFD(fd int) error { - sock, err := syscall.Socket(syscall.AF_UNIX, syscall.SOCK_STREAM, 0) - if err != nil { - return err - } - - var addr syscall.SockaddrUnix - addr.Name = "protect_path" - - if err := (syscall.Connect(sock, &addr)); err != nil { - return err - } - - if err := sendFD(sock, fd); err != nil { - return err - } - - ret := []byte{9} - if n, err := syscall.Read(sock, ret); err != nil { - return err - } else if n != 1 { - return errors.New("protecting failed") - } - - syscall.Close(sock) - - if ret[0] != 0 { - return errors.New("protecting failed") - } - - return nil -} - -var _int_value_one int = 1 -var _little_endian = *(*byte)(unsafe.Pointer(&_int_value_one)) == 1 - -func sendFD(sock int, fd int) error { - cmsg := &syscall.Cmsghdr{ - Level: syscall.SOL_SOCKET, - Type: syscall.SCM_RIGHTS, - } - - // cmsghdr.len may be uint64 or uint32, depending on the platform - ln := syscall.SizeofCmsghdr + strconv.IntSize/8 - h := (*[8]byte)(unsafe.Pointer(&cmsg.Len)) - - if _little_endian { - h[0] = byte(ln) - } else { - var i interface{} = cmsg.Len - switch i.(type) { - case uint64: - binary.BigEndian.PutUint64(h[:8], uint64(ln)) - case uint32: - binary.BigEndian.PutUint32(h[:4], uint32(ln)) - } - } - - buffer := make([]byte, cmsg.Len) - - copy(buffer, (*[syscall.SizeofCmsghdr]byte)(unsafe.Pointer(cmsg))[:]) - *(*int)(unsafe.Pointer(&buffer[syscall.SizeofCmsghdr])) = fd - - return syscall.Sendmsg(sock, []byte{'!'}, buffer, nil, 0) -} diff --git a/proxy/ssvpn_interop.go b/proxy/ssvpn_interop.go new file mode 100644 index 0000000..8f9e53e --- /dev/null +++ b/proxy/ssvpn_interop.go @@ -0,0 +1,88 @@ +// +build darwin dragonfly freebsd linux netbsd openbsd solaris + +package proxy + +import ( + "errors" + "net" + "strconv" + "syscall" + "unsafe" + + "github.com/coyove/goflyway/pkg/fd" +) + +func vpnDial(address string) (net.Conn, error) { + sock, err := fd.Socket(syscall.AF_INET) + if err != nil { + return nil, err + } + + // Send our conn fd to shadowsocks vpn thread for protection + if err := protectFD(sock); err != nil { + return nil, err + } + + // If succeeded, this fd will be closed while we still need it. + // So we dial a new conn, replace its fd with this one + return fd.DialWithFD(sock, address) +} + +func protectFD(fd int) error { + sock, err := syscall.Socket(syscall.AF_UNIX, syscall.SOCK_STREAM, 0) + if err != nil { + return err + } + + var addr syscall.SockaddrUnix + addr.Name = "protect_path" + + if err := (syscall.Connect(sock, &addr)); err != nil { + return err + } + + if err := sendFD(sock, fd); err != nil { + return err + } + + ret := []byte{9} + if n, err := syscall.Read(sock, ret); err != nil { + return err + } else if n != 1 { + return errors.New("protecting failed") + } + + syscall.Close(sock) + + if ret[0] != 0 { + return errors.New("protecting failed") + } + + return nil +} + +var _int_value_one int = 1 +var _little_endian = *(*byte)(unsafe.Pointer(&_int_value_one)) == 1 + +func sendFD(sock int, fd int) error { + cmsg := &syscall.Cmsghdr{ + Level: syscall.SOL_SOCKET, + Type: syscall.SCM_RIGHTS, + } + + ln := byte(syscall.SizeofCmsghdr + strconv.IntSize/8) + h := (*[8]byte)(unsafe.Pointer(&cmsg.Len)) + + if _little_endian { + h[0] = ln + } else { + h[3+4*(^cmsg.Len<<32>>63)] = ln + } + + buffer := make([]byte, cmsg.Len) + + copy(buffer, (*[syscall.SizeofCmsghdr]byte)(unsafe.Pointer(cmsg))[:]) + *(*int)(unsafe.Pointer(&buffer[syscall.SizeofCmsghdr])) = fd + + return syscall.Sendmsg(sock, []byte{'!'}, buffer, nil, 0) +} diff --git a/proxy/ssvpn_windows.go b/proxy/ssvpn_windows.go new file mode 100644 index 0000000..c2f8748 --- /dev/null +++ b/proxy/ssvpn_windows.go @@ -0,0 +1,7 @@ +package proxy + +import "net" + +func vpnDial(address string) (net.Conn, error) { + panic("not on Windows") +}