github.com/metacubex/mihomo@v1.18.5/listener/tproxy/setsockopt_linux.go (about)

     1  //go:build linux
     2  
     3  package tproxy
     4  
     5  import (
     6  	"net"
     7  	"syscall"
     8  )
     9  
    10  func setsockopt(rc syscall.RawConn, addr string) error {
    11  	isIPv6 := true
    12  	host, _, err := net.SplitHostPort(addr)
    13  	if err != nil {
    14  		return err
    15  	}
    16  	ip := net.ParseIP(host)
    17  	if ip != nil && ip.To4() != nil {
    18  		isIPv6 = false
    19  	}
    20  
    21  	rc.Control(func(fd uintptr) {
    22  		err = syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1)
    23  
    24  		if err == nil {
    25  			err = syscall.SetsockoptInt(int(fd), syscall.SOL_IP, syscall.IP_TRANSPARENT, 1)
    26  		}
    27  		if err == nil && isIPv6 {
    28  			err = syscall.SetsockoptInt(int(fd), syscall.SOL_IPV6, IPV6_TRANSPARENT, 1)
    29  		}
    30  
    31  		if err == nil {
    32  			err = syscall.SetsockoptInt(int(fd), syscall.SOL_IP, syscall.IP_RECVORIGDSTADDR, 1)
    33  		}
    34  		if err == nil && isIPv6 {
    35  			err = syscall.SetsockoptInt(int(fd), syscall.SOL_IPV6, IPV6_RECVORIGDSTADDR, 1)
    36  		}
    37  
    38  		if err == nil {
    39  			_ = setDSCPsockopt(fd, isIPv6)
    40  		}
    41  	})
    42  
    43  	return err
    44  }
    45  
    46  func setDSCPsockopt(fd uintptr, isIPv6 bool) (err error) {
    47  	if err == nil {
    48  		err = syscall.SetsockoptInt(int(fd), syscall.SOL_IP, syscall.IP_RECVTOS, 1)
    49  	}
    50  
    51  	if err == nil && isIPv6 {
    52  		err = syscall.SetsockoptInt(int(fd), syscall.SOL_IPV6, syscall.IPV6_RECVTCLASS, 1)
    53  	}
    54  
    55  	return
    56  }