mirror of
https://github.com/shtorm-7/sing-box-extended.git
synced 2026-09-15 21:00:27 +00:00
dns: Fix preferred_by local support for platform local transport
This commit is contained in:
@@ -8,7 +8,6 @@ import (
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
C "github.com/sagernet/sing-box/constant"
|
||||
"github.com/sagernet/sing-box/dns"
|
||||
"github.com/sagernet/sing-box/dns/transport/hosts"
|
||||
"github.com/sagernet/sing-box/dns/transport/mdns"
|
||||
"github.com/sagernet/sing-box/log"
|
||||
"github.com/sagernet/sing-box/option"
|
||||
@@ -33,21 +32,18 @@ var (
|
||||
|
||||
type Transport struct {
|
||||
dns.TransportAdapter
|
||||
ctx context.Context
|
||||
logger logger.ContextLogger
|
||||
hosts *hosts.File
|
||||
dialer N.Dialer
|
||||
preferGo bool
|
||||
fallback bool
|
||||
resolved ResolvedResolver
|
||||
mdnsTransport adapter.DNSTransport
|
||||
dhcpTransport dhcpTransport
|
||||
system systemResolver
|
||||
serverSet atomic.Pointer[localServerSet]
|
||||
serverSetAccess sync.Mutex
|
||||
|
||||
neighborResolver adapter.NeighborResolver
|
||||
neighborSuffixes []string
|
||||
ctx context.Context
|
||||
logger logger.ContextLogger
|
||||
preferredResolver *PreferredDomainResolver
|
||||
dialer N.Dialer
|
||||
preferGo bool
|
||||
fallback bool
|
||||
resolved ResolvedResolver
|
||||
mdnsTransport adapter.DNSTransport
|
||||
dhcpTransport dhcpTransport
|
||||
system systemResolver
|
||||
serverSet atomic.Pointer[localServerSet]
|
||||
serverSetAccess sync.Mutex
|
||||
}
|
||||
|
||||
type dhcpTransport interface {
|
||||
@@ -60,29 +56,24 @@ func NewTransport(ctx context.Context, logger log.ContextLogger, tag string, opt
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
suffixes, err := buildNeighborMatchers(options.NeighborDomain)
|
||||
preferredResolver, err := NewPreferredDomainResolver(ctx, logger, options)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Transport{
|
||||
TransportAdapter: dns.NewTransportAdapterWithLocalOptions(C.DNSTypeLocal, tag, options),
|
||||
ctx: ctx,
|
||||
logger: logger,
|
||||
dialer: transportDialer,
|
||||
preferGo: options.PreferGo,
|
||||
neighborSuffixes: suffixes,
|
||||
TransportAdapter: dns.NewTransportAdapterWithLocalOptions(C.DNSTypeLocal, tag, options),
|
||||
ctx: ctx,
|
||||
logger: logger,
|
||||
preferredResolver: preferredResolver,
|
||||
dialer: transportDialer,
|
||||
preferGo: options.PreferGo,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (t *Transport) Start(stage adapter.StartStage) error {
|
||||
t.preferredResolver.Start(stage)
|
||||
switch stage {
|
||||
case adapter.StartStateInitialize:
|
||||
defaultHosts, err := hosts.NewDefault()
|
||||
if err != nil {
|
||||
t.logger.Warn(err)
|
||||
} else {
|
||||
t.hosts = defaultHosts
|
||||
}
|
||||
if !t.preferGo && isSystemdResolvedManaged() {
|
||||
resolvedResolver, err := NewResolvedResolver(t.ctx, t.logger)
|
||||
if err == nil {
|
||||
@@ -109,10 +100,6 @@ func (t *Transport) Start(stage adapter.StartStage) error {
|
||||
} else {
|
||||
t.mdnsTransport = mdns.NewRawTransport(t.TransportAdapter, t.ctx, t.logger)
|
||||
}
|
||||
router := service.FromContext[adapter.Router](t.ctx)
|
||||
if router != nil {
|
||||
t.neighborResolver = router.NeighborResolver()
|
||||
}
|
||||
fallthrough
|
||||
default:
|
||||
if t.dhcpTransport != nil {
|
||||
@@ -160,12 +147,7 @@ func (t *Transport) Reset() {
|
||||
}
|
||||
|
||||
func (t *Transport) PreferredDomain(domain string) bool {
|
||||
if t.hosts != nil {
|
||||
if len(t.hosts.Lookup(dns.FqdnToDomain(domain))) > 0 {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return t.hasNeighborHost(domain) || mdns.IsLocalDomain(domain)
|
||||
return t.preferredResolver.PreferredDomain(domain)
|
||||
}
|
||||
|
||||
func (t *Transport) Exchange(ctx context.Context, message *mDNS.Msg) (*mDNS.Msg, error) {
|
||||
@@ -185,14 +167,7 @@ func (t *Transport) Exchange(ctx context.Context, message *mDNS.Msg) (*mDNS.Msg,
|
||||
|
||||
func (t *Transport) ExchangeAsync(ctx context.Context, message *mDNS.Msg, callback func(response *mDNS.Msg, err error)) {
|
||||
question := message.Question[0]
|
||||
if t.hosts != nil && (question.Qtype == mDNS.TypeA || question.Qtype == mDNS.TypeAAAA) {
|
||||
addresses := t.hosts.Lookup(dns.FqdnToDomain(question.Name))
|
||||
if len(addresses) > 0 {
|
||||
callback(dns.FixedResponse(message.Id, question, addresses, C.DefaultDNSTTL), nil)
|
||||
return
|
||||
}
|
||||
}
|
||||
response := t.lookupNeighbor(message)
|
||||
response := t.preferredResolver.Lookup(message)
|
||||
if response != nil {
|
||||
callback(response, nil)
|
||||
return
|
||||
|
||||
@@ -24,34 +24,34 @@ func buildNeighborMatchers(domains []string) ([]string, error) {
|
||||
return suffixes, nil
|
||||
}
|
||||
|
||||
func (t *Transport) lookupNeighbor(message *mDNS.Msg) *mDNS.Msg {
|
||||
if t.neighborResolver == nil {
|
||||
func (r *PreferredDomainResolver) lookupNeighbor(message *mDNS.Msg) *mDNS.Msg {
|
||||
if r.neighborResolver == nil {
|
||||
return nil
|
||||
}
|
||||
question := message.Question[0]
|
||||
if question.Qtype != mDNS.TypeA && question.Qtype != mDNS.TypeAAAA {
|
||||
return nil
|
||||
}
|
||||
host := extractNeighborHost(mDNS.CanonicalName(question.Name), t.neighborSuffixes)
|
||||
host := extractNeighborHost(mDNS.CanonicalName(question.Name), r.neighborSuffixes)
|
||||
if host == "" {
|
||||
return nil
|
||||
}
|
||||
addresses := t.neighborResolver.LookupAddresses(host)
|
||||
addresses := r.neighborResolver.LookupAddresses(host)
|
||||
if len(addresses) == 0 {
|
||||
return nil
|
||||
}
|
||||
return dns.FixedResponse(message.Id, question, addresses, C.DefaultDNSTTL)
|
||||
}
|
||||
|
||||
func (t *Transport) hasNeighborHost(domain string) bool {
|
||||
if t.neighborResolver == nil {
|
||||
func (r *PreferredDomainResolver) hasNeighborHost(domain string) bool {
|
||||
if r.neighborResolver == nil {
|
||||
return false
|
||||
}
|
||||
host := extractNeighborHost(domain, t.neighborSuffixes)
|
||||
host := extractNeighborHost(domain, r.neighborSuffixes)
|
||||
if host == "" {
|
||||
return false
|
||||
}
|
||||
return len(t.neighborResolver.LookupAddresses(host)) > 0
|
||||
return len(r.neighborResolver.LookupAddresses(host)) > 0
|
||||
}
|
||||
|
||||
func extractNeighborHost(canonical string, suffixes []string) string {
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
package local
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
C "github.com/sagernet/sing-box/constant"
|
||||
"github.com/sagernet/sing-box/dns"
|
||||
"github.com/sagernet/sing-box/dns/transport/hosts"
|
||||
"github.com/sagernet/sing-box/dns/transport/mdns"
|
||||
"github.com/sagernet/sing-box/option"
|
||||
"github.com/sagernet/sing/common/logger"
|
||||
"github.com/sagernet/sing/service"
|
||||
|
||||
mDNS "github.com/miekg/dns"
|
||||
)
|
||||
|
||||
type PreferredDomainResolver struct {
|
||||
ctx context.Context
|
||||
logger logger.ContextLogger
|
||||
hosts *hosts.File
|
||||
neighborResolver adapter.NeighborResolver
|
||||
neighborSuffixes []string
|
||||
}
|
||||
|
||||
func NewPreferredDomainResolver(ctx context.Context, contextLogger logger.ContextLogger, options option.LocalDNSServerOptions) (*PreferredDomainResolver, error) {
|
||||
suffixes, err := buildNeighborMatchers(options.NeighborDomain)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &PreferredDomainResolver{
|
||||
ctx: ctx,
|
||||
logger: contextLogger,
|
||||
neighborSuffixes: suffixes,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (r *PreferredDomainResolver) Start(stage adapter.StartStage) {
|
||||
switch stage {
|
||||
case adapter.StartStateInitialize:
|
||||
defaultHosts, err := hosts.NewDefault()
|
||||
if err != nil {
|
||||
r.logger.Warn(err)
|
||||
} else {
|
||||
r.hosts = defaultHosts
|
||||
}
|
||||
case adapter.StartStateStart:
|
||||
router := service.FromContext[adapter.Router](r.ctx)
|
||||
if router != nil {
|
||||
r.neighborResolver = router.NeighborResolver()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (r *PreferredDomainResolver) PreferredDomain(domain string) bool {
|
||||
if r.hosts != nil {
|
||||
if len(r.hosts.Lookup(dns.FqdnToDomain(domain))) > 0 {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return r.hasNeighborHost(domain) || mdns.IsLocalDomain(domain)
|
||||
}
|
||||
|
||||
func (r *PreferredDomainResolver) Lookup(message *mDNS.Msg) *mDNS.Msg {
|
||||
question := message.Question[0]
|
||||
if question.Qtype != mDNS.TypeA && question.Qtype != mDNS.TypeAAAA {
|
||||
return nil
|
||||
}
|
||||
if r.hosts != nil {
|
||||
addresses := r.hosts.Lookup(dns.FqdnToDomain(question.Name))
|
||||
if len(addresses) > 0 {
|
||||
return dns.FixedResponse(message.Id, question, addresses, C.DefaultDNSTTL)
|
||||
}
|
||||
}
|
||||
return r.lookupNeighbor(message)
|
||||
}
|
||||
Reference in New Issue
Block a user