resolve.go 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  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. M "github.com/sagernet/sing/common/metadata"
  11. N "github.com/sagernet/sing/common/network"
  12. )
  13. type ResolveDialer struct {
  14. dialer N.Dialer
  15. router adapter.Router
  16. strategy dns.DomainStrategy
  17. fallbackDelay time.Duration
  18. }
  19. func NewResolveDialer(router adapter.Router, dialer N.Dialer, strategy dns.DomainStrategy, fallbackDelay time.Duration) *ResolveDialer {
  20. return &ResolveDialer{
  21. dialer,
  22. router,
  23. strategy,
  24. fallbackDelay,
  25. }
  26. }
  27. func (d *ResolveDialer) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
  28. if !destination.IsFqdn() {
  29. return d.dialer.DialContext(ctx, network, destination)
  30. }
  31. ctx, metadata := adapter.AppendContext(ctx)
  32. ctx = log.ContextWithOverrideLevel(ctx, log.LevelDebug)
  33. metadata.Destination = destination
  34. metadata.Domain = ""
  35. var addresses []netip.Addr
  36. var err error
  37. if d.strategy == dns.DomainStrategyAsIS {
  38. addresses, err = d.router.LookupDefault(ctx, destination.Fqdn)
  39. } else {
  40. addresses, err = d.router.Lookup(ctx, destination.Fqdn, d.strategy)
  41. }
  42. if err != nil {
  43. return nil, err
  44. }
  45. return N.DialParallel(ctx, d.dialer, network, destination, addresses, d.strategy == dns.DomainStrategyPreferIPv6, d.fallbackDelay)
  46. }
  47. func (d *ResolveDialer) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
  48. if !destination.IsFqdn() || destination.Fqdn == "" {
  49. return d.dialer.ListenPacket(ctx, destination)
  50. }
  51. ctx, metadata := adapter.AppendContext(ctx)
  52. ctx = log.ContextWithOverrideLevel(ctx, log.LevelDebug)
  53. metadata.Destination = destination
  54. metadata.Domain = ""
  55. var addresses []netip.Addr
  56. var err error
  57. if d.strategy == dns.DomainStrategyAsIS {
  58. addresses, err = d.router.LookupDefault(ctx, destination.Fqdn)
  59. } else {
  60. addresses, err = d.router.Lookup(ctx, destination.Fqdn, d.strategy)
  61. }
  62. if err != nil {
  63. return nil, err
  64. }
  65. conn, err := N.ListenSerial(ctx, d.dialer, destination, addresses)
  66. if err != nil {
  67. return nil, err
  68. }
  69. return NewResolvePacketConn(ctx, d.router, d.strategy, conn), nil
  70. }
  71. func (d *ResolveDialer) Upstream() any {
  72. return d.dialer
  73. }