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  }