From 2ad042b0a66ac42aeb061c29bd62b54d8b904c9b Mon Sep 17 00:00:00 2001 From: hwipl <33433250+hwipl@users.noreply.github.com> Date: Wed, 30 Nov 2022 13:42:18 +0100 Subject: [PATCH 1/3] Handle DNS Reports properly in tools/dnsproxy Signed-off-by: hwipl <33433250+hwipl@users.noreply.github.com> --- tools/dnsproxy/main.go | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/dnsproxy/main.go b/tools/dnsproxy/main.go index 4ae0294..cd8988f 100644 --- a/tools/dnsproxy/main.go +++ b/tools/dnsproxy/main.go @@ -74,5 +74,6 @@ func main() { go p.Start() for r := range p.Reports() { log.WithField("report", r).Debug("DNS-Proxy got watched domain report") + r.Done() } } From ff6fa893e5a6f1b1973dfda0af1085b7d361775e Mon Sep 17 00:00:00 2001 From: hwipl <33433250+hwipl@users.noreply.github.com> Date: Wed, 30 Nov 2022 15:37:22 +0100 Subject: [PATCH 2/3] Add TCP support to DNS Proxy Signed-off-by: hwipl <33433250+hwipl@users.noreply.github.com> --- internal/dnsproxy/proxy.go | 71 ++++++++++++++++++++++++--------- internal/dnsproxy/proxy_test.go | 4 +- 2 files changed, 55 insertions(+), 20 deletions(-) diff --git a/internal/dnsproxy/proxy.go b/internal/dnsproxy/proxy.go index 732d3fb..38f2268 100644 --- a/internal/dnsproxy/proxy.go +++ b/internal/dnsproxy/proxy.go @@ -16,10 +16,12 @@ const ( // Proxy is a DNS proxy type Proxy struct { - server *dns.Server + udp *dns.Server + tcp *dns.Server remotes *Remotes watches *Watches reports chan *Report + done chan struct{} // channels for temp watch cleaning goroutine stopClean chan struct{} @@ -132,22 +134,54 @@ func (p *Proxy) cleanTempWatches() { } } +// startDNSServer starts the dns server +func (p *Proxy) startDNSServer(server *dns.Server) { + log.WithFields(log.Fields{ + "addr": server.Addr, + "net": server.Net, + }).Debug("DNS-Proxy starting server") + err := server.ListenAndServe() + if err != nil { + log.WithError(err).Error("DNS-Proxy DNS server stopped") + } +} + +// stopDNSServer stops the dns server +func (p *Proxy) stopDNSServer(server *dns.Server) { + err := server.Shutdown() + if err != nil { + log.WithFields(log.Fields{ + "addr": server.Addr, + "net": server.Net, + "error": err, + }).Error("DNS-Proxy could not stop DNS server") + } +} + // start starts running the proxy func (p *Proxy) start() { // start cleaning goroutine go p.cleanTempWatches() - // start dns server + // start dns servers log.Debug("DNS-Proxy registering handler") dns.HandleFunc(".", p.handleRequest) - log.WithFields(log.Fields{ - "addr": p.server.Addr, - "net": p.server.Net, - }).Debug("DNS-Proxy starting server") - err := p.server.ListenAndServe() - if err != nil { - log.WithError(err).Error("DNS-Proxy could not start DNS server") + for _, srv := range []*dns.Server{p.udp, p.tcp} { + go p.startDNSServer(srv) } + + // wait for proxy termination + <-p.done + + // stop cleaning goroutine + close(p.stopClean) + <-p.doneClean + + // stop dns servers + for _, srv := range []*dns.Server{p.udp, p.tcp} { + p.stopDNSServer(srv) + } + close(p.reports) } // Start starts running the proxy @@ -157,16 +191,10 @@ func (p *Proxy) Start() { // Stop stops running the proxy func (p *Proxy) Stop() { - // stop cleaning goroutine - close(p.stopClean) - <-p.doneClean - - // stop server - err := p.server.Shutdown() - if err != nil { - log.WithError(err).Fatal("DNS-Proxy could not stop DNS server") + close(p.done) + for range p.reports { + // wait for channel shutdown } - close(p.reports) } // Reports returns the Report channel for watched domains @@ -193,13 +221,18 @@ func (p *Proxy) SetWatches(watches []string) { // NewProxy returns a new Proxy that listens on address func NewProxy(address string) *Proxy { return &Proxy{ - server: &dns.Server{ + udp: &dns.Server{ Addr: address, Net: "udp", }, + tcp: &dns.Server{ + Addr: address, + Net: "tcp", + }, remotes: NewRemotes(), watches: NewWatches(), reports: make(chan *Report), + done: make(chan struct{}), stopClean: make(chan struct{}), doneClean: make(chan struct{}), diff --git a/internal/dnsproxy/proxy_test.go b/internal/dnsproxy/proxy_test.go index 6649c3e..c55bbe7 100644 --- a/internal/dnsproxy/proxy_test.go +++ b/internal/dnsproxy/proxy_test.go @@ -39,10 +39,12 @@ func TestProxySetWatches(t *testing.T) { // TestNewProxy tests NewProxy func TestNewProxy(t *testing.T) { p := NewProxy("127.0.0.1:4254") - if p.server == nil || + if p.udp == nil || + p.tcp == nil || p.remotes == nil || p.watches == nil || p.reports == nil || + p.done == nil || p.stopClean == nil || p.doneClean == nil { From 9812097fc287a8241068dc98601025a6f5a7e8e1 Mon Sep 17 00:00:00 2001 From: hwipl <33433250+hwipl@users.noreply.github.com> Date: Wed, 7 Dec 2022 12:03:32 +0100 Subject: [PATCH 3/3] Reset DNS server features learnt by resolved Reset DNS server features learnt by systemd-resolved when DNS configuration is changed to ensure resolved probes the DNS Proxy and detects all features during VPN tunnel setup. Signed-off-by: hwipl <33433250+hwipl@users.noreply.github.com> --- internal/vpnconfig/config.go | 6 ++++++ internal/vpnconfig/config_test.go | 2 ++ 2 files changed, 8 insertions(+) diff --git a/internal/vpnconfig/config.go b/internal/vpnconfig/config.go index f8dc7ad..fde55f2 100644 --- a/internal/vpnconfig/config.go +++ b/internal/vpnconfig/config.go @@ -248,6 +248,9 @@ func (c *Config) SetDNS(server string) { // flush dns caches runResolvectl("flush-caches") + + // reset learnt server features + runResolvectl("reset-server-features") } // UnsetDNS unsets the DNS configuration @@ -259,6 +262,9 @@ func (c *Config) UnsetDNS() { // flush dns caches runResolvectl("flush-caches") + + // reset learnt server features + runResolvectl("reset-server-features") } // New returns a new Config diff --git a/internal/vpnconfig/config_test.go b/internal/vpnconfig/config_test.go index b159b79..bdec26c 100644 --- a/internal/vpnconfig/config_test.go +++ b/internal/vpnconfig/config_test.go @@ -280,6 +280,7 @@ func TestConfigSetDNS(t *testing.T) { "domain tun0 mycompany.com ~.", "default-route tun0 yes", "flush-caches", + "reset-server-features", } if !reflect.DeepEqual(got, want) { t.Errorf("got %v, want %v", got, want) @@ -300,6 +301,7 @@ func TestConfigUnsetDNS(t *testing.T) { want := []string{ "revert tun0", "flush-caches", + "reset-server-features", } if !reflect.DeepEqual(got, want) { t.Errorf("got %v, want %v", got, want)