transport_dialer.go 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. package dns
  2. import (
  3. "context"
  4. "net"
  5. "time"
  6. "github.com/sagernet/sing-box/adapter"
  7. "github.com/sagernet/sing-box/common/dialer"
  8. C "github.com/sagernet/sing-box/constant"
  9. "github.com/sagernet/sing-box/option"
  10. E "github.com/sagernet/sing/common/exceptions"
  11. M "github.com/sagernet/sing/common/metadata"
  12. N "github.com/sagernet/sing/common/network"
  13. "github.com/sagernet/sing/service"
  14. )
  15. func NewLocalDialer(ctx context.Context, options option.LocalDNSServerOptions) (N.Dialer, error) {
  16. if options.LegacyDefaultDialer {
  17. return dialer.NewDefaultOutbound(ctx), nil
  18. } else {
  19. return dialer.NewWithOptions(dialer.Options{
  20. Context: ctx,
  21. Options: options.DialerOptions,
  22. DirectResolver: true,
  23. LegacyDNSDialer: options.Legacy,
  24. })
  25. }
  26. }
  27. func NewRemoteDialer(ctx context.Context, options option.RemoteDNSServerOptions) (N.Dialer, error) {
  28. if options.LegacyDefaultDialer {
  29. transportDialer := dialer.NewDefaultOutbound(ctx)
  30. if options.LegacyAddressResolver != "" {
  31. transport := service.FromContext[adapter.DNSTransportManager](ctx)
  32. resolverTransport, loaded := transport.Transport(options.LegacyAddressResolver)
  33. if !loaded {
  34. return nil, E.New("address resolver not found: ", options.LegacyAddressResolver)
  35. }
  36. transportDialer = newTransportDialer(transportDialer, service.FromContext[adapter.DNSRouter](ctx), resolverTransport, C.DomainStrategy(options.LegacyAddressStrategy), time.Duration(options.LegacyAddressFallbackDelay))
  37. } else if options.ServerIsDomain() {
  38. return nil, E.New("missing address resolver for server: ", options.Server)
  39. }
  40. return transportDialer, nil
  41. } else {
  42. return dialer.NewWithOptions(dialer.Options{
  43. Context: ctx,
  44. Options: options.DialerOptions,
  45. RemoteIsDomain: options.ServerIsDomain(),
  46. DirectResolver: true,
  47. LegacyDNSDialer: options.Legacy,
  48. })
  49. }
  50. }
  51. type legacyTransportDialer struct {
  52. dialer N.Dialer
  53. dnsRouter adapter.DNSRouter
  54. transport adapter.DNSTransport
  55. strategy C.DomainStrategy
  56. fallbackDelay time.Duration
  57. }
  58. func newTransportDialer(dialer N.Dialer, dnsRouter adapter.DNSRouter, transport adapter.DNSTransport, strategy C.DomainStrategy, fallbackDelay time.Duration) *legacyTransportDialer {
  59. return &legacyTransportDialer{
  60. dialer,
  61. dnsRouter,
  62. transport,
  63. strategy,
  64. fallbackDelay,
  65. }
  66. }
  67. func (d *legacyTransportDialer) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
  68. if destination.IsIP() {
  69. return d.dialer.DialContext(ctx, network, destination)
  70. }
  71. addresses, err := d.dnsRouter.Lookup(ctx, destination.Fqdn, adapter.DNSQueryOptions{
  72. Transport: d.transport,
  73. Strategy: d.strategy,
  74. })
  75. if err != nil {
  76. return nil, err
  77. }
  78. return N.DialParallel(ctx, d.dialer, network, destination, addresses, d.strategy == C.DomainStrategyPreferIPv6, d.fallbackDelay)
  79. }
  80. func (d *legacyTransportDialer) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
  81. if destination.IsIP() {
  82. return d.dialer.ListenPacket(ctx, destination)
  83. }
  84. addresses, err := d.dnsRouter.Lookup(ctx, destination.Fqdn, adapter.DNSQueryOptions{
  85. Transport: d.transport,
  86. Strategy: d.strategy,
  87. })
  88. if err != nil {
  89. return nil, err
  90. }
  91. conn, _, err := N.ListenSerial(ctx, d.dialer, destination, addresses)
  92. return conn, err
  93. }
  94. func (d *legacyTransportDialer) Upstream() any {
  95. return d.dialer
  96. }