mirror of
https://github.com/SagerNet/sing-box.git
synced 2024-11-25 01:51:29 +00:00
Implement resolve(server)
This commit is contained in:
parent
5bb2caa50c
commit
c616ef800f
|
@ -50,12 +50,14 @@ type InboundContext struct {
|
||||||
// Deprecated
|
// Deprecated
|
||||||
InboundOptions option.InboundOptions
|
InboundOptions option.InboundOptions
|
||||||
UDPDisableDomainUnmapping bool
|
UDPDisableDomainUnmapping bool
|
||||||
DestinationAddresses []netip.Addr
|
DNSServer string
|
||||||
SourceGeoIPCode string
|
|
||||||
GeoIPCode string
|
DestinationAddresses []netip.Addr
|
||||||
ProcessInfo *process.Info
|
SourceGeoIPCode string
|
||||||
QueryType uint16
|
GeoIPCode string
|
||||||
FakeIP bool
|
ProcessInfo *process.Info
|
||||||
|
QueryType uint16
|
||||||
|
FakeIP bool
|
||||||
|
|
||||||
// rule cache
|
// rule cache
|
||||||
|
|
||||||
|
|
|
@ -584,7 +584,7 @@ func (r *Router) actionSniff(
|
||||||
|
|
||||||
func (r *Router) actionResolve(ctx context.Context, metadata *adapter.InboundContext, action *rule.RuleActionResolve) error {
|
func (r *Router) actionResolve(ctx context.Context, metadata *adapter.InboundContext, action *rule.RuleActionResolve) error {
|
||||||
if metadata.Destination.IsFqdn() {
|
if metadata.Destination.IsFqdn() {
|
||||||
// TODO: check if WithContext is necessary
|
metadata.DNSServer = action.Server
|
||||||
addresses, err := r.Lookup(adapter.WithContext(ctx, metadata), metadata.Destination.Fqdn, action.Strategy)
|
addresses, err := r.Lookup(adapter.WithContext(ctx, metadata), metadata.Destination.Fqdn, action.Strategy)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -185,41 +185,7 @@ func (r *Router) Lookup(ctx context.Context, domain string, strategy dns.DomainS
|
||||||
cached bool
|
cached bool
|
||||||
err error
|
err error
|
||||||
)
|
)
|
||||||
responseAddrs, cached = r.dnsClient.LookupCache(ctx, domain, strategy)
|
printResult := func() {
|
||||||
if cached {
|
|
||||||
if len(responseAddrs) == 0 {
|
|
||||||
return nil, dns.RCodeNameError
|
|
||||||
}
|
|
||||||
return responseAddrs, nil
|
|
||||||
}
|
|
||||||
r.dnsLogger.DebugContext(ctx, "lookup domain ", domain)
|
|
||||||
ctx, metadata := adapter.ExtendContext(ctx)
|
|
||||||
metadata.Destination = M.Socksaddr{}
|
|
||||||
metadata.Domain = domain
|
|
||||||
var (
|
|
||||||
transport dns.Transport
|
|
||||||
options dns.QueryOptions
|
|
||||||
rule adapter.DNSRule
|
|
||||||
ruleIndex int
|
|
||||||
)
|
|
||||||
ruleIndex = -1
|
|
||||||
for {
|
|
||||||
dnsCtx := adapter.OverrideContext(ctx)
|
|
||||||
var addressLimit bool
|
|
||||||
transport, options, rule, ruleIndex = r.matchDNS(ctx, false, ruleIndex, true)
|
|
||||||
if strategy != dns.DomainStrategyAsIS {
|
|
||||||
options.Strategy = strategy
|
|
||||||
}
|
|
||||||
if rule != nil && rule.WithAddressLimit() {
|
|
||||||
addressLimit = true
|
|
||||||
responseAddrs, err = r.dnsClient.LookupWithResponseCheck(dnsCtx, transport, domain, options, func(responseAddrs []netip.Addr) bool {
|
|
||||||
metadata.DestinationAddresses = responseAddrs
|
|
||||||
return rule.MatchAddressLimit(metadata)
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
addressLimit = false
|
|
||||||
responseAddrs, err = r.dnsClient.Lookup(dnsCtx, transport, domain, options)
|
|
||||||
}
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, dns.ErrResponseRejectedCached) {
|
if errors.Is(err, dns.ErrResponseRejectedCached) {
|
||||||
r.dnsLogger.DebugContext(ctx, "response rejected for ", domain, " (cached)")
|
r.dnsLogger.DebugContext(ctx, "response rejected for ", domain, " (cached)")
|
||||||
|
@ -232,10 +198,63 @@ func (r *Router) Lookup(ctx context.Context, domain string, strategy dns.DomainS
|
||||||
r.dnsLogger.ErrorContext(ctx, "lookup failed for ", domain, ": empty result")
|
r.dnsLogger.ErrorContext(ctx, "lookup failed for ", domain, ": empty result")
|
||||||
err = dns.RCodeNameError
|
err = dns.RCodeNameError
|
||||||
}
|
}
|
||||||
if !addressLimit || err == nil {
|
}
|
||||||
break
|
responseAddrs, cached = r.dnsClient.LookupCache(ctx, domain, strategy)
|
||||||
|
if cached {
|
||||||
|
if len(responseAddrs) == 0 {
|
||||||
|
return nil, dns.RCodeNameError
|
||||||
|
}
|
||||||
|
return responseAddrs, nil
|
||||||
|
}
|
||||||
|
r.dnsLogger.DebugContext(ctx, "lookup domain ", domain)
|
||||||
|
ctx, metadata := adapter.ExtendContext(ctx)
|
||||||
|
metadata.Destination = M.Socksaddr{}
|
||||||
|
metadata.Domain = domain
|
||||||
|
if metadata.DNSServer != "" {
|
||||||
|
transport, loaded := r.transportMap[metadata.DNSServer]
|
||||||
|
if !loaded {
|
||||||
|
return nil, E.New("transport not found: ", metadata.DNSServer)
|
||||||
|
}
|
||||||
|
if strategy == dns.DomainStrategyAsIS {
|
||||||
|
if transportDomainStrategy, loaded := r.transportDomainStrategy[transport]; loaded {
|
||||||
|
strategy = transportDomainStrategy
|
||||||
|
} else {
|
||||||
|
strategy = r.defaultDomainStrategy
|
||||||
|
}
|
||||||
|
}
|
||||||
|
responseAddrs, err = r.dnsClient.Lookup(ctx, transport, domain, dns.QueryOptions{Strategy: strategy})
|
||||||
|
} else {
|
||||||
|
var (
|
||||||
|
transport dns.Transport
|
||||||
|
options dns.QueryOptions
|
||||||
|
rule adapter.DNSRule
|
||||||
|
ruleIndex int
|
||||||
|
)
|
||||||
|
ruleIndex = -1
|
||||||
|
for {
|
||||||
|
dnsCtx := adapter.OverrideContext(ctx)
|
||||||
|
var addressLimit bool
|
||||||
|
transport, options, rule, ruleIndex = r.matchDNS(ctx, false, ruleIndex, true)
|
||||||
|
if strategy != dns.DomainStrategyAsIS {
|
||||||
|
options.Strategy = strategy
|
||||||
|
}
|
||||||
|
if rule != nil && rule.WithAddressLimit() {
|
||||||
|
addressLimit = true
|
||||||
|
responseAddrs, err = r.dnsClient.LookupWithResponseCheck(dnsCtx, transport, domain, options, func(responseAddrs []netip.Addr) bool {
|
||||||
|
metadata.DestinationAddresses = responseAddrs
|
||||||
|
return rule.MatchAddressLimit(metadata)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
addressLimit = false
|
||||||
|
responseAddrs, err = r.dnsClient.Lookup(dnsCtx, transport, domain, options)
|
||||||
|
}
|
||||||
|
if !addressLimit || err == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
printResult()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
printResult()
|
||||||
if len(responseAddrs) > 0 {
|
if len(responseAddrs) > 0 {
|
||||||
r.dnsLogger.InfoContext(ctx, "lookup succeed for ", domain, ": ", strings.Join(F.MapToString(responseAddrs), " "))
|
r.dnsLogger.InfoContext(ctx, "lookup succeed for ", domain, ": ", strings.Join(F.MapToString(responseAddrs), " "))
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue