dialer.go 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. package dialer
  2. import (
  3. "context"
  4. "net"
  5. "net/netip"
  6. "time"
  7. "github.com/sagernet/sing-box/adapter"
  8. C "github.com/sagernet/sing-box/constant"
  9. "github.com/sagernet/sing-box/experimental/deprecated"
  10. "github.com/sagernet/sing-box/option"
  11. E "github.com/sagernet/sing/common/exceptions"
  12. M "github.com/sagernet/sing/common/metadata"
  13. N "github.com/sagernet/sing/common/network"
  14. "github.com/sagernet/sing/service"
  15. )
  16. type Options struct {
  17. Context context.Context
  18. Options option.DialerOptions
  19. RemoteIsDomain bool
  20. DirectResolver bool
  21. ResolverOnDetour bool
  22. NewDialer bool
  23. DisableEmptyDirectCheck bool
  24. DirectOutbound bool
  25. DefaultOutbound bool
  26. }
  27. // TODO: merge with NewWithOptions
  28. func New(ctx context.Context, options option.DialerOptions, remoteIsDomain bool) (N.Dialer, error) {
  29. return NewWithOptions(Options{
  30. Context: ctx,
  31. Options: options,
  32. RemoteIsDomain: remoteIsDomain,
  33. })
  34. }
  35. func NewWithOptions(options Options) (N.Dialer, error) {
  36. dialOptions := options.Options
  37. var (
  38. dialer N.Dialer
  39. err error
  40. )
  41. hasDetour := dialOptions.Detour != "" || options.DefaultOutbound
  42. if dialOptions.Detour != "" {
  43. outboundManager := service.FromContext[adapter.OutboundManager](options.Context)
  44. if outboundManager == nil {
  45. return nil, E.New("missing outbound manager")
  46. }
  47. dialer = NewDetour(outboundManager, dialOptions.Detour, options.DisableEmptyDirectCheck)
  48. } else if options.DefaultOutbound {
  49. outboundManager := service.FromContext[adapter.OutboundManager](options.Context)
  50. if outboundManager == nil {
  51. return nil, E.New("missing outbound manager")
  52. }
  53. dialer = NewDefaultOutboundDetour(outboundManager)
  54. } else {
  55. dialer, err = NewDefault(options.Context, dialOptions)
  56. if err != nil {
  57. return nil, err
  58. }
  59. }
  60. if options.RemoteIsDomain && (!hasDetour || options.ResolverOnDetour || dialOptions.DomainResolver != nil && dialOptions.DomainResolver.Server != "") {
  61. networkManager := service.FromContext[adapter.NetworkManager](options.Context)
  62. dnsTransport := service.FromContext[adapter.DNSTransportManager](options.Context)
  63. var defaultOptions adapter.NetworkOptions
  64. if networkManager != nil {
  65. defaultOptions = networkManager.DefaultOptions()
  66. }
  67. var (
  68. server string
  69. dnsQueryOptions adapter.DNSQueryOptions
  70. resolveFallbackDelay time.Duration
  71. )
  72. if dialOptions.DomainResolver != nil && dialOptions.DomainResolver.Server != "" {
  73. var transport adapter.DNSTransport
  74. if !options.DirectResolver {
  75. var loaded bool
  76. transport, loaded = dnsTransport.Transport(dialOptions.DomainResolver.Server)
  77. if !loaded {
  78. return nil, E.New("domain resolver not found: " + dialOptions.DomainResolver.Server)
  79. }
  80. }
  81. var strategy C.DomainStrategy
  82. if dialOptions.DomainResolver.Strategy != option.DomainStrategy(C.DomainStrategyAsIS) {
  83. strategy = C.DomainStrategy(dialOptions.DomainResolver.Strategy)
  84. } else if
  85. //nolint:staticcheck
  86. dialOptions.DomainStrategy != option.DomainStrategy(C.DomainStrategyAsIS) {
  87. //nolint:staticcheck
  88. strategy = C.DomainStrategy(dialOptions.DomainStrategy)
  89. deprecated.Report(options.Context, deprecated.OptionLegacyDomainStrategyOptions)
  90. }
  91. server = dialOptions.DomainResolver.Server
  92. dnsQueryOptions = adapter.DNSQueryOptions{
  93. Transport: transport,
  94. Strategy: strategy,
  95. DisableCache: dialOptions.DomainResolver.DisableCache,
  96. DisableOptimisticCache: dialOptions.DomainResolver.DisableOptimisticCache,
  97. RewriteTTL: dialOptions.DomainResolver.RewriteTTL,
  98. ClientSubnet: dialOptions.DomainResolver.ClientSubnet.Build(netip.Prefix{}),
  99. }
  100. resolveFallbackDelay = time.Duration(dialOptions.FallbackDelay)
  101. } else if options.DirectResolver {
  102. return nil, E.New("missing domain resolver for domain server address")
  103. } else {
  104. if defaultOptions.DomainResolver != "" {
  105. dnsQueryOptions = defaultOptions.DomainResolveOptions
  106. transport, loaded := dnsTransport.Transport(defaultOptions.DomainResolver)
  107. if !loaded {
  108. return nil, E.New("default domain resolver not found: " + defaultOptions.DomainResolver)
  109. }
  110. dnsQueryOptions.Transport = transport
  111. resolveFallbackDelay = time.Duration(dialOptions.FallbackDelay)
  112. } else {
  113. transports := dnsTransport.Transports()
  114. if len(transports) < 2 {
  115. dnsQueryOptions.Transport = dnsTransport.Default()
  116. } else if options.NewDialer {
  117. return nil, E.New("missing domain resolver for domain server address")
  118. } else {
  119. deprecated.Report(options.Context, deprecated.OptionMissingDomainResolver)
  120. }
  121. }
  122. if
  123. //nolint:staticcheck
  124. dialOptions.DomainStrategy != option.DomainStrategy(C.DomainStrategyAsIS) {
  125. //nolint:staticcheck
  126. dnsQueryOptions.Strategy = C.DomainStrategy(dialOptions.DomainStrategy)
  127. deprecated.Report(options.Context, deprecated.OptionLegacyDomainStrategyOptions)
  128. }
  129. }
  130. dialer = NewResolveDialer(
  131. options.Context,
  132. dialer,
  133. dialOptions.Detour == "" && !dialOptions.TCPFastOpen,
  134. server,
  135. dnsQueryOptions,
  136. resolveFallbackDelay,
  137. )
  138. }
  139. return dialer, nil
  140. }
  141. type ParallelInterfaceDialer interface {
  142. N.Dialer
  143. DialParallelInterface(ctx context.Context, network string, destination M.Socksaddr, strategy *C.NetworkStrategy, interfaceType []C.InterfaceType, fallbackInterfaceType []C.InterfaceType, fallbackDelay time.Duration) (net.Conn, error)
  144. ListenSerialInterfacePacket(ctx context.Context, destination M.Socksaddr, strategy *C.NetworkStrategy, interfaceType []C.InterfaceType, fallbackInterfaceType []C.InterfaceType, fallbackDelay time.Duration) (net.PacketConn, error)
  145. }
  146. type ParallelNetworkDialer interface {
  147. DialParallelNetwork(ctx context.Context, network string, destination M.Socksaddr, destinationAddresses []netip.Addr, strategy *C.NetworkStrategy, interfaceType []C.InterfaceType, fallbackInterfaceType []C.InterfaceType, fallbackDelay time.Duration) (net.Conn, error)
  148. ListenSerialNetworkPacket(ctx context.Context, destination M.Socksaddr, destinationAddresses []netip.Addr, strategy *C.NetworkStrategy, interfaceType []C.InterfaceType, fallbackInterfaceType []C.InterfaceType, fallbackDelay time.Duration) (net.PacketConn, netip.Addr, error)
  149. }
  150. type PacketDialerWithDestination interface {
  151. ListenPacketWithDestination(ctx context.Context, destination M.Socksaddr) (net.PacketConn, netip.Addr, error)
  152. }