dialer.go 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  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. }
  23. // TODO: merge with NewWithOptions
  24. func New(ctx context.Context, options option.DialerOptions, remoteIsDomain bool) (N.Dialer, error) {
  25. return NewWithOptions(Options{
  26. Context: ctx,
  27. Options: options,
  28. RemoteIsDomain: remoteIsDomain,
  29. })
  30. }
  31. func NewWithOptions(options Options) (N.Dialer, error) {
  32. dialOptions := options.Options
  33. var (
  34. dialer N.Dialer
  35. err error
  36. )
  37. if dialOptions.Detour != "" {
  38. outboundManager := service.FromContext[adapter.OutboundManager](options.Context)
  39. if outboundManager == nil {
  40. return nil, E.New("missing outbound manager")
  41. }
  42. dialer = NewDetour(outboundManager, dialOptions.Detour)
  43. } else {
  44. dialer, err = NewDefault(options.Context, dialOptions)
  45. if err != nil {
  46. return nil, err
  47. }
  48. }
  49. if options.RemoteIsDomain && (dialOptions.Detour == "" || options.ResolverOnDetour) {
  50. networkManager := service.FromContext[adapter.NetworkManager](options.Context)
  51. dnsTransport := service.FromContext[adapter.DNSTransportManager](options.Context)
  52. var defaultOptions adapter.NetworkOptions
  53. if networkManager != nil {
  54. defaultOptions = networkManager.DefaultOptions()
  55. }
  56. var (
  57. server string
  58. dnsQueryOptions adapter.DNSQueryOptions
  59. resolveFallbackDelay time.Duration
  60. )
  61. if dialOptions.DomainResolver != nil && dialOptions.DomainResolver.Server != "" {
  62. var transport adapter.DNSTransport
  63. if !options.DirectResolver {
  64. var loaded bool
  65. transport, loaded = dnsTransport.Transport(dialOptions.DomainResolver.Server)
  66. if !loaded {
  67. return nil, E.New("domain resolver not found: " + dialOptions.DomainResolver.Server)
  68. }
  69. }
  70. var strategy C.DomainStrategy
  71. if dialOptions.DomainResolver.Strategy != option.DomainStrategy(C.DomainStrategyAsIS) {
  72. strategy = C.DomainStrategy(dialOptions.DomainResolver.Strategy)
  73. } else if
  74. //nolint:staticcheck
  75. dialOptions.DomainStrategy != option.DomainStrategy(C.DomainStrategyAsIS) {
  76. //nolint:staticcheck
  77. strategy = C.DomainStrategy(dialOptions.DomainStrategy)
  78. }
  79. server = dialOptions.DomainResolver.Server
  80. dnsQueryOptions = adapter.DNSQueryOptions{
  81. Transport: transport,
  82. Strategy: strategy,
  83. DisableCache: dialOptions.DomainResolver.DisableCache,
  84. RewriteTTL: dialOptions.DomainResolver.RewriteTTL,
  85. ClientSubnet: dialOptions.DomainResolver.ClientSubnet.Build(netip.Prefix{}),
  86. }
  87. resolveFallbackDelay = time.Duration(dialOptions.FallbackDelay)
  88. } else if options.DirectResolver {
  89. return nil, E.New("missing domain resolver for domain server address")
  90. } else if defaultOptions.DomainResolver != "" {
  91. dnsQueryOptions = defaultOptions.DomainResolveOptions
  92. transport, loaded := dnsTransport.Transport(defaultOptions.DomainResolver)
  93. if !loaded {
  94. return nil, E.New("default domain resolver not found: " + defaultOptions.DomainResolver)
  95. }
  96. dnsQueryOptions.Transport = transport
  97. resolveFallbackDelay = time.Duration(dialOptions.FallbackDelay)
  98. } else {
  99. deprecated.Report(options.Context, deprecated.OptionMissingDomainResolver)
  100. }
  101. dialer = NewResolveDialer(
  102. options.Context,
  103. dialer,
  104. dialOptions.Detour == "" && !dialOptions.TCPFastOpen,
  105. server,
  106. dnsQueryOptions,
  107. resolveFallbackDelay,
  108. )
  109. }
  110. return dialer, nil
  111. }
  112. type ParallelInterfaceDialer interface {
  113. N.Dialer
  114. DialParallelInterface(ctx context.Context, network string, destination M.Socksaddr, strategy *C.NetworkStrategy, interfaceType []C.InterfaceType, fallbackInterfaceType []C.InterfaceType, fallbackDelay time.Duration) (net.Conn, error)
  115. ListenSerialInterfacePacket(ctx context.Context, destination M.Socksaddr, strategy *C.NetworkStrategy, interfaceType []C.InterfaceType, fallbackInterfaceType []C.InterfaceType, fallbackDelay time.Duration) (net.PacketConn, error)
  116. }
  117. type ParallelNetworkDialer interface {
  118. 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)
  119. 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)
  120. }