mirror of
https://github.com/SagerNet/sing-box.git
synced 2024-12-27 05:55:38 +08:00
58 lines
1.9 KiB
Go
58 lines
1.9 KiB
Go
package redir
|
|
|
|
import (
|
|
"encoding/binary"
|
|
"net/netip"
|
|
"syscall"
|
|
|
|
"github.com/sagernet/sing/common/control"
|
|
E "github.com/sagernet/sing/common/exceptions"
|
|
M "github.com/sagernet/sing/common/metadata"
|
|
|
|
"golang.org/x/sys/unix"
|
|
)
|
|
|
|
func TProxy(fd uintptr, isIPv6 bool) error {
|
|
err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1)
|
|
if err == nil {
|
|
err = syscall.SetsockoptInt(int(fd), syscall.SOL_IP, syscall.IP_TRANSPARENT, 1)
|
|
}
|
|
if err == nil && isIPv6 {
|
|
err = syscall.SetsockoptInt(int(fd), syscall.SOL_IPV6, unix.IPV6_TRANSPARENT, 1)
|
|
}
|
|
if err == nil {
|
|
err = syscall.SetsockoptInt(int(fd), syscall.SOL_IP, syscall.IP_RECVORIGDSTADDR, 1)
|
|
}
|
|
if err == nil && isIPv6 {
|
|
err = syscall.SetsockoptInt(int(fd), syscall.SOL_IPV6, unix.IPV6_RECVORIGDSTADDR, 1)
|
|
}
|
|
return err
|
|
}
|
|
|
|
func TProxyWriteBack() control.Func {
|
|
return func(network, address string, conn syscall.RawConn) error {
|
|
return control.Raw(conn, func(fd uintptr) error {
|
|
if M.ParseSocksaddr(address).Addr.Is6() {
|
|
return syscall.SetsockoptInt(int(fd), syscall.SOL_IPV6, unix.IPV6_TRANSPARENT, 1)
|
|
} else {
|
|
return syscall.SetsockoptInt(int(fd), syscall.SOL_IP, syscall.IP_TRANSPARENT, 1)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func GetOriginalDestinationFromOOB(oob []byte) (netip.AddrPort, error) {
|
|
controlMessages, err := unix.ParseSocketControlMessage(oob)
|
|
if err != nil {
|
|
return netip.AddrPort{}, err
|
|
}
|
|
for _, message := range controlMessages {
|
|
if message.Header.Level == unix.SOL_IP && message.Header.Type == unix.IP_RECVORIGDSTADDR {
|
|
return netip.AddrPortFrom(M.AddrFromIP(message.Data[4:8]), binary.BigEndian.Uint16(message.Data[2:4])), nil
|
|
} else if message.Header.Level == unix.SOL_IPV6 && message.Header.Type == unix.IPV6_RECVORIGDSTADDR {
|
|
return netip.AddrPortFrom(M.AddrFromIP(message.Data[8:24]), binary.BigEndian.Uint16(message.Data[2:4])), nil
|
|
}
|
|
}
|
|
return netip.AddrPort{}, E.New("not found")
|
|
}
|