Compare commits

...

2 Commits

Author SHA1 Message Date
Viktor Liu
4b4d00d110 Add default case 2025-11-21 14:19:15 +01:00
Viktor Liu
1dcd92c5d1 Use Go's resolver for darwin for control plane and ICE traffic 2025-11-21 13:53:50 +01:00
4 changed files with 59 additions and 3 deletions

View File

@@ -29,7 +29,9 @@ func WithCustomDialer(_ bool, _ string) grpc.DialOption {
// the custom dialer requires root permissions which are not required for use cases run as non-root
if currentUser.Uid != "0" {
log.Debug("Not running as root, using standard dialer")
dialer := &net.Dialer{}
dialer := &net.Dialer{
Resolver: nbnet.NewResolver(),
}
return dialer.DialContext(ctx, "tcp", addr)
}
}

View File

@@ -18,6 +18,7 @@ import (
"github.com/pion/transport/v3/stdnet"
"github.com/netbirdio/netbird/client/iface/netstack"
nbnet "github.com/netbirdio/netbird/client/net"
)
const (
@@ -42,6 +43,8 @@ type Net struct {
// ctx is the context for network operations that supports cancellation
ctx context.Context
resolver *net.Resolver
}
// NewNetWithDiscover creates a new StdNet instance.
@@ -52,6 +55,7 @@ func NewNetWithDiscover(ctx context.Context, iFaceDiscover ExternalIFaceDiscover
n := &Net{
interfaceFilter: InterfaceFilter(disallowList),
ctx: ctx,
resolver: nbnet.NewResolver(),
}
// current ExternalIFaceDiscover implement in android-client https://github.dev/netbirdio/android-client
// so in android cli use pionDiscover
@@ -72,6 +76,7 @@ func NewNet(ctx context.Context, disallowList []string) (*Net, error) {
iFaceDiscover: pionDiscover{},
interfaceFilter: InterfaceFilter(disallowList),
ctx: ctx,
resolver: nbnet.NewResolver(),
}
return n, n.UpdateInterfaces()
}
@@ -110,7 +115,7 @@ func (n *Net) resolveAddr(network, address string) (netip.AddrPort, error) {
ctx, cancel := context.WithTimeout(n.ctx, dnsResolveTimeout)
defer cancel()
addrs, err := net.DefaultResolver.LookupNetIP(ctx, ipNet, host)
addrs, err := n.resolver.LookupNetIP(ctx, ipNet, host)
if err != nil {
return netip.AddrPort{}, err
}

View File

@@ -13,7 +13,9 @@ type Dialer struct {
// NewDialer returns a customized net.Dialer with overridden Control method
func NewDialer() *Dialer {
dialer := &Dialer{
Dialer: &net.Dialer{},
Dialer: &net.Dialer{
Resolver: NewResolver(),
},
}
dialer.init()
return dialer

47
client/net/resolver.go Normal file
View File

@@ -0,0 +1,47 @@
package net
import (
"net"
"os"
"runtime"
"strings"
log "github.com/sirupsen/logrus"
)
const (
// EnvResolver is the environment variable to control DNS resolver behavior
// Values: "system" (use system resolver), "go" (use pure Go resolver), empty (auto-detect)
EnvResolver = "NB_DNS_RESOLVER"
)
// NewResolver creates a DNS resolver with appropriate settings based on platform and configuration.
// On Darwin (macOS), it defaults to the pure Go resolver to avoid getaddrinfo hangs after sleep/wake.
// This is particularly important for connections using this package's Dialer, which bypasses the NetBird
// overlay network for control plane traffic. Since these connections target external infrastructure
// (management, signal, relay servers), it is safe to ignore split DNS configurations that would
// normally be provided by the system resolver.
// On other platforms, it uses the system resolver (cgo).
// This behavior can be overridden using the NB_DNS_RESOLVER environment variable or GODEBUG.
func NewResolver() *net.Resolver {
if resolver := os.Getenv(EnvResolver); resolver != "" {
switch strings.ToLower(resolver) {
case "system":
return net.DefaultResolver
case "go":
return &net.Resolver{
PreferGo: true,
}
default:
log.Debugf("Invalid %s value: %s, using platform defaults", EnvResolver, resolver)
}
}
if runtime.GOOS == "darwin" {
return &net.Resolver{
PreferGo: true,
}
}
return net.DefaultResolver
}