From 5a9c2b1e80d77b969a96eaa922ddad58aca85540 Mon Sep 17 00:00:00 2001 From: dyhkwong <50692134+dyhkwong@users.noreply.github.com> Date: Wed, 31 Aug 2022 14:21:37 +0800 Subject: [PATCH] darwin pf support (#52) --- common/redir/redir_darwin.go | 64 ++++++++++++++++++++++++++++++++++++ common/redir/redir_other.go | 2 +- 2 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 common/redir/redir_darwin.go diff --git a/common/redir/redir_darwin.go b/common/redir/redir_darwin.go new file mode 100644 index 00000000..d8691234 --- /dev/null +++ b/common/redir/redir_darwin.go @@ -0,0 +1,64 @@ +package redir + +import ( + "net" + "net/netip" + "syscall" + "unsafe" + + M "github.com/sagernet/sing/common/metadata" +) + +const ( + PF_OUT = 0x2 + DIOCNATLOOK = 0xc0544417 +) + +func GetOriginalDestination(conn net.Conn) (destination netip.AddrPort, err error) { + fd, err := syscall.Open("/dev/pf", 0, syscall.O_RDONLY) + if err != nil { + return netip.AddrPort{}, err + } + defer syscall.Close(fd) + nl := struct { + saddr, daddr, rsaddr, rdaddr [16]byte + sxport, dxport, rsxport, rdxport [4]byte + af, proto, protoVariant, direction uint8 + }{ + af: syscall.AF_INET, + proto: syscall.IPPROTO_TCP, + direction: PF_OUT, + } + la := conn.LocalAddr().(*net.TCPAddr) + ra := conn.RemoteAddr().(*net.TCPAddr) + raIP, laIP := ra.IP, la.IP + raPort, laPort := ra.Port, la.Port + switch { + case raIP.To4() != nil: + copy(nl.saddr[:net.IPv4len], raIP.To4()) + copy(nl.daddr[:net.IPv4len], laIP.To4()) + nl.af = syscall.AF_INET + default: + copy(nl.saddr[:], raIP.To16()) + copy(nl.daddr[:], laIP.To16()) + nl.af = syscall.AF_INET6 + } + nl.sxport[0], nl.sxport[1] = byte(raPort>>8), byte(raPort) + nl.dxport[0], nl.dxport[1] = byte(laPort>>8), byte(laPort) + if _, _, errno := syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), DIOCNATLOOK, uintptr(unsafe.Pointer(&nl))); errno != 0 { + return netip.AddrPort{}, errno + } + + var ip net.IP + switch nl.af { + case syscall.AF_INET: + ip = make(net.IP, net.IPv4len) + copy(ip, nl.rdaddr[:net.IPv4len]) + case syscall.AF_INET6: + ip = make(net.IP, net.IPv6len) + copy(ip, nl.rdaddr[:]) + } + port := uint16(nl.rdxport[0])<<8 | uint16(nl.rdxport[1]) + destination = netip.AddrPortFrom(M.AddrFromIP(ip), port) + return +} diff --git a/common/redir/redir_other.go b/common/redir/redir_other.go index e33e2de9..3d60afeb 100644 --- a/common/redir/redir_other.go +++ b/common/redir/redir_other.go @@ -1,4 +1,4 @@ -//go:build !linux +//go:build !linux && !darwin package redir