default.go 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387
  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. keepIdle := time.Duration(options.TCPKeepAlive)
  146. if keepIdle == 0 {
  147. keepIdle = C.TCPKeepAliveInitial
  148. }
  149. keepInterval := time.Duration(options.TCPKeepAliveInterval)
  150. if keepInterval == 0 {
  151. keepInterval = C.TCPKeepAliveInterval
  152. }
  153. dialer.KeepAliveConfig = net.KeepAliveConfig{
  154. Enable: true,
  155. Idle: keepIdle,
  156. Interval: keepInterval,
  157. }
  158. }
  159. var udpFragment bool
  160. if options.UDPFragment != nil {
  161. udpFragment = *options.UDPFragment
  162. } else {
  163. udpFragment = options.UDPFragmentDefault
  164. }
  165. if !udpFragment {
  166. dialer.Control = control.Append(dialer.Control, control.DisableUDPFragment())
  167. listener.Control = control.Append(listener.Control, control.DisableUDPFragment())
  168. }
  169. var (
  170. dialer4 = dialer
  171. udpDialer4 = dialer
  172. udpAddr4 string
  173. )
  174. if options.Inet4BindAddress != nil {
  175. bindAddr := options.Inet4BindAddress.Build(netip.IPv4Unspecified())
  176. dialer4.LocalAddr = &net.TCPAddr{IP: bindAddr.AsSlice()}
  177. udpDialer4.LocalAddr = &net.UDPAddr{IP: bindAddr.AsSlice()}
  178. udpAddr4 = M.SocksaddrFrom(bindAddr, 0).String()
  179. }
  180. var (
  181. dialer6 = dialer
  182. udpDialer6 = dialer
  183. udpAddr6 string
  184. )
  185. if options.Inet6BindAddress != nil {
  186. bindAddr := options.Inet6BindAddress.Build(netip.IPv6Unspecified())
  187. dialer6.LocalAddr = &net.TCPAddr{IP: bindAddr.AsSlice()}
  188. udpDialer6.LocalAddr = &net.UDPAddr{IP: bindAddr.AsSlice()}
  189. udpAddr6 = M.SocksaddrFrom(bindAddr, 0).String()
  190. }
  191. if options.TCPMultiPath {
  192. dialer4.SetMultipathTCP(true)
  193. }
  194. tcpDialer4 := tfo.Dialer{Dialer: dialer4, DisableTFO: !options.TCPFastOpen}
  195. tcpDialer6 := tfo.Dialer{Dialer: dialer6, DisableTFO: !options.TCPFastOpen}
  196. return &DefaultDialer{
  197. dialer4: tcpDialer4,
  198. dialer6: tcpDialer6,
  199. udpDialer4: udpDialer4,
  200. udpDialer6: udpDialer6,
  201. udpListener: listener,
  202. udpAddr4: udpAddr4,
  203. udpAddr6: udpAddr6,
  204. netns: options.NetNs,
  205. connectionManager: connectionManager,
  206. networkManager: networkManager,
  207. networkStrategy: networkStrategy,
  208. defaultNetworkStrategy: defaultNetworkStrategy,
  209. networkType: networkType,
  210. fallbackNetworkType: fallbackNetworkType,
  211. networkFallbackDelay: networkFallbackDelay,
  212. }, nil
  213. }
  214. func setMarkWrapper(networkManager adapter.NetworkManager, mark uint32, isDefault bool) control.Func {
  215. if networkManager == nil {
  216. return control.RoutingMark(mark)
  217. }
  218. return func(network, address string, conn syscall.RawConn) error {
  219. if networkManager.AutoRedirectOutputMark() != 0 {
  220. if isDefault {
  221. return E.New("`route.default_mark` is conflict with `tun.auto_redirect`")
  222. } else {
  223. return E.New("`routing_mark` is conflict with `tun.auto_redirect`")
  224. }
  225. }
  226. return control.RoutingMark(mark)(network, address, conn)
  227. }
  228. }
  229. func (d *DefaultDialer) DialContext(ctx context.Context, network string, address M.Socksaddr) (net.Conn, error) {
  230. if !address.IsValid() {
  231. return nil, E.New("invalid address")
  232. } else if address.IsFqdn() {
  233. return nil, E.New("domain not resolved")
  234. }
  235. if d.networkStrategy == nil {
  236. return d.trackConn(listener.ListenNetworkNamespace[net.Conn](d.netns, func() (net.Conn, error) {
  237. switch N.NetworkName(network) {
  238. case N.NetworkUDP:
  239. if !address.IsIPv6() {
  240. return d.udpDialer4.DialContext(ctx, network, address.String())
  241. } else {
  242. return d.udpDialer6.DialContext(ctx, network, address.String())
  243. }
  244. }
  245. if !address.IsIPv6() {
  246. return DialSlowContext(&d.dialer4, ctx, network, address)
  247. } else {
  248. return DialSlowContext(&d.dialer6, ctx, network, address)
  249. }
  250. }))
  251. } else {
  252. return d.DialParallelInterface(ctx, network, address, d.networkStrategy, d.networkType, d.fallbackNetworkType, d.networkFallbackDelay)
  253. }
  254. }
  255. 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) {
  256. if strategy == nil {
  257. strategy = d.networkStrategy
  258. }
  259. if strategy == nil {
  260. return d.DialContext(ctx, network, address)
  261. }
  262. if len(interfaceType) == 0 {
  263. interfaceType = d.networkType
  264. }
  265. if len(fallbackInterfaceType) == 0 {
  266. fallbackInterfaceType = d.fallbackNetworkType
  267. }
  268. if fallbackDelay == 0 {
  269. fallbackDelay = d.networkFallbackDelay
  270. }
  271. var dialer net.Dialer
  272. if N.NetworkName(network) == N.NetworkTCP {
  273. dialer = d.dialer4.Dialer
  274. } else {
  275. dialer = d.udpDialer4
  276. }
  277. fastFallback := time.Since(d.networkLastFallback.Load()) < C.TCPTimeout
  278. var (
  279. conn net.Conn
  280. isPrimary bool
  281. err error
  282. )
  283. if !fastFallback {
  284. conn, isPrimary, err = d.dialParallelInterface(ctx, dialer, network, address.String(), *strategy, interfaceType, fallbackInterfaceType, fallbackDelay)
  285. } else {
  286. conn, isPrimary, err = d.dialParallelInterfaceFastFallback(ctx, dialer, network, address.String(), *strategy, interfaceType, fallbackInterfaceType, fallbackDelay, d.networkLastFallback.Store)
  287. }
  288. if err != nil {
  289. // bind interface failed on legacy xiaomi systems
  290. if d.defaultNetworkStrategy && errors.Is(err, syscall.EPERM) {
  291. d.networkStrategy = nil
  292. return d.DialContext(ctx, network, address)
  293. } else {
  294. return nil, err
  295. }
  296. }
  297. if !fastFallback && !isPrimary {
  298. d.networkLastFallback.Store(time.Now())
  299. }
  300. return d.trackConn(conn, nil)
  301. }
  302. func (d *DefaultDialer) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
  303. if d.networkStrategy == nil {
  304. return d.trackPacketConn(listener.ListenNetworkNamespace[net.PacketConn](d.netns, func() (net.PacketConn, error) {
  305. if destination.IsIPv6() {
  306. return d.udpListener.ListenPacket(ctx, N.NetworkUDP, d.udpAddr6)
  307. } else if destination.IsIPv4() && !destination.Addr.IsUnspecified() {
  308. return d.udpListener.ListenPacket(ctx, N.NetworkUDP+"4", d.udpAddr4)
  309. } else {
  310. return d.udpListener.ListenPacket(ctx, N.NetworkUDP, d.udpAddr4)
  311. }
  312. }))
  313. } else {
  314. return d.ListenSerialInterfacePacket(ctx, destination, d.networkStrategy, d.networkType, d.fallbackNetworkType, d.networkFallbackDelay)
  315. }
  316. }
  317. func (d *DefaultDialer) DialerForICMPDestination(destination netip.Addr) net.Dialer {
  318. if !destination.Is6() {
  319. return d.dialer6.Dialer
  320. } else {
  321. return d.dialer4.Dialer
  322. }
  323. }
  324. 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) {
  325. if strategy == nil {
  326. strategy = d.networkStrategy
  327. }
  328. if strategy == nil {
  329. return d.ListenPacket(ctx, destination)
  330. }
  331. if len(interfaceType) == 0 {
  332. interfaceType = d.networkType
  333. }
  334. if len(fallbackInterfaceType) == 0 {
  335. fallbackInterfaceType = d.fallbackNetworkType
  336. }
  337. if fallbackDelay == 0 {
  338. fallbackDelay = d.networkFallbackDelay
  339. }
  340. network := N.NetworkUDP
  341. if destination.IsIPv4() && !destination.Addr.IsUnspecified() {
  342. network += "4"
  343. }
  344. packetConn, err := d.listenSerialInterfacePacket(ctx, d.udpListener, network, "", *strategy, interfaceType, fallbackInterfaceType, fallbackDelay)
  345. if err != nil {
  346. // bind interface failed on legacy xiaomi systems
  347. if d.defaultNetworkStrategy && errors.Is(err, syscall.EPERM) {
  348. d.networkStrategy = nil
  349. return d.ListenPacket(ctx, destination)
  350. } else {
  351. return nil, err
  352. }
  353. }
  354. return d.trackPacketConn(packetConn, nil)
  355. }
  356. func (d *DefaultDialer) WireGuardControl() control.Func {
  357. return d.udpListener.Control
  358. }
  359. func (d *DefaultDialer) trackConn(conn net.Conn, err error) (net.Conn, error) {
  360. if d.connectionManager == nil || err != nil {
  361. return conn, err
  362. }
  363. return d.connectionManager.TrackConn(conn), nil
  364. }
  365. func (d *DefaultDialer) trackPacketConn(conn net.PacketConn, err error) (net.PacketConn, error) {
  366. if d.connectionManager == nil || err != nil {
  367. return conn, err
  368. }
  369. return d.connectionManager.TrackPacketConn(conn), nil
  370. }