/
proxy_linux.go
65 lines (55 loc) · 1.36 KB
/
proxy_linux.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
package netx
import (
"net"
"os"
"syscall"
"unsafe"
)
func originalTargetAddr(conn net.Conn) (n *net.TCPAddr, err error) {
const (
SO_ORIGINAL_DST = 80 // missing from the syscall package
)
// Calling conn.File will put the socket in blocking mode, we make sure to
// set it back to non-blocking before returning to prevent the runtime from
// creating tons of threads because it deals with blocking syscalls all over
// the place.
var f *os.File
if f, err = BaseConn(conn).(fileConn).File(); err != nil {
return
}
defer f.Close()
defer syscall.SetNonblock(int(f.Fd()), true)
sock := f.Fd()
addr := syscall.RawSockaddrAny{}
size := uint32(unsafe.Sizeof(addr))
_, _, e := syscall.RawSyscall6(
uintptr(syscall.SYS_GETSOCKOPT),
uintptr(sock),
uintptr(syscall.SOL_IP),
uintptr(SO_ORIGINAL_DST),
uintptr(unsafe.Pointer(&addr)),
uintptr(unsafe.Pointer(&size)),
uintptr(0),
)
if e != 0 {
err = e
return
}
switch addr.Addr.Family {
case syscall.AF_INET:
a := (*syscall.RawSockaddrInet4)(unsafe.Pointer(&addr))
n = &net.TCPAddr{
IP: net.IP(a.Addr[:]),
Port: int((a.Port >> 8) | (a.Port << 8)),
}
case syscall.AF_INET6:
a := (*syscall.RawSockaddrInet6)(unsafe.Pointer(&addr))
n = &net.TCPAddr{
IP: net.IP(a.Addr[:]),
Port: int((a.Port >> 8) | (a.Port << 8)),
}
default:
err = syscall.EAFNOSUPPORT
}
return
}