net/dns: improve NetworkManager detection, using more DBus.
Signed-off-by: David Anderson <danderson@tailscale.com>pull/1691/head
parent
9a48bac8ad
commit
84430cdfa1
|
@ -8,6 +8,8 @@ import "tailscale.com/types/logger"
|
||||||
|
|
||||||
func NewOSConfigurator(logf logger.Logf, interfaceName string) OSConfigurator {
|
func NewOSConfigurator(logf logger.Logf, interfaceName string) OSConfigurator {
|
||||||
switch {
|
switch {
|
||||||
|
case isNMActive():
|
||||||
|
return newNMManager(interfaceName)
|
||||||
// TODO: rework NetworkManager and resolved support.
|
// TODO: rework NetworkManager and resolved support.
|
||||||
// case isResolvedActive():
|
// case isResolvedActive():
|
||||||
// return newResolvedManager()
|
// return newResolvedManager()
|
||||||
|
|
|
@ -14,7 +14,7 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"time"
|
||||||
|
|
||||||
"github.com/godbus/dbus/v5"
|
"github.com/godbus/dbus/v5"
|
||||||
"tailscale.com/util/endian"
|
"tailscale.com/util/endian"
|
||||||
|
@ -22,11 +22,21 @@ import (
|
||||||
|
|
||||||
// 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 {
|
||||||
// This is somewhat tricky because NetworkManager supports a number
|
ctx, cancel := context.WithTimeout(context.Background(), reconfigTimeout)
|
||||||
// of DNS configuration modes. In all cases, we expect it to be installed
|
defer cancel()
|
||||||
// and /etc/resolv.conf to contain a mention of NetworkManager in the comments.
|
|
||||||
_, err := exec.LookPath("NetworkManager")
|
conn, err := dbus.SystemBus()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
// Probably no DBus on this system. Either way, we can't
|
||||||
|
// control NM without DBus.
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to ping NetworkManager's DnsManager object. If it responds,
|
||||||
|
// NM is running and we're allowed to touch it.
|
||||||
|
nm := conn.Object("org.freedesktop.NetworkManager", dbus.ObjectPath("/org/freedesktop/NetworkManager/DnsManager"))
|
||||||
|
call := nm.CallWithContext(ctx, "org.freedesktop.DBus.Peer.Ping", 0)
|
||||||
|
if call.Err != nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,8 +77,24 @@ func (m nmManager) SetDNS(config OSConfig) error {
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), reconfigTimeout)
|
ctx, cancel := context.WithTimeout(context.Background(), reconfigTimeout)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
// conn is a shared connection whose lifecycle is managed by the dbus package.
|
// NetworkManager only lets you set DNS settings on "active"
|
||||||
// We should not interfere with that by closing it.
|
// connections, which requires an assigned IP address. This got
|
||||||
|
// configured before the DNS manager was invoked, but it might
|
||||||
|
// take a little time for the netlink notifications to propagate
|
||||||
|
// up. So, keep retrying for the duration of the reconfigTimeout.
|
||||||
|
var err error
|
||||||
|
for ctx.Err() == nil {
|
||||||
|
err = m.trySet(ctx, config)
|
||||||
|
if err == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
time.Sleep(10 * time.Millisecond)
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m nmManager) trySet(ctx context.Context, config OSConfig) error {
|
||||||
conn, err := dbus.SystemBus()
|
conn, err := dbus.SystemBus()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("connecting to system bus: %w", err)
|
return fmt.Errorf("connecting to system bus: %w", err)
|
||||||
|
|
|
@ -1010,15 +1010,18 @@ func (e *userspaceEngine) Reconfig(cfg *wgcfg.Config, routerCfg *router.Config,
|
||||||
}
|
}
|
||||||
|
|
||||||
if routerChanged {
|
if routerChanged {
|
||||||
e.logf("wgengine: Reconfig: configuring DNS")
|
e.logf("wgengine: Reconfig: configuring router")
|
||||||
err := e.dns.Set(*dnsCfg)
|
err := e.router.Set(routerCfg)
|
||||||
health.SetDNSHealth(err)
|
health.SetRouterHealth(err)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
e.logf("wgengine: Reconfig: configuring router")
|
// Keep DNS configuration after router configuration, as some
|
||||||
err = e.router.Set(routerCfg)
|
// DNS managers refuse to apply settings if the device has no
|
||||||
health.SetRouterHealth(err)
|
// assigned address.
|
||||||
|
e.logf("wgengine: Reconfig: configuring DNS")
|
||||||
|
err = e.dns.Set(*dnsCfg)
|
||||||
|
health.SetDNSHealth(err)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue