mirror of
https://github.com/tailscale/tailscale.git
synced 2025-02-18 02:48:40 +00:00
net/dns: improve NetworkManager detection, using more DBus.
Signed-off-by: David Anderson <danderson@tailscale.com>
This commit is contained in:
parent
9a48bac8ad
commit
84430cdfa1
@ -8,6 +8,8 @@ import "tailscale.com/types/logger"
|
||||
|
||||
func NewOSConfigurator(logf logger.Logf, interfaceName string) OSConfigurator {
|
||||
switch {
|
||||
case isNMActive():
|
||||
return newNMManager(interfaceName)
|
||||
// TODO: rework NetworkManager and resolved support.
|
||||
// case isResolvedActive():
|
||||
// return newResolvedManager()
|
||||
|
@ -14,7 +14,7 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"time"
|
||||
|
||||
"github.com/godbus/dbus/v5"
|
||||
"tailscale.com/util/endian"
|
||||
@ -22,11 +22,21 @@ import (
|
||||
|
||||
// isNMActive determines if NetworkManager is currently managing system DNS settings.
|
||||
func isNMActive() bool {
|
||||
// This is somewhat tricky because NetworkManager supports a number
|
||||
// of DNS configuration modes. In all cases, we expect it to be installed
|
||||
// and /etc/resolv.conf to contain a mention of NetworkManager in the comments.
|
||||
_, err := exec.LookPath("NetworkManager")
|
||||
ctx, cancel := context.WithTimeout(context.Background(), reconfigTimeout)
|
||||
defer cancel()
|
||||
|
||||
conn, err := dbus.SystemBus()
|
||||
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
|
||||
}
|
||||
|
||||
@ -67,8 +77,24 @@ func (m nmManager) SetDNS(config OSConfig) error {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), reconfigTimeout)
|
||||
defer cancel()
|
||||
|
||||
// conn is a shared connection whose lifecycle is managed by the dbus package.
|
||||
// We should not interfere with that by closing it.
|
||||
// NetworkManager only lets you set DNS settings on "active"
|
||||
// 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()
|
||||
if err != nil {
|
||||
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 {
|
||||
e.logf("wgengine: Reconfig: configuring DNS")
|
||||
err := e.dns.Set(*dnsCfg)
|
||||
health.SetDNSHealth(err)
|
||||
e.logf("wgengine: Reconfig: configuring router")
|
||||
err := e.router.Set(routerCfg)
|
||||
health.SetRouterHealth(err)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
e.logf("wgengine: Reconfig: configuring router")
|
||||
err = e.router.Set(routerCfg)
|
||||
health.SetRouterHealth(err)
|
||||
// Keep DNS configuration after router configuration, as some
|
||||
// DNS managers refuse to apply settings if the device has no
|
||||
// assigned address.
|
||||
e.logf("wgengine: Reconfig: configuring DNS")
|
||||
err = e.dns.Set(*dnsCfg)
|
||||
health.SetDNSHealth(err)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user