cmd/ctrld: workaround setting DNS issue on Linux

On some Ubuntu systems, we experiment with DNS is not set even though
systemd-resolved log indicates that it set them. To ensure the DNS will
be set, after setting them, double check the current DNS for interface
is actually the value was set, if not, attempting to set again.

While at it, also make sure the DNS is set when ctrld start on Linux.
This commit is contained in:
Cuong Manh Le
2023-02-01 23:11:33 +07:00
committed by Cuong Manh Le
parent 37de5441c1
commit 61156453b2
5 changed files with 47 additions and 4 deletions
+9 -2
View File
@@ -169,6 +169,8 @@ func initCLI() {
runCmd.Flags().StringVarP(&cdUID, "cd", "", "", "Control D resolver uid") runCmd.Flags().StringVarP(&cdUID, "cd", "", "", "Control D resolver uid")
runCmd.Flags().StringVarP(&homedir, "homedir", "", "", "") runCmd.Flags().StringVarP(&homedir, "homedir", "", "", "")
_ = runCmd.Flags().MarkHidden("homedir") _ = runCmd.Flags().MarkHidden("homedir")
runCmd.Flags().StringVarP(&iface, "iface", "", "", `Update DNS setting for iface, "auto" means the default interface gateway`)
_ = runCmd.Flags().MarkHidden("iface")
rootCmd.AddCommand(runCmd) rootCmd.AddCommand(runCmd)
@@ -226,7 +228,7 @@ func initCLI() {
} }
}, },
} }
// Keep these flags in sync with runCmd above, except for "-d", "--iface". // Keep these flags in sync with runCmd above, except for "-d".
startCmd.Flags().StringVarP(&configPath, "config", "c", "", "Path to config file") startCmd.Flags().StringVarP(&configPath, "config", "c", "", "Path to config file")
startCmd.Flags().StringVarP(&configBase64, "base64_config", "", "", "Base64 encoded config") startCmd.Flags().StringVarP(&configBase64, "base64_config", "", "", "Base64 encoded config")
startCmd.Flags().StringVarP(&listenAddress, "listen", "", "", "Listener address and port, in format: address:port") startCmd.Flags().StringVarP(&listenAddress, "listen", "", "", "Listener address and port, in format: address:port")
@@ -321,7 +323,6 @@ func initCLI() {
} }
initLogging() initLogging()
if doTasks(tasks) { if doTasks(tasks) {
prog.resetDNS()
mainLog.Info().Msg("Service uninstalled") mainLog.Info().Msg("Service uninstalled")
return return
} }
@@ -393,6 +394,9 @@ func initCLI() {
Use: "start", Use: "start",
Short: "Quick start service and configure DNS on interface", Short: "Quick start service and configure DNS on interface",
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
if !cmd.Flags().Changed("iface") {
os.Args = append(os.Args, "--iface="+ifaceStartStop)
}
iface = ifaceStartStop iface = ifaceStartStop
startCmd.Run(cmd, args) startCmd.Run(cmd, args)
}, },
@@ -405,6 +409,9 @@ func initCLI() {
Use: "stop", Use: "stop",
Short: "Quick stop service and remove DNS from interface", Short: "Quick stop service and remove DNS from interface",
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
if !cmd.Flags().Changed("iface") {
os.Args = append(os.Args, "--iface="+ifaceStartStop)
}
iface = ifaceStartStop iface = ifaceStartStop
stopCmd.Run(cmd, args) stopCmd.Run(cmd, args)
}, },
+17 -2
View File
@@ -8,6 +8,7 @@ import (
"net" "net"
"net/netip" "net/netip"
"os/exec" "os/exec"
"reflect"
"strings" "strings"
"syscall" "syscall"
"time" "time"
@@ -41,6 +42,8 @@ func deAllocateIP(ip string) error {
return nil return nil
} }
const maxSetDNSAttempts = 5
// set the dns server for the provided network interface // set the dns server for the provided network interface
func setDNS(iface *net.Interface, nameservers []string) error { func setDNS(iface *net.Interface, nameservers []string) error {
logf := func(format string, args ...any) { logf := func(format string, args ...any) {
@@ -57,10 +60,22 @@ func setDNS(iface *net.Interface, nameservers []string) error {
for _, nameserver := range nameservers { for _, nameserver := range nameservers {
ns = append(ns, netip.MustParseAddr(nameserver)) ns = append(ns, netip.MustParseAddr(nameserver))
} }
return r.SetDNS(dns.OSConfig{
osConfig := dns.OSConfig{
Nameservers: ns, Nameservers: ns,
SearchDomains: []dnsname.FQDN{}, SearchDomains: []dnsname.FQDN{},
}) }
for i := 0; i < maxSetDNSAttempts; i++ {
if err := r.SetDNS(osConfig); err != nil {
return err
}
currentNS := currentDNS(iface)
if reflect.DeepEqual(currentNS, nameservers) {
break
}
}
return nil
} }
func resetDNS(iface *net.Interface) error { func resetDNS(iface *net.Interface) error {
+6
View File
@@ -35,6 +35,7 @@ func (p *prog) Start(s service.Service) error {
} }
func (p *prog) run() { func (p *prog) run() {
p.preRun()
if p.cfg.Service.CacheEnable { if p.cfg.Service.CacheEnable {
cacher, err := dnscache.NewLRUCache(p.cfg.Service.CacheSize) cacher, err := dnscache.NewLRUCache(p.cfg.Service.CacheSize)
if err != nil { if err != nil {
@@ -173,6 +174,11 @@ func (p *prog) Stop(s service.Service) error {
return nil return nil
} }
func (p *prog) Uninstall(s service.Service) error {
p.resetDNS()
return nil
}
func (p *prog) allocateIP(ip string) error { func (p *prog) allocateIP(ip string) error {
if !p.cfg.Service.AllocateIP { if !p.cfg.Service.AllocateIP {
return nil return nil
+9
View File
@@ -0,0 +1,9 @@
package main
import "github.com/kardianos/service"
func (p *prog) preRun() {
if !service.Interactive() {
p.setDNS()
}
}
+6
View File
@@ -0,0 +1,6 @@
//go:build !linux
// +build !linux
package main
func (p *prog) preRun() {}