From cc28b929354d97102e1a4814507f06872b5543b6 Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Sat, 24 Jun 2023 00:29:49 +0700 Subject: [PATCH] all: fallback to br0 as nameserver if 127.0.0.1 is used On Firewalla, lo interface is excluded in all dnsmasq settings of all interfaces, to prevent conflicts. The one that ctrld adds in dnsmasq_local directory could not work if there're multiple dnsmasq configs for multiple interfaces (real example from an user who uses VLAN in router setup). Instead, if we detect 127.0.0.1 on Firewalla, fallback to "br0" interface IP address instead. --- cmd/ctrld/cli.go | 4 +++ cmd/ctrld/prog.go | 18 ++++++++++++- internal/router/dnsmasq.go | 5 +--- internal/router/firewalla.go | 49 ++++++++++-------------------------- internal/router/router.go | 18 +++++++++++++ 5 files changed, 53 insertions(+), 41 deletions(-) diff --git a/cmd/ctrld/cli.go b/cmd/ctrld/cli.go index 7b9a307..1b0262b 100644 --- a/cmd/ctrld/cli.go +++ b/cmd/ctrld/cli.go @@ -982,6 +982,10 @@ func uninstall(p *prog, s service.Service) { } initLogging() if doTasks(tasks) { + if err := router.PostUninstall(svcConfig); err != nil { + mainLog.Warn().Err(err).Msg("post uninstallation failed, please check system/service log for details error") + return + } // Stop already reset DNS on router. if router.Name() == "" { p.resetDNS() diff --git a/cmd/ctrld/prog.go b/cmd/ctrld/prog.go index 54cad6d..e917f88 100644 --- a/cmd/ctrld/prog.go +++ b/cmd/ctrld/prog.go @@ -235,7 +235,23 @@ func (p *prog) setDNS() { return } logger.Debug().Msg("setting DNS for interface") - if err := setDNS(netIface, []string{cfg.Listener["0"].IP}); err != nil { + ns := cfg.Listener["0"].IP + if router.Name() == router.Firewalla && ns == "127.0.0.1" { + // On Firewalla, the lo interface is excluded in all dnsmasq settings of all interfaces. + // Thus, we use "br0" as the nameserver in /etc/resolv.conf file. + logger.Warn().Msg("127.0.0.1 won't work on Firewalla") + if netIface, err := net.InterfaceByName("br0"); err == nil { + addrs, _ := netIface.Addrs() + for _, addr := range addrs { + if netIP, ok := addr.(*net.IPNet); ok && netIP.IP.To4() != nil { + logger.Warn().Msg("using br0 interface IP address as DNS server") + ns = netIP.IP.To4().String() + break + } + } + } + } + if err := setDNS(netIface, []string{ns}); err != nil { logger.Error().Err(err).Msgf("could not set DNS for interface") return } diff --git a/internal/router/dnsmasq.go b/internal/router/dnsmasq.go index 2ca3249..9df4132 100644 --- a/internal/router/dnsmasq.go +++ b/internal/router/dnsmasq.go @@ -1,7 +1,6 @@ package router import ( - "fmt" "strings" "text/template" ) @@ -50,10 +49,8 @@ func dnsMasqConf() (string, error) { var sb strings.Builder var tmplText string switch Name() { - case DDWrt, EdgeOS, OpenWrt, Ubios, Synology, Tomato: + case DDWrt, EdgeOS, Firewalla, OpenWrt, Ubios, Synology, Tomato: tmplText = dnsMasqConfigContentTmpl - case Firewalla: - tmplText = dnsMasqConfigContentTmpl + fmt.Sprintf("listen-address=127.0.0.1\n") case Merlin: tmplText = merlinDNSMasqPostConfTmpl } diff --git a/internal/router/firewalla.go b/internal/router/firewalla.go index 1182890..6d57409 100644 --- a/internal/router/firewalla.go +++ b/internal/router/firewalla.go @@ -4,42 +4,21 @@ import ( "fmt" "os" "os/exec" - "path/filepath" "strings" ) const ( - firewallaDNSMasqConfigPath = "/home/pi/.firewalla/config/dnsmasq_local" - firewallaDNSMasqBackupConfigPath = "/home/pi/.firewalla/config/dnsmasq_local.bak" - firewallaConfigPostMainDir = "/home/pi/.firewalla/config/post_main.d" - firewallaCtrldInitScriptPath = "/home/pi/.firewalla/config/post_main.d/start_ctrld.sh" + firewallaDNSMasqConfigPath = "/home/pi/.firewalla/config/dnsmasq_local/ctrld" + firewallaConfigPostMainDir = "/home/pi/.firewalla/config/post_main.d" + firewallaCtrldInitScriptPath = "/home/pi/.firewalla/config/post_main.d/start_ctrld.sh" ) func setupFirewalla() error { - fi, err := os.Stat(firewallaDNSMasqConfigPath) - if err != nil { - return fmt.Errorf("setupFirewalla: get current config directory: %w", err) - } - - _ = os.RemoveAll(firewallaDNSMasqBackupConfigPath) - - // Creating a backup. - if err := os.Rename(firewallaDNSMasqConfigPath, firewallaDNSMasqBackupConfigPath); err != nil { - return fmt.Errorf("setupFirewalla: backup current config: %w", err) - } - - // Creating our own config. - if err := os.MkdirAll(firewallaDNSMasqConfigPath, fi.Mode()); err != nil { - return fmt.Errorf("setupFirewalla: creating config dir: %w", err) - } - - // Adding ctrld listener as the only upstream. dnsMasqConfigContent, err := dnsMasqConf() if err != nil { return fmt.Errorf("setupFirewalla: generating dnsmasq config: %w", err) } - ctrldConfPath := filepath.Join(firewallaDNSMasqConfigPath, "ctrld") - if err := os.WriteFile(ctrldConfPath, []byte(dnsMasqConfigContent), 0600); err != nil { + if err := os.WriteFile(firewallaDNSMasqConfigPath, []byte(dnsMasqConfigContent), 0600); err != nil { return fmt.Errorf("setupFirewalla: writing ctrld config: %w", err) } @@ -52,21 +31,11 @@ func setupFirewalla() error { } func cleanupFirewalla() error { - // Do nothing if there's no backup config. - if _, err := os.Stat(firewallaDNSMasqBackupConfigPath); err != nil && os.IsNotExist(err) { - return nil - } - // Removing current config. - if err := os.RemoveAll(firewallaDNSMasqConfigPath); err != nil { + if err := os.Remove(firewallaDNSMasqConfigPath); err != nil { return fmt.Errorf("cleanupFirewalla: removing ctrld config: %w", err) } - // Restoring backup. - if err := os.Rename(firewallaDNSMasqBackupConfigPath, firewallaDNSMasqConfigPath); err != nil { - return fmt.Errorf("cleanupFirewalla: restoring backup config: %w", err) - } - // Restart dnsmasq service. if err := restartDNSMasq(); err != nil { return fmt.Errorf("cleanupFirewalla: restartDNSMasq: %w", err) @@ -83,6 +52,14 @@ func postInstallFirewalla() error { return nil } +func postUninstallFirewalla() error { + // Removing startup script. + if err := os.Remove(firewallaCtrldInitScriptPath); err != nil { + return fmt.Errorf("postUninstallFirewalla: removing startup script: %w", err) + } + return nil +} + func firewallaRestartDNSMasq() error { return exec.Command("systemctl", "restart", "firerouter_dns").Run() } diff --git a/internal/router/router.go b/internal/router/router.go index 79f5901..c53178f 100644 --- a/internal/router/router.go +++ b/internal/router/router.go @@ -174,6 +174,24 @@ func PostInstall(svc *service.Config) error { return nil } +// PostUninstall performs task after uninstalling ctrld on router. +func PostUninstall(svc *service.Config) error { + name := Name() + switch name { + case DDWrt: + case EdgeOS: + case Firewalla: + return postUninstallFirewalla() + case Merlin: + case OpenWrt: + case Pfsense: + case Synology: + case Tomato: + case Ubios: + } + return nil +} + // Cleanup cleans ctrld setup on the router. func Cleanup(svc *service.Config) error { name := Name()