sockopt_freebsd.go 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. package internet
  2. import (
  3. "encoding/binary"
  4. "net"
  5. "os"
  6. "syscall"
  7. "unsafe"
  8. )
  9. const (
  10. sysAF_INET = 0x2
  11. sysAF_INET6 = 0x1c
  12. sysPF_INOUT = 0x0
  13. sysPF_IN = 0x1
  14. sysPF_OUT = 0x2
  15. sysPF_FWD = 0x3
  16. sysDIOCNATLOOK = 0xc04c4417
  17. ianaProtocolIP = 0x0
  18. ianaProtocolTCP = 0x6
  19. ianaProtocolUDP = 0x11
  20. ianaProtocolIPv6 = 0x29
  21. )
  22. type pfiocNatlook struct {
  23. Saddr [16]byte /* pf_addr */
  24. Daddr [16]byte /* pf_addr */
  25. Rsaddr [16]byte /* pf_addr */
  26. Rdaddr [16]byte /* pf_addr */
  27. Sport uint16
  28. Dport uint16
  29. Rsport uint16
  30. Rdport uint16
  31. Af uint8
  32. Proto uint8
  33. Direction uint8
  34. Pad_cgo_0 [1]byte
  35. }
  36. const (
  37. sizeofPfiocNatlook = 0x4c
  38. SO_REUSEPORT_LB = 0x00010000
  39. IP_RECVORIGDSTADDR = 27
  40. TCP_FASTOPEN = 0x401
  41. SO_REUSEADDR = 0x4
  42. )
  43. func ioctl(s uintptr, ioc int, b []byte) error {
  44. if _, _, errno := syscall.Syscall(syscall.SYS_IOCTL, s, uintptr(ioc), uintptr(unsafe.Pointer(&b[0]))); errno != 0 {
  45. return error(errno)
  46. }
  47. return nil
  48. }
  49. func (nl *pfiocNatlook) rdPort() int {
  50. return int(binary.BigEndian.Uint16((*[2]byte)(unsafe.Pointer(&nl.Rdport))[:]))
  51. }
  52. func (nl *pfiocNatlook) setPort(remote, local int) {
  53. binary.BigEndian.PutUint16((*[2]byte)(unsafe.Pointer(&nl.Sport))[:], uint16(remote))
  54. binary.BigEndian.PutUint16((*[2]byte)(unsafe.Pointer(&nl.Dport))[:], uint16(local))
  55. }
  56. func OriginalDst(la, ra net.Addr) (net.IP, int, error) {
  57. f, err := os.Open("/dev/pf")
  58. if err != nil {
  59. return net.IP{}, -1, newError("failed to open device /dev/pf").Base(err)
  60. }
  61. defer f.Close()
  62. fd := f.Fd()
  63. b := make([]byte, sizeofPfiocNatlook)
  64. nl := (*pfiocNatlook)(unsafe.Pointer(&b[0]))
  65. var raIP, laIP net.IP
  66. var raPort, laPort int
  67. switch la.(type) {
  68. case *net.TCPAddr:
  69. raIP = ra.(*net.TCPAddr).IP
  70. laIP = la.(*net.TCPAddr).IP
  71. raPort = ra.(*net.TCPAddr).Port
  72. laPort = la.(*net.TCPAddr).Port
  73. nl.Proto = ianaProtocolTCP
  74. case *net.UDPAddr:
  75. raIP = ra.(*net.UDPAddr).IP
  76. laIP = la.(*net.UDPAddr).IP
  77. raPort = ra.(*net.UDPAddr).Port
  78. laPort = la.(*net.UDPAddr).Port
  79. nl.Proto = ianaProtocolUDP
  80. }
  81. if raIP.To4() != nil {
  82. if laIP.IsUnspecified() {
  83. laIP = net.ParseIP("127.0.0.1")
  84. }
  85. copy(nl.Saddr[:net.IPv4len], raIP.To4())
  86. copy(nl.Daddr[:net.IPv4len], laIP.To4())
  87. nl.Af = sysAF_INET
  88. }
  89. if raIP.To16() != nil && raIP.To4() == nil {
  90. if laIP.IsUnspecified() {
  91. laIP = net.ParseIP("::1")
  92. }
  93. copy(nl.Saddr[:], raIP)
  94. copy(nl.Daddr[:], laIP)
  95. nl.Af = sysAF_INET6
  96. }
  97. nl.setPort(raPort, laPort)
  98. ioc := uintptr(sysDIOCNATLOOK)
  99. for _, dir := range []byte{sysPF_OUT, sysPF_IN} {
  100. nl.Direction = dir
  101. err = ioctl(fd, int(ioc), b)
  102. if err == nil || err != syscall.ENOENT {
  103. break
  104. }
  105. }
  106. if err != nil {
  107. return net.IP{}, -1, os.NewSyscallError("ioctl", err)
  108. }
  109. odPort := nl.rdPort()
  110. var odIP net.IP
  111. switch nl.Af {
  112. case sysAF_INET:
  113. odIP = make(net.IP, net.IPv4len)
  114. copy(odIP, nl.Rdaddr[:net.IPv4len])
  115. case sysAF_INET6:
  116. odIP = make(net.IP, net.IPv6len)
  117. copy(odIP, nl.Rdaddr[:])
  118. }
  119. return odIP, odPort, nil
  120. }
  121. func applyOutboundSocketOptions(network string, address string, fd uintptr, config *SocketConfig) error {
  122. if config.Mark != 0 {
  123. if err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_USER_COOKIE, int(config.Mark)); err != nil {
  124. return newError("failed to set SO_USER_COOKIE").Base(err)
  125. }
  126. }
  127. if isTCPSocket(network) {
  128. switch config.Tfo {
  129. case SocketConfig_Enable:
  130. if err := syscall.SetsockoptInt(int(fd), ianaProtocolTCP, TCP_FASTOPEN, 1); err != nil {
  131. return newError("failed to set TCP_FASTOPEN_CONNECT=1").Base(err)
  132. }
  133. case SocketConfig_Disable:
  134. if err := syscall.SetsockoptInt(int(fd), ianaProtocolTCP, TCP_FASTOPEN, 0); err != nil {
  135. return newError("failed to set TCP_FASTOPEN_CONNECT=0").Base(err)
  136. }
  137. }
  138. }
  139. if config.Tproxy.IsEnabled() {
  140. ip, _, _ := net.SplitHostPort(address)
  141. if net.ParseIP(ip).To4() != nil {
  142. if err := syscall.SetsockoptInt(int(fd), ianaProtocolIP, syscall.IP_BINDANY, 1); err != nil {
  143. return newError("failed to set outbound IP_BINDANY").Base(err)
  144. }
  145. } else {
  146. if err := syscall.SetsockoptInt(int(fd), ianaProtocolIPv6, syscall.IPV6_BINDANY, 1); err != nil {
  147. return newError("failed to set outbound IPV6_BINDANY").Base(err)
  148. }
  149. }
  150. }
  151. return nil
  152. }
  153. func applyInboundSocketOptions(network string, fd uintptr, config *SocketConfig) error {
  154. if config.Mark != 0 {
  155. if err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_USER_COOKIE, int(config.Mark)); err != nil {
  156. return newError("failed to set SO_USER_COOKIE").Base(err)
  157. }
  158. }
  159. if isTCPSocket(network) {
  160. switch config.Tfo {
  161. case SocketConfig_Enable:
  162. if err := syscall.SetsockoptInt(int(fd), ianaProtocolTCP, TCP_FASTOPEN, 1); err != nil {
  163. return newError("failed to set TCP_FASTOPEN=1").Base(err)
  164. }
  165. case SocketConfig_Disable:
  166. if err := syscall.SetsockoptInt(int(fd), ianaProtocolTCP, TCP_FASTOPEN, 0); err != nil {
  167. return newError("failed to set TCP_FASTOPEN=0").Base(err)
  168. }
  169. }
  170. }
  171. if config.Tproxy.IsEnabled() {
  172. if err := syscall.SetsockoptInt(int(fd), ianaProtocolIPv6, syscall.IPV6_BINDANY, 1); err != nil {
  173. if err := syscall.SetsockoptInt(int(fd), ianaProtocolIP, syscall.IP_BINDANY, 1); err != nil {
  174. return newError("failed to set inbound IP_BINDANY").Base(err)
  175. }
  176. }
  177. }
  178. return nil
  179. }
  180. func bindAddr(fd uintptr, ip []byte, port uint32) error {
  181. if err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, SO_REUSEADDR, 1); err != nil {
  182. return newError("failed to set resuse_addr").Base(err).AtWarning()
  183. }
  184. if err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, SO_REUSEPORT_LB, 1); err != nil {
  185. return newError("failed to set resuse_port").Base(err).AtWarning()
  186. }
  187. var sockaddr syscall.Sockaddr
  188. switch len(ip) {
  189. case net.IPv4len:
  190. a4 := &syscall.SockaddrInet4{
  191. Port: int(port),
  192. }
  193. copy(a4.Addr[:], ip)
  194. sockaddr = a4
  195. case net.IPv6len:
  196. a6 := &syscall.SockaddrInet6{
  197. Port: int(port),
  198. }
  199. copy(a6.Addr[:], ip)
  200. sockaddr = a6
  201. default:
  202. return newError("unexpected length of ip")
  203. }
  204. return syscall.Bind(int(fd), sockaddr)
  205. }