Skip to content

Commit

Permalink
Fixed redir on Linux x86
Browse files Browse the repository at this point in the history
  • Loading branch information
riobard committed Feb 13, 2017
1 parent 3e9aaf3 commit 56421fc
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 6 deletions.
15 changes: 9 additions & 6 deletions tcp_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ import (
"github.com/riobard/go-shadowsocks2/socks"
)

const (
SO_ORIGINAL_DST = 80 // from linux/include/uapi/linux/netfilter_ipv4.h
IP6T_SO_ORIGINAL_DST = 80 // from linux/include/uapi/linux/netfilter_ipv6/ip6_tables.h
)

// Listen on addr for netfilter redirected TCP connections
func redirLocal(addr, server string, ciph core.StreamConnCipher) {
logf("TCP redirect %s <-> %s", addr, server)
Expand Down Expand Up @@ -52,11 +57,10 @@ func getOrigDst(conn net.Conn, ipv6 bool) (socks.Addr, error) {

// Call getorigdst() from linux/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
func getorigdst(fd uintptr) (socks.Addr, error) {
const SO_ORIGINAL_DST = 80 // from linux/include/uapi/linux/netfilter_ipv4.h
raw := syscall.RawSockaddrInet4{}
siz := unsafe.Sizeof(raw)
if _, _, errno := syscall.Syscall6(syscall.SYS_GETSOCKOPT, fd, syscall.IPPROTO_IP, SO_ORIGINAL_DST, uintptr(unsafe.Pointer(&raw)), uintptr(unsafe.Pointer(&siz)), 0); errno != 0 {
return nil, errno
if err := socketcall(GETSOCKOPT, fd, syscall.IPPROTO_IP, SO_ORIGINAL_DST, uintptr(unsafe.Pointer(&raw)), uintptr(unsafe.Pointer(&siz)), 0); err != nil {
return nil, err
}

addr := make([]byte, 1+net.IPv4len+2)
Expand All @@ -70,11 +74,10 @@ func getorigdst(fd uintptr) (socks.Addr, error) {
// Call ipv6_getorigdst() from linux/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
// NOTE: I haven't tried yet but it should work since Linux 3.8.
func ipv6_getorigdst(fd uintptr) (socks.Addr, error) {
const IP6T_SO_ORIGINAL_DST = 80 // from linux/include/uapi/linux/netfilter_ipv6/ip6_tables.h
raw := syscall.RawSockaddrInet6{}
siz := unsafe.Sizeof(raw)
if _, _, errno := syscall.Syscall6(syscall.SYS_GETSOCKOPT, fd, syscall.IPPROTO_IPV6, IP6T_SO_ORIGINAL_DST, uintptr(unsafe.Pointer(&raw)), uintptr(unsafe.Pointer(&siz)), 0); errno != 0 {
return nil, errno
if err := socketcall(GETSOCKOPT, fd, syscall.IPPROTO_IPV6, IP6T_SO_ORIGINAL_DST, uintptr(unsafe.Pointer(&raw)), uintptr(unsafe.Pointer(&siz)), 0); err != nil {
return nil, err
}

addr := make([]byte, 1+net.IPv6len+2)
Expand Down
17 changes: 17 additions & 0 deletions tcp_linux_386.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package main

import (
"syscall"
"unsafe"
)

const GETSOCKOPT = 15 // https://golang.org/src/syscall/syscall_linux_386.go#L183

func socketcall(call, a0, a1, a2, a3, a4, a5 uintptr) error {
var a [6]uintptr
a[0], a[1], a[2], a[3], a[4], a[5] = a0, a1, a2, a3, a4, a5
if _, _, errno := syscall.Syscall6(syscall.SYS_SOCKETCALL, call, uintptr(unsafe.Pointer(&a)), 0, 0, 0, 0); errno != 0 {
return errno
}
return nil
}
14 changes: 14 additions & 0 deletions tcp_linux_other.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// +build linux,!386

package main

import "syscall"

const GETSOCKOPT = syscall.SYS_GETSOCKOPT

func socketcall(call, a0, a1, a2, a3, a4, a5 uintptr) error {
if _, _, errno := syscall.Syscall6(call, a0, a1, a2, a3, a4, a5); errno != 0 {
return errno
}
return nil
}

0 comments on commit 56421fc

Please sign in to comment.