Clean up DNS transports

This commit is contained in:
世界 2026-04-23 01:33:38 +08:00
parent a3fc14f35f
commit 3312b8da50
No known key found for this signature in database
GPG key ID: CD109927C34A63C4
9 changed files with 736 additions and 1031 deletions

View file

@ -49,6 +49,7 @@ type DNSTransport struct {
dnsRouter adapter.DNSRouter
endpointManager adapter.EndpointManager
endpoint *Endpoint
access sync.RWMutex
routePrefixes []netip.Prefix
routes map[string][]adapter.DNSTransport
hosts map[string][]netip.Addr
@ -91,6 +92,12 @@ func (t *DNSTransport) Start(stage adapter.StartStage) error {
}
func (t *DNSTransport) Reset() {
t.access.RLock()
transports := t.collectResolversLocked()
t.access.RUnlock()
for _, transport := range transports {
transport.Reset()
}
}
func (t *DNSTransport) onReconfig(cfg *wgcfg.Config, routerCfg *router.Config, dnsCfg *nDNS.Config) {
@ -101,7 +108,7 @@ func (t *DNSTransport) onReconfig(cfg *wgcfg.Config, routerCfg *router.Config, d
}
func (t *DNSTransport) updateDNSServers(routeConfig *router.Config, dnsConfig *nDNS.Config) error {
t.routePrefixes = buildRoutePrefixes(routeConfig)
routePrefixes := buildRoutePrefixes(routeConfig)
directDialerOnce := sync.OnceValue(func() N.Dialer {
directDialer := common.Must1(dialer.NewDefault(t.ctx, option.DialerOptions{}))
return &DNSDialer{transport: t, fallbackDialer: directDialer}
@ -130,9 +137,19 @@ func (t *DNSTransport) updateDNSServers(routeConfig *router.Config, dnsConfig *n
}
defaultResolvers = append(defaultResolvers, myResolver)
}
t.access.Lock()
oldResolvers := t.collectResolversLocked()
t.routePrefixes = routePrefixes
t.routes = routes
t.hosts = hosts
t.defaultResolvers = defaultResolvers
t.access.Unlock()
for _, transport := range oldResolvers {
transport.Close()
}
if len(defaultResolvers) > 0 {
t.logger.Info("updated ", len(routes), " routes, ", len(hosts), " hosts, default resolvers: ",
strings.Join(common.Map(dnsConfig.DefaultResolvers, func(it *dnstype.Resolver) string { return it.Addr }), " "))
@ -207,7 +224,22 @@ func buildRoutePrefixes(routeConfig *router.Config) []netip.Prefix {
}
func (t *DNSTransport) Close() error {
return nil
t.access.Lock()
transports := t.collectResolversLocked()
t.routePrefixes = nil
t.routes = nil
t.hosts = nil
t.defaultResolvers = nil
t.access.Unlock()
var err error
for _, transport := range transports {
name := "resolver/" + transport.Type() + "[" + transport.Tag() + "]"
err = E.Append(err, transport.Close(), func(err error) error {
return E.Cause(err, "close ", name)
})
}
return err
}
func (t *DNSTransport) Raw() bool {
@ -219,7 +251,15 @@ func (t *DNSTransport) Exchange(ctx context.Context, message *mDNS.Msg) (*mDNS.M
return nil, os.ErrInvalid
}
question := message.Question[0]
addresses, hostsLoaded := t.hosts[question.Name]
t.access.RLock()
hosts := t.hosts
routes := t.routes
defaultResolvers := t.defaultResolvers
acceptDefaultResolvers := t.acceptDefaultResolvers
t.access.RUnlock()
addresses, hostsLoaded := hosts[question.Name]
if hostsLoaded {
switch question.Qtype {
case mDNS.TypeA:
@ -238,7 +278,7 @@ func (t *DNSTransport) Exchange(ctx context.Context, message *mDNS.Msg) (*mDNS.M
}
}
}
for domainSuffix, transports := range t.routes {
for domainSuffix, transports := range routes {
if strings.HasSuffix(question.Name, domainSuffix) {
if len(transports) == 0 {
return &mDNS.Msg{
@ -262,10 +302,10 @@ func (t *DNSTransport) Exchange(ctx context.Context, message *mDNS.Msg) (*mDNS.M
return nil, lastErr
}
}
if t.acceptDefaultResolvers {
if len(t.defaultResolvers) > 0 {
if acceptDefaultResolvers {
if len(defaultResolvers) > 0 {
var lastErr error
for _, resolver := range t.defaultResolvers {
for _, resolver := range defaultResolvers {
response, err := resolver.Exchange(ctx, message)
if err != nil {
lastErr = err
@ -281,6 +321,15 @@ func (t *DNSTransport) Exchange(ctx context.Context, message *mDNS.Msg) (*mDNS.M
return nil, dns.RcodeNameError
}
func (t *DNSTransport) collectResolversLocked() []adapter.DNSTransport {
var transports []adapter.DNSTransport
for _, resolvers := range t.routes {
transports = append(transports, resolvers...)
}
transports = append(transports, t.defaultResolvers...)
return transports
}
type DNSDialer struct {
transport *DNSTransport
fallbackDialer N.Dialer
@ -290,7 +339,8 @@ func (d *DNSDialer) DialContext(ctx context.Context, network string, destination
if destination.IsDomain() {
panic("invalid request here")
}
for _, prefix := range d.transport.routePrefixes {
routePrefixes := d.transport.routePrefixesSnapshot()
for _, prefix := range routePrefixes {
if prefix.Contains(destination.Addr) {
return d.transport.endpoint.DialContext(ctx, network, destination)
}
@ -302,10 +352,17 @@ func (d *DNSDialer) ListenPacket(ctx context.Context, destination M.Socksaddr) (
if destination.IsDomain() {
panic("invalid request here")
}
for _, prefix := range d.transport.routePrefixes {
routePrefixes := d.transport.routePrefixesSnapshot()
for _, prefix := range routePrefixes {
if prefix.Contains(destination.Addr) {
return d.transport.endpoint.ListenPacket(ctx, destination)
}
}
return d.fallbackDialer.ListenPacket(ctx, destination)
}
func (t *DNSTransport) routePrefixesSnapshot() []netip.Prefix {
t.access.RLock()
defer t.access.RUnlock()
return append([]netip.Prefix(nil), t.routePrefixes...)
}