sockopt_linux.go 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. package internet
  2. import (
  3. "net"
  4. "strconv"
  5. "syscall"
  6. "github.com/xtls/xray-core/common/errors"
  7. "golang.org/x/sys/unix"
  8. )
  9. func bindAddr(fd uintptr, ip []byte, port uint32) error {
  10. setReuseAddr(fd)
  11. setReusePort(fd)
  12. var sockaddr syscall.Sockaddr
  13. switch len(ip) {
  14. case net.IPv4len:
  15. a4 := &syscall.SockaddrInet4{
  16. Port: int(port),
  17. }
  18. copy(a4.Addr[:], ip)
  19. sockaddr = a4
  20. case net.IPv6len:
  21. a6 := &syscall.SockaddrInet6{
  22. Port: int(port),
  23. }
  24. copy(a6.Addr[:], ip)
  25. sockaddr = a6
  26. default:
  27. return errors.New("unexpected length of ip")
  28. }
  29. return syscall.Bind(int(fd), sockaddr)
  30. }
  31. func applyOutboundSocketOptions(network string, address string, fd uintptr, config *SocketConfig) error {
  32. if config.Mark != 0 {
  33. if err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_MARK, int(config.Mark)); err != nil {
  34. return errors.New("failed to set SO_MARK").Base(err)
  35. }
  36. }
  37. if config.Interface != "" {
  38. if err := syscall.BindToDevice(int(fd), config.Interface); err != nil {
  39. return errors.New("failed to set Interface").Base(err)
  40. }
  41. }
  42. if isTCPSocket(network) {
  43. tfo := config.ParseTFOValue()
  44. if tfo > 0 {
  45. tfo = 1
  46. }
  47. if tfo >= 0 {
  48. if err := syscall.SetsockoptInt(int(fd), syscall.SOL_TCP, unix.TCP_FASTOPEN_CONNECT, tfo); err != nil {
  49. return errors.New("failed to set TCP_FASTOPEN_CONNECT", tfo).Base(err)
  50. }
  51. }
  52. if config.TcpKeepAliveInterval > 0 || config.TcpKeepAliveIdle > 0 {
  53. if config.TcpKeepAliveInterval > 0 {
  54. if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, syscall.TCP_KEEPINTVL, int(config.TcpKeepAliveInterval)); err != nil {
  55. return errors.New("failed to set TCP_KEEPINTVL", err)
  56. }
  57. }
  58. if config.TcpKeepAliveIdle > 0 {
  59. if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, syscall.TCP_KEEPIDLE, int(config.TcpKeepAliveIdle)); err != nil {
  60. return errors.New("failed to set TCP_KEEPIDLE", err)
  61. }
  62. }
  63. if err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_KEEPALIVE, 1); err != nil {
  64. return errors.New("failed to set SO_KEEPALIVE", err)
  65. }
  66. } else if config.TcpKeepAliveInterval < 0 || config.TcpKeepAliveIdle < 0 {
  67. if err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_KEEPALIVE, 0); err != nil {
  68. return errors.New("failed to unset SO_KEEPALIVE", err)
  69. }
  70. }
  71. if config.TcpCongestion != "" {
  72. if err := syscall.SetsockoptString(int(fd), syscall.SOL_TCP, syscall.TCP_CONGESTION, config.TcpCongestion); err != nil {
  73. return errors.New("failed to set TCP_CONGESTION", err)
  74. }
  75. }
  76. if config.TcpWindowClamp > 0 {
  77. if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, syscall.TCP_WINDOW_CLAMP, int(config.TcpWindowClamp)); err != nil {
  78. return errors.New("failed to set TCP_WINDOW_CLAMP", err)
  79. }
  80. }
  81. if config.TcpUserTimeout > 0 {
  82. if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, unix.TCP_USER_TIMEOUT, int(config.TcpUserTimeout)); err != nil {
  83. return errors.New("failed to set TCP_USER_TIMEOUT", err)
  84. }
  85. }
  86. if config.TcpMaxSeg > 0 {
  87. if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, unix.TCP_MAXSEG, int(config.TcpMaxSeg)); err != nil {
  88. return errors.New("failed to set TCP_MAXSEG", err)
  89. }
  90. }
  91. if config.TcpNoDelay {
  92. if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, unix.TCP_NODELAY, 1); err != nil {
  93. return errors.New("failed to set TCP_NODELAY", err)
  94. }
  95. }
  96. if len(config.CustomSockopt) > 0 {
  97. for _, custom := range config.CustomSockopt {
  98. var level = 0x6 // default TCP
  99. var opt int
  100. if len(custom.Opt) == 0 {
  101. return errors.New("No opt!")
  102. } else {
  103. opt, _ = strconv.Atoi(custom.Opt)
  104. }
  105. if custom.Level != "" {
  106. level, _ = strconv.Atoi(custom.Level)
  107. }
  108. if custom.Type == "int" {
  109. value, _ := strconv.Atoi(custom.Value)
  110. if err := syscall.SetsockoptInt(int(fd), level, opt, value); err != nil {
  111. return errors.New("failed to set CustomSockoptInt", opt, value, err)
  112. }
  113. } else if custom.Type == "str" {
  114. if err := syscall.SetsockoptString(int(fd), level, opt, custom.Value); err != nil {
  115. return errors.New("failed to set CustomSockoptString", opt, custom.Value, err)
  116. }
  117. } else {
  118. return errors.New("unknown CustomSockopt type:", custom.Type)
  119. }
  120. }
  121. }
  122. }
  123. if config.Tproxy.IsEnabled() {
  124. if err := syscall.SetsockoptInt(int(fd), syscall.SOL_IP, syscall.IP_TRANSPARENT, 1); err != nil {
  125. return errors.New("failed to set IP_TRANSPARENT").Base(err)
  126. }
  127. }
  128. return nil
  129. }
  130. func applyInboundSocketOptions(network string, fd uintptr, config *SocketConfig) error {
  131. if config.Mark != 0 {
  132. if err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_MARK, int(config.Mark)); err != nil {
  133. return errors.New("failed to set SO_MARK").Base(err)
  134. }
  135. }
  136. if isTCPSocket(network) {
  137. tfo := config.ParseTFOValue()
  138. if tfo >= 0 {
  139. if err := syscall.SetsockoptInt(int(fd), syscall.SOL_TCP, unix.TCP_FASTOPEN, tfo); err != nil {
  140. return errors.New("failed to set TCP_FASTOPEN", tfo).Base(err)
  141. }
  142. }
  143. if config.TcpKeepAliveInterval > 0 || config.TcpKeepAliveIdle > 0 {
  144. if config.TcpKeepAliveInterval > 0 {
  145. if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, syscall.TCP_KEEPINTVL, int(config.TcpKeepAliveInterval)); err != nil {
  146. return errors.New("failed to set TCP_KEEPINTVL", err)
  147. }
  148. }
  149. if config.TcpKeepAliveIdle > 0 {
  150. if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, syscall.TCP_KEEPIDLE, int(config.TcpKeepAliveIdle)); err != nil {
  151. return errors.New("failed to set TCP_KEEPIDLE", err)
  152. }
  153. }
  154. if err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_KEEPALIVE, 1); err != nil {
  155. return errors.New("failed to set SO_KEEPALIVE", err)
  156. }
  157. } else if config.TcpKeepAliveInterval < 0 || config.TcpKeepAliveIdle < 0 {
  158. if err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_KEEPALIVE, 0); err != nil {
  159. return errors.New("failed to unset SO_KEEPALIVE", err)
  160. }
  161. }
  162. if config.TcpCongestion != "" {
  163. if err := syscall.SetsockoptString(int(fd), syscall.SOL_TCP, syscall.TCP_CONGESTION, config.TcpCongestion); err != nil {
  164. return errors.New("failed to set TCP_CONGESTION", err)
  165. }
  166. }
  167. if config.TcpWindowClamp > 0 {
  168. if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, syscall.TCP_WINDOW_CLAMP, int(config.TcpWindowClamp)); err != nil {
  169. return errors.New("failed to set TCP_WINDOW_CLAMP", err)
  170. }
  171. }
  172. if config.TcpUserTimeout > 0 {
  173. if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, unix.TCP_USER_TIMEOUT, int(config.TcpUserTimeout)); err != nil {
  174. return errors.New("failed to set TCP_USER_TIMEOUT", err)
  175. }
  176. }
  177. if config.TcpMaxSeg > 0 {
  178. if err := syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, unix.TCP_MAXSEG, int(config.TcpMaxSeg)); err != nil {
  179. return errors.New("failed to set TCP_MAXSEG", err)
  180. }
  181. }
  182. if len(config.CustomSockopt) > 0 {
  183. for _, custom := range config.CustomSockopt {
  184. var level = 0x6 // default TCP
  185. var opt int
  186. if len(custom.Opt) == 0 {
  187. return errors.New("No opt!")
  188. } else {
  189. opt, _ = strconv.Atoi(custom.Opt)
  190. }
  191. if custom.Level != "" {
  192. level, _ = strconv.Atoi(custom.Level)
  193. }
  194. if custom.Type == "int" {
  195. value, _ := strconv.Atoi(custom.Value)
  196. if err := syscall.SetsockoptInt(int(fd), level, opt, value); err != nil {
  197. return errors.New("failed to set CustomSockoptInt", opt, value, err)
  198. }
  199. } else if custom.Type == "str" {
  200. if err := syscall.SetsockoptString(int(fd), level, opt, custom.Value); err != nil {
  201. return errors.New("failed to set CustomSockoptString", opt, custom.Value, err)
  202. }
  203. } else {
  204. return errors.New("unknown CustomSockopt type:", custom.Type)
  205. }
  206. }
  207. }
  208. }
  209. if config.Tproxy.IsEnabled() {
  210. if err := syscall.SetsockoptInt(int(fd), syscall.SOL_IP, syscall.IP_TRANSPARENT, 1); err != nil {
  211. return errors.New("failed to set IP_TRANSPARENT").Base(err)
  212. }
  213. }
  214. if config.ReceiveOriginalDestAddress && isUDPSocket(network) {
  215. err1 := syscall.SetsockoptInt(int(fd), syscall.SOL_IPV6, unix.IPV6_RECVORIGDSTADDR, 1)
  216. err2 := syscall.SetsockoptInt(int(fd), syscall.SOL_IP, syscall.IP_RECVORIGDSTADDR, 1)
  217. if err1 != nil && err2 != nil {
  218. return err1
  219. }
  220. }
  221. if config.V6Only {
  222. if err := syscall.SetsockoptInt(int(fd), syscall.SOL_IPV6, syscall.IPV6_V6ONLY, 1); err != nil {
  223. return errors.New("failed to set IPV6_V6ONLY", err)
  224. }
  225. }
  226. return nil
  227. }
  228. func setReuseAddr(fd uintptr) error {
  229. if err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1); err != nil {
  230. return errors.New("failed to set SO_REUSEADDR").Base(err).AtWarning()
  231. }
  232. return nil
  233. }
  234. func setReusePort(fd uintptr) error {
  235. if err := syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, unix.SO_REUSEPORT, 1); err != nil {
  236. return errors.New("failed to set SO_REUSEPORT").Base(err).AtWarning()
  237. }
  238. return nil
  239. }