resolve.go 2.3 KB

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