@ -22,6 +22,7 @@ import (
"golang.org/x/sys/windows/registry"
"golang.zx2c4.com/wireguard/windows/tunnel/winipcfg"
"tailscale.com/atomicfile"
"tailscale.com/control/controlknobs"
"tailscale.com/envknob"
"tailscale.com/health"
"tailscale.com/types/logger"
@ -38,6 +39,7 @@ var configureWSL = envknob.RegisterBool("TS_DEBUG_CONFIGURE_WSL")
type windowsManager struct {
logf logger . Logf
guid string
knobs * controlknobs . Knobs // or nil
nrptDB * nrptRuleDatabase
wslManager * wslManager
@ -45,10 +47,14 @@ type windowsManager struct {
closing bool
}
func NewOSConfigurator ( logf logger . Logf , health * health . Tracker , interfaceName string ) ( OSConfigurator , error ) {
// NewOSConfigurator created a new OS configurator.
//
// The health tracker and the knobs may be nil.
func NewOSConfigurator ( logf logger . Logf , health * health . Tracker , knobs * controlknobs . Knobs , interfaceName string ) ( OSConfigurator , error ) {
ret := & windowsManager {
logf : logf ,
guid : interfaceName ,
knobs : knobs ,
wslManager : newWSLManager ( logf , health ) ,
}
@ -288,6 +294,10 @@ func (m *windowsManager) setPrimaryDNS(resolvers []netip.Addr, domains []dnsname
return nil
}
func ( m * windowsManager ) disableLocalDNSOverrideViaNRPT ( ) bool {
return m . knobs != nil && m . knobs . DisableLocalDNSOverrideViaNRPT . Load ( )
}
func ( m * windowsManager ) SetDNS ( cfg OSConfig ) error {
// We can configure Windows DNS in one of two ways:
//
@ -322,7 +332,17 @@ func (m *windowsManager) SetDNS(cfg OSConfig) error {
}
if len ( cfg . MatchDomains ) == 0 {
if err := m . setSplitDNS ( nil , nil ) ; err != nil {
var resolvers [ ] netip . Addr
var domains [ ] dnsname . FQDN
if ! m . disableLocalDNSOverrideViaNRPT ( ) {
// Create a default catch-all rule to make ourselves the actual primary resolver.
// Without this rule, Windows 8.1 and newer devices issue parallel DNS requests to DNS servers
// associated with all network adapters, even when "Override local DNS" is enabled and/or
// a Mullvad exit node is being used, resulting in DNS leaks.
resolvers = cfg . Nameservers
domains = [ ] dnsname . FQDN { "." }
}
if err := m . setSplitDNS ( resolvers , domains ) ; err != nil {
return err
}
if err := m . setHosts ( nil ) ; err != nil {
@ -331,8 +351,6 @@ func (m *windowsManager) SetDNS(cfg OSConfig) error {
if err := m . setPrimaryDNS ( cfg . Nameservers , cfg . SearchDomains ) ; err != nil {
return err
}
} else if m . nrptDB == nil {
return errors . New ( "cannot set per-domain resolvers on Windows 7" )
} else {
if err := m . setSplitDNS ( cfg . Nameservers , cfg . MatchDomains ) ; err != nil {
return err