[client] Support wildcard DNS on iOS (#3979)

This commit is contained in:
Viktor Liu 2025-06-16 18:33:51 +02:00 committed by GitHub
parent bfa5c21d2d
commit 8df8c1012f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 35 additions and 9 deletions

View File

@ -84,3 +84,10 @@ func (u *upstreamResolver) isLocalResolver(upstream string) bool {
} }
return false return false
} }
func GetClientPrivate(ip netip.Addr, interfaceName string, dialTimeout time.Duration) (*dns.Client, error) {
return &dns.Client{
Timeout: dialTimeout,
Net: "udp",
}, nil
}

View File

@ -36,3 +36,10 @@ func newUpstreamResolver(
func (u *upstreamResolver) exchange(ctx context.Context, upstream string, r *dns.Msg) (rm *dns.Msg, t time.Duration, err error) { func (u *upstreamResolver) exchange(ctx context.Context, upstream string, r *dns.Msg) (rm *dns.Msg, t time.Duration, err error) {
return ExchangeWithFallback(ctx, &dns.Client{}, r, upstream) return ExchangeWithFallback(ctx, &dns.Client{}, r, upstream)
} }
func GetClientPrivate(ip netip.Addr, interfaceName string, dialTimeout time.Duration) (*dns.Client, error) {
return &dns.Client{
Timeout: dialTimeout,
Net: "udp",
}, nil
}

View File

@ -4,7 +4,6 @@ import (
"context" "context"
"fmt" "fmt"
"reflect" "reflect"
"runtime"
"time" "time"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
@ -23,7 +22,7 @@ import (
const ( const (
handlerTypeDynamic = iota handlerTypeDynamic = iota
handlerTypeDomain handlerTypeDnsInterceptor
handlerTypeStatic handlerTypeStatic
) )
@ -566,13 +565,14 @@ func HandlerFromRoute(
useNewDNSRoute bool, useNewDNSRoute bool,
) RouteHandler { ) RouteHandler {
switch handlerType(rt, useNewDNSRoute) { switch handlerType(rt, useNewDNSRoute) {
case handlerTypeDomain: case handlerTypeDnsInterceptor:
return dnsinterceptor.New( return dnsinterceptor.New(
rt, rt,
routeRefCounter, routeRefCounter,
allowedIPsRefCounter, allowedIPsRefCounter,
statusRecorder, statusRecorder,
dnsServer, dnsServer,
wgInterface,
peerStore, peerStore,
) )
case handlerTypeDynamic: case handlerTypeDynamic:
@ -596,8 +596,8 @@ func handlerType(rt *route.Route, useNewDNSRoute bool) int {
return handlerTypeStatic return handlerTypeStatic
} }
if useNewDNSRoute && runtime.GOOS != "ios" { if useNewDNSRoute {
return handlerTypeDomain return handlerTypeDnsInterceptor
} }
return handlerTypeDynamic return handlerTypeDynamic
} }

View File

@ -12,6 +12,7 @@ import (
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
nberrors "github.com/netbirdio/netbird/client/errors" nberrors "github.com/netbirdio/netbird/client/errors"
"github.com/netbirdio/netbird/client/iface/wgaddr"
nbdns "github.com/netbirdio/netbird/client/internal/dns" nbdns "github.com/netbirdio/netbird/client/internal/dns"
"github.com/netbirdio/netbird/client/internal/dnsfwd" "github.com/netbirdio/netbird/client/internal/dnsfwd"
"github.com/netbirdio/netbird/client/internal/peer" "github.com/netbirdio/netbird/client/internal/peer"
@ -23,6 +24,11 @@ import (
type domainMap map[domain.Domain][]netip.Prefix type domainMap map[domain.Domain][]netip.Prefix
type wgInterface interface {
Name() string
Address() wgaddr.Address
}
type DnsInterceptor struct { type DnsInterceptor struct {
mu sync.RWMutex mu sync.RWMutex
route *route.Route route *route.Route
@ -32,6 +38,7 @@ type DnsInterceptor struct {
dnsServer nbdns.Server dnsServer nbdns.Server
currentPeerKey string currentPeerKey string
interceptedDomains domainMap interceptedDomains domainMap
wgInterface wgInterface
peerStore *peerstore.Store peerStore *peerstore.Store
} }
@ -41,6 +48,7 @@ func New(
allowedIPsRefCounter *refcounter.AllowedIPsRefCounter, allowedIPsRefCounter *refcounter.AllowedIPsRefCounter,
statusRecorder *peer.Status, statusRecorder *peer.Status,
dnsServer nbdns.Server, dnsServer nbdns.Server,
wgInterface wgInterface,
peerStore *peerstore.Store, peerStore *peerstore.Store,
) *DnsInterceptor { ) *DnsInterceptor {
return &DnsInterceptor{ return &DnsInterceptor{
@ -49,6 +57,7 @@ func New(
allowedIPsRefcounter: allowedIPsRefCounter, allowedIPsRefcounter: allowedIPsRefCounter,
statusRecorder: statusRecorder, statusRecorder: statusRecorder,
dnsServer: dnsServer, dnsServer: dnsServer,
wgInterface: wgInterface,
interceptedDomains: make(domainMap), interceptedDomains: make(domainMap),
peerStore: peerStore, peerStore: peerStore,
} }
@ -162,13 +171,16 @@ func (d *DnsInterceptor) ServeDNS(w dns.ResponseWriter, r *dns.Msg) {
return return
} }
client, err := nbdns.GetClientPrivate(d.wgInterface.Address().IP, d.wgInterface.Name(), nbdns.UpstreamTimeout)
if err != nil {
d.writeDNSError(w, r, fmt.Sprintf("create DNS client: %v", err))
return
}
if r.Extra == nil { if r.Extra == nil {
r.MsgHdr.AuthenticatedData = true r.MsgHdr.AuthenticatedData = true
} }
client := &dns.Client{
Timeout: nbdns.UpstreamTimeout,
Net: "udp",
}
upstream := fmt.Sprintf("%s:%d", upstreamIP.String(), dnsfwd.ListenPort) upstream := fmt.Sprintf("%s:%d", upstreamIP.String(), dnsfwd.ListenPort)
reply, _, err := nbdns.ExchangeWithFallback(context.TODO(), client, r, upstream) reply, _, err := nbdns.ExchangeWithFallback(context.TODO(), client, r, upstream)
if err != nil { if err != nil {