|
|
|
|
@ -180,20 +180,55 @@ func dnsMode(logf logger.Logf, env newOSConfigEnv) (ret string, err error) { |
|
|
|
|
return "direct", nil |
|
|
|
|
} |
|
|
|
|
case "NetworkManager": |
|
|
|
|
// You'd think we would use newNMManager somewhere in
|
|
|
|
|
// here. However, as explained in
|
|
|
|
|
// https://github.com/tailscale/tailscale/issues/1699 , using
|
|
|
|
|
// NetworkManager for DNS configuration carries with it the
|
|
|
|
|
// cost of losing IPv6 configuration on the Tailscale network
|
|
|
|
|
// interface. So, when we can avoid it, we bypass
|
|
|
|
|
// NetworkManager by replacing resolv.conf directly.
|
|
|
|
|
//
|
|
|
|
|
// If you ever try to put NMManager back here, keep in mind
|
|
|
|
|
// that versions >=1.26.6 will ignore DNS configuration
|
|
|
|
|
// anyway, so you still need a fallback path that uses
|
|
|
|
|
// directManager.
|
|
|
|
|
dbg("rc", "nm") |
|
|
|
|
return "direct", nil |
|
|
|
|
// Sometimes, NetworkManager owns the configuration but points
|
|
|
|
|
// it at systemd-resolved.
|
|
|
|
|
if err := resolvedIsActuallyResolver(bs); err != nil { |
|
|
|
|
dbg("resolved", "not-in-use") |
|
|
|
|
// You'd think we would use newNMManager here. However, as
|
|
|
|
|
// explained in
|
|
|
|
|
// https://github.com/tailscale/tailscale/issues/1699 ,
|
|
|
|
|
// using NetworkManager for DNS configuration carries with
|
|
|
|
|
// it the cost of losing IPv6 configuration on the
|
|
|
|
|
// Tailscale network interface. So, when we can avoid it,
|
|
|
|
|
// we bypass NetworkManager by replacing resolv.conf
|
|
|
|
|
// directly.
|
|
|
|
|
//
|
|
|
|
|
// If you ever try to put NMManager back here, keep in mind
|
|
|
|
|
// that versions >=1.26.6 will ignore DNS configuration
|
|
|
|
|
// anyway, so you still need a fallback path that uses
|
|
|
|
|
// directManager.
|
|
|
|
|
return "direct", nil |
|
|
|
|
} |
|
|
|
|
dbg("nm-resolved", "yes") |
|
|
|
|
|
|
|
|
|
if err := env.dbusPing("org.freedesktop.resolve1", "/org/freedesktop/resolve1"); err != nil { |
|
|
|
|
dbg("resolved", "no") |
|
|
|
|
return "direct", nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// See large comment above for reasons we'd use NM rather than
|
|
|
|
|
// resolved. systemd-resolved is actually in charge of DNS
|
|
|
|
|
// configuration, but in some cases we might need to configure
|
|
|
|
|
// it via NetworkManager. All the logic below is probing for
|
|
|
|
|
// that case: is NetworkManager running? If so, is it one of
|
|
|
|
|
// the versions that requires direct interaction with it?
|
|
|
|
|
if err := env.dbusPing("org.freedesktop.NetworkManager", "/org/freedesktop/NetworkManager/DnsManager"); err != nil { |
|
|
|
|
dbg("nm", "no") |
|
|
|
|
return "systemd-resolved", nil |
|
|
|
|
} |
|
|
|
|
safe, err := env.nmVersionBetween("1.26.0", "1.26.5") |
|
|
|
|
if err != nil { |
|
|
|
|
// Failed to figure out NM's version, can't make a correct
|
|
|
|
|
// decision.
|
|
|
|
|
return "", fmt.Errorf("checking NetworkManager version: %v", err) |
|
|
|
|
} |
|
|
|
|
if safe { |
|
|
|
|
dbg("nm-safe", "yes") |
|
|
|
|
return "network-manager", nil |
|
|
|
|
} |
|
|
|
|
dbg("nm-safe", "no") |
|
|
|
|
return "systemd-resolved", nil |
|
|
|
|
default: |
|
|
|
|
dbg("rc", "unknown") |
|
|
|
|
return "direct", nil |
|
|
|
|
@ -244,6 +279,13 @@ func nmIsUsingResolved() error { |
|
|
|
|
return nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// resolvedIsActuallyResolver reports whether the given resolv.conf
|
|
|
|
|
// bytes describe a configuration where systemd-resolved (127.0.0.53)
|
|
|
|
|
// is the only configured nameserver.
|
|
|
|
|
//
|
|
|
|
|
// Returns an error if the configuration is something other than
|
|
|
|
|
// exclusively systemd-resolved, or nil if the config is only
|
|
|
|
|
// systemd-resolved.
|
|
|
|
|
func resolvedIsActuallyResolver(bs []byte) error { |
|
|
|
|
cfg, err := readResolv(bytes.NewBuffer(bs)) |
|
|
|
|
if err != nil { |
|
|
|
|
|