From 93c2882a2fe9b8058440bad60943ac2ad7a97ef2 Mon Sep 17 00:00:00 2001 From: Denton Gentry Date: Sat, 18 Sep 2021 20:33:21 -0700 Subject: [PATCH] wgengine: flush DNS cache after major link change. Windows has a public dns.Flush used in router_windows.go. However that won't work for platforms like Linux, where we need a different flush mechanism for resolved versus other implementations. We're instead adding a FlushCaches method to the dns Manager, which can be made to work on all platforms as needed. Fixes https://github.com/tailscale/tailscale/issues/2132 Signed-off-by: Denton Gentry --- net/dns/flush_default.go | 12 ++++++++++++ net/dns/flush_windows.go | 13 +++++++++++-- net/dns/manager.go | 4 ++++ wgengine/userspace.go | 5 +++++ 4 files changed, 32 insertions(+), 2 deletions(-) create mode 100644 net/dns/flush_default.go diff --git a/net/dns/flush_default.go b/net/dns/flush_default.go new file mode 100644 index 000000000..c8452383e --- /dev/null +++ b/net/dns/flush_default.go @@ -0,0 +1,12 @@ +// Copyright (c) 2021 Tailscale Inc & AUTHORS All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !windows +// +build !windows + +package dns + +func flushCaches() error { + return nil +} diff --git a/net/dns/flush_windows.go b/net/dns/flush_windows.go index 3c7e7d645..71da08e32 100644 --- a/net/dns/flush_windows.go +++ b/net/dns/flush_windows.go @@ -9,11 +9,20 @@ import ( "os/exec" ) -// Flush clears the local resolver cache. -func Flush() error { +func flushCaches() error { out, err := exec.Command("ipconfig", "/flushdns").CombinedOutput() if err != nil { return fmt.Errorf("%v (output: %s)", err, out) } return nil } + +// Flush clears the local resolver cache. +// +// Only Windows has a public dns.Flush, needed in router_windows.go. Other +// platforms like Linux need a different flush implementation depending on +// the DNS manager. There is a FlushCaches method on the manager which +// can be used on all platforms. +func Flush() error { + return flushCaches() +} diff --git a/net/dns/manager.go b/net/dns/manager.go index e16a6f8e2..dfb107208 100644 --- a/net/dns/manager.go +++ b/net/dns/manager.go @@ -212,6 +212,10 @@ func (m *Manager) Down() error { return nil } +func (m *Manager) FlushCaches() error { + return flushCaches() +} + // Cleanup restores the system DNS configuration to its original state // in case the Tailscale daemon terminated without closing the router. // No other state needs to be instantiated before this runs. diff --git a/wgengine/userspace.go b/wgengine/userspace.go index e2786be42..b3847134b 100644 --- a/wgengine/userspace.go +++ b/wgengine/userspace.go @@ -1160,6 +1160,11 @@ func (e *userspaceEngine) linkChange(changed bool, cur *interfaces.State) { health.SetAnyInterfaceUp(up) e.magicConn.SetNetworkUp(up) + if !up || changed { + if err := e.dns.FlushCaches(); err != nil { + e.logf("wgengine: dns flush failed after major link change: %v", err) + } + } // Hacky workaround for Linux DNS issue 2458: on // suspend/resume or whenever NetworkManager is started, it