resolve.go 2.1 KB

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