resolve.go 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. package dialer
  2. import (
  3. "context"
  4. "net"
  5. "net/netip"
  6. "time"
  7. "github.com/sagernet/sing-box/adapter"
  8. "github.com/sagernet/sing-box/log"
  9. "github.com/sagernet/sing-dns"
  10. "github.com/sagernet/sing/common/bufio"
  11. M "github.com/sagernet/sing/common/metadata"
  12. N "github.com/sagernet/sing/common/network"
  13. )
  14. type ResolveDialer struct {
  15. dialer N.Dialer
  16. parallel bool
  17. router adapter.Router
  18. strategy dns.DomainStrategy
  19. fallbackDelay time.Duration
  20. }
  21. func NewResolveDialer(router adapter.Router, dialer N.Dialer, parallel bool, strategy dns.DomainStrategy, fallbackDelay time.Duration) *ResolveDialer {
  22. return &ResolveDialer{
  23. dialer,
  24. parallel,
  25. router,
  26. strategy,
  27. fallbackDelay,
  28. }
  29. }
  30. func (d *ResolveDialer) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
  31. if !destination.IsFqdn() {
  32. return d.dialer.DialContext(ctx, network, destination)
  33. }
  34. ctx, metadata := adapter.ExtendContext(ctx)
  35. ctx = log.ContextWithOverrideLevel(ctx, log.LevelDebug)
  36. metadata.Destination = destination
  37. metadata.Domain = ""
  38. var addresses []netip.Addr
  39. var err error
  40. if d.strategy == dns.DomainStrategyAsIS {
  41. addresses, err = d.router.LookupDefault(ctx, destination.Fqdn)
  42. } else {
  43. addresses, err = d.router.Lookup(ctx, destination.Fqdn, d.strategy)
  44. }
  45. if err != nil {
  46. return nil, err
  47. }
  48. if d.parallel {
  49. return N.DialParallel(ctx, d.dialer, network, destination, addresses, d.strategy == dns.DomainStrategyPreferIPv6, d.fallbackDelay)
  50. } else {
  51. return N.DialSerial(ctx, d.dialer, network, destination, addresses)
  52. }
  53. }
  54. func (d *ResolveDialer) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
  55. if !destination.IsFqdn() {
  56. return d.dialer.ListenPacket(ctx, destination)
  57. }
  58. ctx, metadata := adapter.ExtendContext(ctx)
  59. ctx = log.ContextWithOverrideLevel(ctx, log.LevelDebug)
  60. metadata.Destination = destination
  61. metadata.Domain = ""
  62. var addresses []netip.Addr
  63. var err error
  64. if d.strategy == dns.DomainStrategyAsIS {
  65. addresses, err = d.router.LookupDefault(ctx, destination.Fqdn)
  66. } else {
  67. addresses, err = d.router.Lookup(ctx, destination.Fqdn, d.strategy)
  68. }
  69. if err != nil {
  70. return nil, err
  71. }
  72. conn, destinationAddress, err := N.ListenSerial(ctx, d.dialer, destination, addresses)
  73. if err != nil {
  74. return nil, err
  75. }
  76. return bufio.NewNATPacketConn(bufio.NewPacketConn(conn), M.SocksaddrFrom(destinationAddress, destination.Port), destination), nil
  77. }
  78. func (d *ResolveDialer) Upstream() any {
  79. return d.dialer
  80. }