default.go 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390
  1. package dialer
  2. import (
  3. "context"
  4. "errors"
  5. "net"
  6. "net/netip"
  7. "syscall"
  8. "time"
  9. "github.com/sagernet/sing-box/adapter"
  10. "github.com/sagernet/sing-box/common/listener"
  11. C "github.com/sagernet/sing-box/constant"
  12. "github.com/sagernet/sing-box/option"
  13. "github.com/sagernet/sing/common"
  14. "github.com/sagernet/sing/common/control"
  15. E "github.com/sagernet/sing/common/exceptions"
  16. M "github.com/sagernet/sing/common/metadata"
  17. N "github.com/sagernet/sing/common/network"
  18. "github.com/sagernet/sing/service"
  19. "github.com/database64128/tfo-go/v2"
  20. )
  21. var (
  22. _ ParallelInterfaceDialer = (*DefaultDialer)(nil)
  23. _ WireGuardListener = (*DefaultDialer)(nil)
  24. )
  25. type DefaultDialer struct {
  26. dialer4 tfo.Dialer
  27. dialer6 tfo.Dialer
  28. udpDialer4 net.Dialer
  29. udpDialer6 net.Dialer
  30. udpListener net.ListenConfig
  31. udpAddr4 string
  32. udpAddr6 string
  33. netns string
  34. connectionManager adapter.ConnectionManager
  35. networkManager adapter.NetworkManager
  36. networkStrategy *C.NetworkStrategy
  37. defaultNetworkStrategy bool
  38. networkType []C.InterfaceType
  39. fallbackNetworkType []C.InterfaceType
  40. networkFallbackDelay time.Duration
  41. networkLastFallback common.TypedValue[time.Time]
  42. }
  43. func NewDefault(ctx context.Context, options option.DialerOptions) (*DefaultDialer, error) {
  44. connectionManager := service.FromContext[adapter.ConnectionManager](ctx)
  45. networkManager := service.FromContext[adapter.NetworkManager](ctx)
  46. platformInterface := service.FromContext[adapter.PlatformInterface](ctx)
  47. var (
  48. dialer net.Dialer
  49. listener net.ListenConfig
  50. interfaceFinder control.InterfaceFinder
  51. networkStrategy *C.NetworkStrategy
  52. defaultNetworkStrategy bool
  53. networkType []C.InterfaceType
  54. fallbackNetworkType []C.InterfaceType
  55. networkFallbackDelay time.Duration
  56. )
  57. if networkManager != nil {
  58. interfaceFinder = networkManager.InterfaceFinder()
  59. } else {
  60. interfaceFinder = control.NewDefaultInterfaceFinder()
  61. }
  62. if options.BindInterface != "" {
  63. if !(C.IsLinux || C.IsDarwin || C.IsWindows) {
  64. return nil, E.New("`bind_interface` is only supported on Linux, macOS and Windows")
  65. }
  66. bindFunc := control.BindToInterface(interfaceFinder, options.BindInterface, -1)
  67. dialer.Control = control.Append(dialer.Control, bindFunc)
  68. listener.Control = control.Append(listener.Control, bindFunc)
  69. }
  70. if options.RoutingMark > 0 {
  71. if !C.IsLinux {
  72. return nil, E.New("`routing_mark` is only supported on Linux")
  73. }
  74. dialer.Control = control.Append(dialer.Control, setMarkWrapper(networkManager, uint32(options.RoutingMark), false))
  75. listener.Control = control.Append(listener.Control, setMarkWrapper(networkManager, uint32(options.RoutingMark), false))
  76. }
  77. disableDefaultBind := options.BindInterface != "" || options.Inet4BindAddress != nil || options.Inet6BindAddress != nil
  78. if disableDefaultBind || options.TCPFastOpen {
  79. if options.NetworkStrategy != nil || len(options.NetworkType) > 0 && options.FallbackNetworkType == nil && options.FallbackDelay == 0 {
  80. return nil, E.New("`network_strategy` is conflict with `bind_interface`, `inet4_bind_address`, `inet6_bind_address` and `tcp_fast_open`")
  81. }
  82. }
  83. if networkManager != nil {
  84. defaultOptions := networkManager.DefaultOptions()
  85. if defaultOptions.BindInterface != "" && !disableDefaultBind {
  86. bindFunc := control.BindToInterface(networkManager.InterfaceFinder(), defaultOptions.BindInterface, -1)
  87. dialer.Control = control.Append(dialer.Control, bindFunc)
  88. listener.Control = control.Append(listener.Control, bindFunc)
  89. } else if networkManager.AutoDetectInterface() && !disableDefaultBind {
  90. if platformInterface != nil {
  91. networkStrategy = (*C.NetworkStrategy)(options.NetworkStrategy)
  92. networkType = common.Map(options.NetworkType, option.InterfaceType.Build)
  93. fallbackNetworkType = common.Map(options.FallbackNetworkType, option.InterfaceType.Build)
  94. if networkStrategy == nil && len(networkType) == 0 && len(fallbackNetworkType) == 0 {
  95. networkStrategy = defaultOptions.NetworkStrategy
  96. networkType = defaultOptions.NetworkType
  97. fallbackNetworkType = defaultOptions.FallbackNetworkType
  98. }
  99. networkFallbackDelay = time.Duration(options.FallbackDelay)
  100. if networkFallbackDelay == 0 && defaultOptions.FallbackDelay != 0 {
  101. networkFallbackDelay = defaultOptions.FallbackDelay
  102. }
  103. if networkStrategy == nil {
  104. networkStrategy = common.Ptr(C.NetworkStrategyDefault)
  105. defaultNetworkStrategy = true
  106. }
  107. bindFunc := networkManager.ProtectFunc()
  108. dialer.Control = control.Append(dialer.Control, bindFunc)
  109. listener.Control = control.Append(listener.Control, bindFunc)
  110. } else {
  111. bindFunc := networkManager.AutoDetectInterfaceFunc()
  112. dialer.Control = control.Append(dialer.Control, bindFunc)
  113. listener.Control = control.Append(listener.Control, bindFunc)
  114. }
  115. }
  116. if options.RoutingMark == 0 && defaultOptions.RoutingMark != 0 {
  117. dialer.Control = control.Append(dialer.Control, setMarkWrapper(networkManager, defaultOptions.RoutingMark, true))
  118. listener.Control = control.Append(listener.Control, setMarkWrapper(networkManager, defaultOptions.RoutingMark, true))
  119. }
  120. }
  121. if networkManager != nil {
  122. markFunc := networkManager.AutoRedirectOutputMarkFunc()
  123. dialer.Control = control.Append(dialer.Control, markFunc)
  124. listener.Control = control.Append(listener.Control, markFunc)
  125. }
  126. if options.ReuseAddr {
  127. listener.Control = control.Append(listener.Control, control.ReuseAddr())
  128. }
  129. if options.ProtectPath != "" {
  130. dialer.Control = control.Append(dialer.Control, control.ProtectPath(options.ProtectPath))
  131. listener.Control = control.Append(listener.Control, control.ProtectPath(options.ProtectPath))
  132. }
  133. if options.BindAddressNoPort {
  134. if !C.IsLinux {
  135. return nil, E.New("`bind_address_no_port` is only supported on Linux")
  136. }
  137. dialer.Control = control.Append(dialer.Control, control.BindAddressNoPort())
  138. }
  139. if options.ConnectTimeout != 0 {
  140. dialer.Timeout = time.Duration(options.ConnectTimeout)
  141. } else {
  142. dialer.Timeout = C.TCPConnectTimeout
  143. }
  144. if options.DisableTCPKeepAlive {
  145. dialer.KeepAlive = -1
  146. dialer.KeepAliveConfig.Enable = false
  147. } else {
  148. keepIdle := time.Duration(options.TCPKeepAlive)
  149. if keepIdle == 0 {
  150. keepIdle = C.TCPKeepAliveInitial
  151. }
  152. keepInterval := time.Duration(options.TCPKeepAliveInterval)
  153. if keepInterval == 0 {
  154. keepInterval = C.TCPKeepAliveInterval
  155. }
  156. dialer.KeepAliveConfig = net.KeepAliveConfig{
  157. Enable: true,
  158. Idle: keepIdle,
  159. Interval: keepInterval,
  160. }
  161. }
  162. var udpFragment bool
  163. if options.UDPFragment != nil {
  164. udpFragment = *options.UDPFragment
  165. } else {
  166. udpFragment = options.UDPFragmentDefault
  167. }
  168. if !udpFragment {
  169. dialer.Control = control.Append(dialer.Control, control.DisableUDPFragment())
  170. listener.Control = control.Append(listener.Control, control.DisableUDPFragment())
  171. }
  172. var (
  173. dialer4 = dialer
  174. udpDialer4 = dialer
  175. udpAddr4 string
  176. )
  177. if options.Inet4BindAddress != nil {
  178. bindAddr := options.Inet4BindAddress.Build(netip.IPv4Unspecified())
  179. dialer4.LocalAddr = &net.TCPAddr{IP: bindAddr.AsSlice()}
  180. udpDialer4.LocalAddr = &net.UDPAddr{IP: bindAddr.AsSlice()}
  181. udpAddr4 = M.SocksaddrFrom(bindAddr, 0).String()
  182. }
  183. var (
  184. dialer6 = dialer
  185. udpDialer6 = dialer
  186. udpAddr6 string
  187. )
  188. if options.Inet6BindAddress != nil {
  189. bindAddr := options.Inet6BindAddress.Build(netip.IPv6Unspecified())
  190. dialer6.LocalAddr = &net.TCPAddr{IP: bindAddr.AsSlice()}
  191. udpDialer6.LocalAddr = &net.UDPAddr{IP: bindAddr.AsSlice()}
  192. udpAddr6 = M.SocksaddrFrom(bindAddr, 0).String()
  193. }
  194. if options.TCPMultiPath {
  195. dialer4.SetMultipathTCP(true)
  196. }
  197. tcpDialer4 := tfo.Dialer{Dialer: dialer4, DisableTFO: !options.TCPFastOpen}
  198. tcpDialer6 := tfo.Dialer{Dialer: dialer6, DisableTFO: !options.TCPFastOpen}
  199. return &DefaultDialer{
  200. dialer4: tcpDialer4,
  201. dialer6: tcpDialer6,
  202. udpDialer4: udpDialer4,
  203. udpDialer6: udpDialer6,
  204. udpListener: listener,
  205. udpAddr4: udpAddr4,
  206. udpAddr6: udpAddr6,
  207. netns: options.NetNs,
  208. connectionManager: connectionManager,
  209. networkManager: networkManager,
  210. networkStrategy: networkStrategy,
  211. defaultNetworkStrategy: defaultNetworkStrategy,
  212. networkType: networkType,
  213. fallbackNetworkType: fallbackNetworkType,
  214. networkFallbackDelay: networkFallbackDelay,
  215. }, nil
  216. }
  217. func setMarkWrapper(networkManager adapter.NetworkManager, mark uint32, isDefault bool) control.Func {
  218. if networkManager == nil {
  219. return control.RoutingMark(mark)
  220. }
  221. return func(network, address string, conn syscall.RawConn) error {
  222. if networkManager.AutoRedirectOutputMark() != 0 {
  223. if isDefault {
  224. return E.New("`route.default_mark` is conflict with `tun.auto_redirect`")
  225. } else {
  226. return E.New("`routing_mark` is conflict with `tun.auto_redirect`")
  227. }
  228. }
  229. return control.RoutingMark(mark)(network, address, conn)
  230. }
  231. }
  232. func (d *DefaultDialer) DialContext(ctx context.Context, network string, address M.Socksaddr) (net.Conn, error) {
  233. if !address.IsValid() {
  234. return nil, E.New("invalid address")
  235. } else if address.IsDomain() {
  236. return nil, E.New("domain not resolved")
  237. }
  238. if d.networkStrategy == nil {
  239. return d.trackConn(listener.ListenNetworkNamespace[net.Conn](d.netns, func() (net.Conn, error) {
  240. switch N.NetworkName(network) {
  241. case N.NetworkUDP:
  242. if !address.IsIPv6() {
  243. return d.udpDialer4.DialContext(ctx, network, address.String())
  244. } else {
  245. return d.udpDialer6.DialContext(ctx, network, address.String())
  246. }
  247. }
  248. if !address.IsIPv6() {
  249. return DialSlowContext(&d.dialer4, ctx, network, address)
  250. } else {
  251. return DialSlowContext(&d.dialer6, ctx, network, address)
  252. }
  253. }))
  254. } else {
  255. return d.DialParallelInterface(ctx, network, address, d.networkStrategy, d.networkType, d.fallbackNetworkType, d.networkFallbackDelay)
  256. }
  257. }
  258. func (d *DefaultDialer) DialParallelInterface(ctx context.Context, network string, address M.Socksaddr, strategy *C.NetworkStrategy, interfaceType []C.InterfaceType, fallbackInterfaceType []C.InterfaceType, fallbackDelay time.Duration) (net.Conn, error) {
  259. if strategy == nil {
  260. strategy = d.networkStrategy
  261. }
  262. if strategy == nil {
  263. return d.DialContext(ctx, network, address)
  264. }
  265. if len(interfaceType) == 0 {
  266. interfaceType = d.networkType
  267. }
  268. if len(fallbackInterfaceType) == 0 {
  269. fallbackInterfaceType = d.fallbackNetworkType
  270. }
  271. if fallbackDelay == 0 {
  272. fallbackDelay = d.networkFallbackDelay
  273. }
  274. var dialer net.Dialer
  275. if N.NetworkName(network) == N.NetworkTCP {
  276. dialer = d.dialer4.Dialer
  277. } else {
  278. dialer = d.udpDialer4
  279. }
  280. fastFallback := time.Since(d.networkLastFallback.Load()) < C.TCPTimeout
  281. var (
  282. conn net.Conn
  283. isPrimary bool
  284. err error
  285. )
  286. if !fastFallback {
  287. conn, isPrimary, err = d.dialParallelInterface(ctx, dialer, network, address.String(), *strategy, interfaceType, fallbackInterfaceType, fallbackDelay)
  288. } else {
  289. conn, isPrimary, err = d.dialParallelInterfaceFastFallback(ctx, dialer, network, address.String(), *strategy, interfaceType, fallbackInterfaceType, fallbackDelay, d.networkLastFallback.Store)
  290. }
  291. if err != nil {
  292. // bind interface failed on legacy xiaomi systems
  293. if d.defaultNetworkStrategy && errors.Is(err, syscall.EPERM) {
  294. d.networkStrategy = nil
  295. return d.DialContext(ctx, network, address)
  296. } else {
  297. return nil, err
  298. }
  299. }
  300. if !fastFallback && !isPrimary {
  301. d.networkLastFallback.Store(time.Now())
  302. }
  303. return d.trackConn(conn, nil)
  304. }
  305. func (d *DefaultDialer) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
  306. if d.networkStrategy == nil {
  307. return d.trackPacketConn(listener.ListenNetworkNamespace[net.PacketConn](d.netns, func() (net.PacketConn, error) {
  308. if destination.IsIPv6() {
  309. return d.udpListener.ListenPacket(ctx, N.NetworkUDP, d.udpAddr6)
  310. } else if destination.IsIPv4() && !destination.Addr.IsUnspecified() {
  311. return d.udpListener.ListenPacket(ctx, N.NetworkUDP+"4", d.udpAddr4)
  312. } else {
  313. return d.udpListener.ListenPacket(ctx, N.NetworkUDP, d.udpAddr4)
  314. }
  315. }))
  316. } else {
  317. return d.ListenSerialInterfacePacket(ctx, destination, d.networkStrategy, d.networkType, d.fallbackNetworkType, d.networkFallbackDelay)
  318. }
  319. }
  320. func (d *DefaultDialer) DialerForICMPDestination(destination netip.Addr) net.Dialer {
  321. if !destination.Is6() {
  322. return d.dialer4.Dialer
  323. } else {
  324. return d.dialer6.Dialer
  325. }
  326. }
  327. func (d *DefaultDialer) ListenSerialInterfacePacket(ctx context.Context, destination M.Socksaddr, strategy *C.NetworkStrategy, interfaceType []C.InterfaceType, fallbackInterfaceType []C.InterfaceType, fallbackDelay time.Duration) (net.PacketConn, error) {
  328. if strategy == nil {
  329. strategy = d.networkStrategy
  330. }
  331. if strategy == nil {
  332. return d.ListenPacket(ctx, destination)
  333. }
  334. if len(interfaceType) == 0 {
  335. interfaceType = d.networkType
  336. }
  337. if len(fallbackInterfaceType) == 0 {
  338. fallbackInterfaceType = d.fallbackNetworkType
  339. }
  340. if fallbackDelay == 0 {
  341. fallbackDelay = d.networkFallbackDelay
  342. }
  343. network := N.NetworkUDP
  344. if destination.IsIPv4() && !destination.Addr.IsUnspecified() {
  345. network += "4"
  346. }
  347. packetConn, err := d.listenSerialInterfacePacket(ctx, d.udpListener, network, "", *strategy, interfaceType, fallbackInterfaceType, fallbackDelay)
  348. if err != nil {
  349. // bind interface failed on legacy xiaomi systems
  350. if d.defaultNetworkStrategy && errors.Is(err, syscall.EPERM) {
  351. d.networkStrategy = nil
  352. return d.ListenPacket(ctx, destination)
  353. } else {
  354. return nil, err
  355. }
  356. }
  357. return d.trackPacketConn(packetConn, nil)
  358. }
  359. func (d *DefaultDialer) WireGuardControl() control.Func {
  360. return d.udpListener.Control
  361. }
  362. func (d *DefaultDialer) trackConn(conn net.Conn, err error) (net.Conn, error) {
  363. if d.connectionManager == nil || err != nil {
  364. return conn, err
  365. }
  366. return d.connectionManager.TrackConn(conn), nil
  367. }
  368. func (d *DefaultDialer) trackPacketConn(conn net.PacketConn, err error) (net.PacketConn, error) {
  369. if d.connectionManager == nil || err != nil {
  370. return conn, err
  371. }
  372. return d.connectionManager.TrackPacketConn(conn), nil
  373. }