mirror of
https://github.com/tailscale/tailscale.git
synced 2025-10-09 08:01:31 +00:00
net/dns,docs/windows/policy,util/syspolicy: register Tailscale IP addresses in AD DNS if required by policy
In this PR, we make DNS registration behavior configurable via the EnableDNSRegistration policy setting. We keep the default behavior unchanged, but allow admins to either enforce DNS registration and dynamic DNS updates for the Tailscale interface, or prevent Tailscale from modifying the settings configured in the network adapter's properties or by other means. Updates #14917 Signed-off-by: Nick Khyl <nickk@tailscale.com>
This commit is contained in:
@@ -29,6 +29,9 @@ import (
|
||||
"tailscale.com/health"
|
||||
"tailscale.com/types/logger"
|
||||
"tailscale.com/util/dnsname"
|
||||
"tailscale.com/util/syspolicy"
|
||||
"tailscale.com/util/syspolicy/rsop"
|
||||
"tailscale.com/util/syspolicy/setting"
|
||||
"tailscale.com/util/winutil"
|
||||
)
|
||||
|
||||
@@ -45,6 +48,8 @@ type windowsManager struct {
|
||||
nrptDB *nrptRuleDatabase
|
||||
wslManager *wslManager
|
||||
|
||||
unregisterPolicyChangeCb func() // called when the manager is closing
|
||||
|
||||
mu sync.Mutex
|
||||
closing bool
|
||||
}
|
||||
@@ -64,6 +69,11 @@ func NewOSConfigurator(logf logger.Logf, health *health.Tracker, knobs *controlk
|
||||
ret.nrptDB = newNRPTRuleDatabase(logf)
|
||||
}
|
||||
|
||||
var err error
|
||||
if ret.unregisterPolicyChangeCb, err = syspolicy.RegisterChangeCallback(ret.sysPolicyChanged); err != nil {
|
||||
logf("error registering policy change callback: %v", err) // non-fatal
|
||||
}
|
||||
|
||||
go func() {
|
||||
// Log WSL status once at startup.
|
||||
if distros, err := wslDistros(); err != nil {
|
||||
@@ -362,11 +372,9 @@ func (m *windowsManager) SetDNS(cfg OSConfig) error {
|
||||
// configuration only, routing one set of things to the "split"
|
||||
// resolver and the rest to the primary.
|
||||
|
||||
// Unconditionally disable dynamic DNS updates and NetBIOS on our
|
||||
// interfaces.
|
||||
if err := m.disableDynamicUpdates(); err != nil {
|
||||
m.logf("disableDynamicUpdates error: %v\n", err)
|
||||
}
|
||||
// Reconfigure DNS registration according to the [syspolicy.DNSRegistration]
|
||||
// policy setting, and unconditionally disable NetBIOS on our interfaces.
|
||||
m.reconfigureDNSRegistration()
|
||||
if err := m.disableNetBIOS(); err != nil {
|
||||
m.logf("disableNetBIOS error: %v\n", err)
|
||||
}
|
||||
@@ -485,6 +493,10 @@ func (m *windowsManager) Close() error {
|
||||
m.closing = true
|
||||
m.mu.Unlock()
|
||||
|
||||
if m.unregisterPolicyChangeCb != nil {
|
||||
m.unregisterPolicyChangeCb()
|
||||
}
|
||||
|
||||
err := m.SetDNS(OSConfig{})
|
||||
if m.nrptDB != nil {
|
||||
m.nrptDB.Close()
|
||||
@@ -493,15 +505,62 @@ func (m *windowsManager) Close() error {
|
||||
return err
|
||||
}
|
||||
|
||||
// disableDynamicUpdates sets the appropriate registry values to prevent the
|
||||
// Windows DHCP client from sending dynamic DNS updates for our interface to
|
||||
// AD domain controllers.
|
||||
func (m *windowsManager) disableDynamicUpdates() error {
|
||||
// sysPolicyChanged is a callback triggered by [syspolicy] when it detects
|
||||
// a change in one or more syspolicy settings.
|
||||
func (m *windowsManager) sysPolicyChanged(policy *rsop.PolicyChange) {
|
||||
if policy.HasChanged(syspolicy.EnableDNSRegistration) {
|
||||
m.reconfigureDNSRegistration()
|
||||
}
|
||||
}
|
||||
|
||||
// reconfigureDNSRegistration configures the DNS registration settings
|
||||
// using the [syspolicy.DNSRegistration] policy setting, if it is set.
|
||||
// If the policy is not configured, it disables DNS registration.
|
||||
func (m *windowsManager) reconfigureDNSRegistration() {
|
||||
// Disable DNS registration by default (if the policy setting is not configured).
|
||||
// This is primarily for historical reasons and to avoid breaking existing
|
||||
// setups that rely on this behavior.
|
||||
enableDNSRegistration, err := syspolicy.GetPreferenceOptionOrDefault(syspolicy.EnableDNSRegistration, setting.NeverByPolicy)
|
||||
if err != nil {
|
||||
m.logf("error getting DNSRegistration policy setting: %v", err) // non-fatal; we'll use the default
|
||||
}
|
||||
|
||||
if enableDNSRegistration.Show() {
|
||||
// "Show" reports whether the policy setting is configured as "user-decides".
|
||||
// The name is a bit unfortunate in this context, as we don't actually "show" anything.
|
||||
// Still, if the admin configured the policy as "user-decides", we shouldn't modify
|
||||
// the adapter's settings and should leave them up to the user (admin rights required)
|
||||
// or the system defaults.
|
||||
return
|
||||
}
|
||||
|
||||
// Otherwise, if the policy setting is configured as "always" or "never",
|
||||
// we should configure the adapter accordingly.
|
||||
if err := m.configureDNSRegistration(enableDNSRegistration.IsAlways()); err != nil {
|
||||
m.logf("error configuring DNS registration: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// configureDNSRegistration sets the appropriate registry values to allow or prevent
|
||||
// the Windows DHCP client from registering Tailscale IP addresses with DNS
|
||||
// and sending dynamic updates for our interface to AD domain controllers.
|
||||
func (m *windowsManager) configureDNSRegistration(enabled bool) error {
|
||||
prefixen := []winutil.RegistryPathPrefix{
|
||||
winutil.IPv4TCPIPInterfacePrefix,
|
||||
winutil.IPv6TCPIPInterfacePrefix,
|
||||
}
|
||||
|
||||
var (
|
||||
registrationEnabled = uint32(0)
|
||||
disableDynamicUpdate = uint32(1)
|
||||
maxNumberOfAddressesToRegister = uint32(0)
|
||||
)
|
||||
if enabled {
|
||||
registrationEnabled = 1
|
||||
disableDynamicUpdate = 0
|
||||
maxNumberOfAddressesToRegister = 1
|
||||
}
|
||||
|
||||
for _, prefix := range prefixen {
|
||||
k, err := m.openInterfaceKey(prefix)
|
||||
if err != nil {
|
||||
@@ -509,13 +568,13 @@ func (m *windowsManager) disableDynamicUpdates() error {
|
||||
}
|
||||
defer k.Close()
|
||||
|
||||
if err := k.SetDWordValue("RegistrationEnabled", 0); err != nil {
|
||||
if err := k.SetDWordValue("RegistrationEnabled", registrationEnabled); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := k.SetDWordValue("DisableDynamicUpdate", 1); err != nil {
|
||||
if err := k.SetDWordValue("DisableDynamicUpdate", disableDynamicUpdate); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := k.SetDWordValue("MaxNumberOfAddressesToRegister", 0); err != nil {
|
||||
if err := k.SetDWordValue("MaxNumberOfAddressesToRegister", maxNumberOfAddressesToRegister); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user