net/dns: fix up NetworkManager configurator a bit.

Clear LLMNR and mdns flags, update reasoning for our settings,
and set our override priority harder than before when we want
to be primary resolver.

Signed-off-by: David Anderson <danderson@tailscale.com>
pull/1691/head
David Anderson 4 years ago
parent 303805a389
commit 87eb8384f5

@ -20,6 +20,11 @@ import (
"tailscale.com/util/endian" "tailscale.com/util/endian"
) )
const (
highestPriority = int32(-1 << 31)
lowerPriority = int32(200) // lower than all builtin auto priorities
)
// isNMActive determines if NetworkManager is currently managing system DNS settings. // isNMActive determines if NetworkManager is currently managing system DNS settings.
func isNMActive() bool { func isNMActive() bool {
ctx, cancel := context.WithTimeout(context.Background(), reconfigTimeout) ctx, cancel := context.WithTimeout(context.Background(), reconfigTimeout)
@ -162,43 +167,50 @@ func (m nmManager) trySet(ctx context.Context, config OSConfig) error {
} }
} }
general := settings["connection"]
general["llmnr"] = dbus.MakeVariant(0)
general["mdns"] = dbus.MakeVariant(0)
ipv4Map := settings["ipv4"] ipv4Map := settings["ipv4"]
ipv4Map["dns"] = dbus.MakeVariant(dnsv4) ipv4Map["dns"] = dbus.MakeVariant(dnsv4)
ipv4Map["dns-search"] = dbus.MakeVariant(config.SearchDomains) ipv4Map["dns-search"] = dbus.MakeVariant(config.SearchDomains)
// We should only request priority if we have nameservers to set. // We should only request priority if we have nameservers to set.
if len(dnsv4) == 0 { if len(dnsv4) == 0 {
ipv4Map["dns-priority"] = dbus.MakeVariant(100) ipv4Map["dns-priority"] = dbus.MakeVariant(lowerPriority)
} else { } else {
// dns-priority = -1 ensures that we have priority // Negative priority means only the settings from the most
// over other interfaces, except those exploiting this same trick. // negative connection get used. The way this mixes with
// Ref: https://bugs.launchpad.net/ubuntu/+source/network-manager/+bug/1211110/comments/92. // per-domain routing is unclear, but it _seems_ that the
ipv4Map["dns-priority"] = dbus.MakeVariant(-1) // priority applies after routing has found possible
// candidates for a resolution.
ipv4Map["dns-priority"] = dbus.MakeVariant(highestPriority)
} }
// In principle, we should not need set this to true,
// as our interface does not configure any automatic DNS settings (presumably via DHCP).
// All the same, better to be safe.
ipv4Map["ignore-auto-dns"] = dbus.MakeVariant(true)
ipv6Map := settings["ipv6"] ipv6Map := settings["ipv6"]
// This is a hack. // In IPv6 settings, you're only allowed to provide additional
// Methods "disabled", "ignore", "link-local" (IPv6 default) prevent us from setting DNS. // static DNS settings in "auto" (SLAAC) or "manual" mode. In
// It seems that our only recourse is "manual" or "auto". // "manual" mode you also have to specify IP addresses, so we use
// "manual" requires addresses, so we use "auto", which will assign us a random IPv6 /64. // "auto".
//
// NM actually documents that to set just DNS servers, you should
// use "auto" mode and then set ignore auto routes and DNS, which
// basically means "autoconfigure but ignore any autoconfiguration
// results you might get". As a safety, we also say that
// NetworkManager should never try to make us the default route
// (none of its business anyway, we handle our own default
// routing).
ipv6Map["method"] = dbus.MakeVariant("auto") ipv6Map["method"] = dbus.MakeVariant("auto")
// Our IPv6 config is a fake, so it should never become the default route.
ipv6Map["never-default"] = dbus.MakeVariant(true)
// Moreover, we should ignore all autoconfigured routes (hopefully none), as they are bogus.
ipv6Map["ignore-auto-routes"] = dbus.MakeVariant(true) ipv6Map["ignore-auto-routes"] = dbus.MakeVariant(true)
ipv6Map["ignore-auto-dns"] = dbus.MakeVariant(true)
ipv6Map["never-default"] = dbus.MakeVariant(true)
// Finally, set the actual DNS config.
ipv6Map["dns"] = dbus.MakeVariant(dnsv6) ipv6Map["dns"] = dbus.MakeVariant(dnsv6)
ipv6Map["dns-search"] = dbus.MakeVariant(config.SearchDomains) ipv6Map["dns-search"] = dbus.MakeVariant(config.SearchDomains)
if len(dnsv6) == 0 { if len(dnsv6) == 0 {
ipv6Map["dns-priority"] = dbus.MakeVariant(100) ipv6Map["dns-priority"] = dbus.MakeVariant(lowerPriority)
} else { } else {
ipv6Map["dns-priority"] = dbus.MakeVariant(-1) ipv6Map["dns-priority"] = dbus.MakeVariant(highestPriority)
} }
ipv6Map["ignore-auto-dns"] = dbus.MakeVariant(true)
// deprecatedProperties are the properties in interface settings // deprecatedProperties are the properties in interface settings
// that are deprecated by NetworkManager. // that are deprecated by NetworkManager.
@ -215,11 +227,7 @@ func (m nmManager) trySet(ctx context.Context, config OSConfig) error {
delete(ipv6Map, property) delete(ipv6Map, property)
} }
err = device.CallWithContext( if call := device.CallWithContext(ctx, "org.freedesktop.NetworkManager.Device.Reapply", 0, settings, version, uint32(0)); call.Err != nil {
ctx, "org.freedesktop.NetworkManager.Device.Reapply", 0,
settings, version, uint32(0),
).Store()
if err != nil {
return fmt.Errorf("reapply: %w", err) return fmt.Errorf("reapply: %w", err)
} }
@ -233,5 +241,7 @@ func (m nmManager) GetBaseConfig() (OSConfig, error) {
} }
func (m nmManager) Close() error { func (m nmManager) Close() error {
return m.SetDNS(OSConfig{}) // No need to do anything on close, NetworkManager will delete our
// settings when the tailscale interface goes away.
return nil
} }

Loading…
Cancel
Save