github.com/inazumav/sing-box@v0.0.0-20230926072359-ab51429a14f1/common/dialer/resolve.go (about) 1 package dialer 2 3 import ( 4 "context" 5 "net" 6 "net/netip" 7 "time" 8 9 "github.com/inazumav/sing-box/adapter" 10 "github.com/inazumav/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 router adapter.Router 20 strategy dns.DomainStrategy 21 fallbackDelay time.Duration 22 } 23 24 func NewResolveDialer(router adapter.Router, dialer N.Dialer, strategy dns.DomainStrategy, fallbackDelay time.Duration) *ResolveDialer { 25 return &ResolveDialer{ 26 dialer, 27 router, 28 strategy, 29 fallbackDelay, 30 } 31 } 32 33 func (d *ResolveDialer) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) { 34 if !destination.IsFqdn() { 35 return d.dialer.DialContext(ctx, network, destination) 36 } 37 ctx, metadata := adapter.AppendContext(ctx) 38 ctx = log.ContextWithOverrideLevel(ctx, log.LevelDebug) 39 metadata.Destination = destination 40 metadata.Domain = "" 41 var addresses []netip.Addr 42 var err error 43 if d.strategy == dns.DomainStrategyAsIS { 44 addresses, err = d.router.LookupDefault(ctx, destination.Fqdn) 45 } else { 46 addresses, err = d.router.Lookup(ctx, destination.Fqdn, d.strategy) 47 } 48 if err != nil { 49 return nil, err 50 } 51 return N.DialParallel(ctx, d.dialer, network, destination, addresses, d.strategy == dns.DomainStrategyPreferIPv6, d.fallbackDelay) 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.AppendContext(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 79 func (d *ResolveDialer) Upstream() any { 80 return d.dialer 81 }