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