| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364 | 
							- 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
 
- }
 
 
  |