From 5b6a3a4c6f2a69dcc75756d9358b19fd62486c3c Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Fri, 5 May 2023 21:25:54 +0700 Subject: [PATCH] internal/router: disable native dot on merlin While at it, also ensure custom config is ignored when running on router, because we need to point to 127.0.0.1:53 (dnsmasq listener). --- cmd/ctrld/cli.go | 7 ++++ internal/router/ddwrt.go | 64 ++++------------------------- internal/router/merlin.go | 9 +++++ internal/router/nvram.go | 84 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 107 insertions(+), 57 deletions(-) create mode 100644 internal/router/nvram.go diff --git a/cmd/ctrld/cli.go b/cmd/ctrld/cli.go index 2a6872f..2a12c12 100644 --- a/cmd/ctrld/cli.go +++ b/cmd/ctrld/cli.go @@ -743,6 +743,13 @@ func processCDFlags() { listener.Port = 53 } } + // On router, we want to keep the listener address point to dnsmasq listener, aka 127.0.0.1:53. + if router.Name() != "" { + if lc := cfg.Listener["0"]; lc != nil { + lc.IP = "127.0.0.1" + lc.Port = 53 + } + } } else { cfg = ctrld.Config{} cfg.Network = make(map[string]*ctrld.NetworkConfig) diff --git a/internal/router/ddwrt.go b/internal/router/ddwrt.go index ad6e921..52a5732 100644 --- a/internal/router/ddwrt.go +++ b/internal/router/ddwrt.go @@ -1,11 +1,9 @@ package router import ( - "bytes" "errors" "fmt" "os/exec" - "strings" ) const ( @@ -19,12 +17,6 @@ var ddwrtJffs2NotEnabledErr = errors.New(`could not install service without jffs https://wiki.dd-wrt.com/wiki/index.php/Journalling_Flash_File_System `) -var nvramKeys = map[string]string{ - "dns_dnsmasq": "1", // Make dnsmasq running but disable DNS ability, ctrld will replace it. - "dnsmasq_options": "", // Configuration of dnsmasq set by ctrld, filled by setupDDWrt. - "dns_crypt": "0", // Disable DNSCrypt. -} - func setupDDWrt() error { // Already setup. if val, _ := nvram("get", nvramCtrldSetupKey); val == "1" { @@ -35,28 +27,13 @@ func setupDDWrt() error { if err != nil { return err } - nvramKeys["dnsmasq_options"] = data - // Backup current value, store ctrld's configs. - for key, value := range nvramKeys { - old, err := nvram("get", key) - if err != nil { - return fmt.Errorf("%s: %w", old, err) - } - if out, err := nvram("set", nvramCtrldKeyPrefix+key+"="+old); err != nil { - return fmt.Errorf("%s: %w", out, err) - } - if out, err := nvram("set", key+"="+value); err != nil { - return fmt.Errorf("%s: %w", out, err) - } + + nvramKvMap := nvramKV() + nvramKvMap["dnsmasq_options"] = data + if err := nvramSetup(nvramKvMap); err != nil { + return err } - if out, err := nvram("set", nvramCtrldSetupKey+"=1"); err != nil { - return fmt.Errorf("%s: %w", out, err) - } - // Commit. - if out, err := nvram("commit"); err != nil { - return fmt.Errorf("%s: %w", out, err) - } // Restart dnsmasq service. if err := ddwrtRestartDNSMasq(); err != nil { return err @@ -66,24 +43,8 @@ func setupDDWrt() error { func cleanupDDWrt() error { // Restore old configs. - for key := range nvramKeys { - ctrldKey := nvramCtrldKeyPrefix + key - old, err := nvram("get", ctrldKey) - if err != nil { - return fmt.Errorf("%s: %w", old, err) - } - _, _ = nvram("unset", ctrldKey) - if out, err := nvram("set", key+"="+old); err != nil { - return fmt.Errorf("%s: %w", out, err) - } - } - - if out, err := nvram("unset", "ctrld_setup"); err != nil { - return fmt.Errorf("%s: %w", out, err) - } - // Commit. - if out, err := nvram("commit"); err != nil { - return fmt.Errorf("%s: %w", out, err) + if err := nvramRestore(nvramKV()); err != nil { + return err } // Restart dnsmasq service. if err := ddwrtRestartDNSMasq(); err != nil { @@ -96,17 +57,6 @@ func postInstallDDWrt() error { return nil } -func nvram(args ...string) (string, error) { - cmd := exec.Command("nvram", args...) - var stdout, stderr bytes.Buffer - cmd.Stdout = &stdout - cmd.Stderr = &stderr - if err := cmd.Run(); err != nil { - return "", fmt.Errorf("%s:%w", stderr.String(), err) - } - return strings.TrimSpace(stdout.String()), nil -} - func ddwrtRestartDNSMasq() error { if out, err := exec.Command("restart_dns").CombinedOutput(); err != nil { return fmt.Errorf("restart_dns: %s, %w", string(out), err) diff --git a/internal/router/merlin.go b/internal/router/merlin.go index b2386bf..ca739cb 100644 --- a/internal/router/merlin.go +++ b/internal/router/merlin.go @@ -38,10 +38,19 @@ func setupMerlin() error { if err := merlinRestartDNSMasq(); err != nil { return err } + + if err := nvramSetup(nvramKV()); err != nil { + return err + } + return nil } func cleanupMerlin() error { + // Restore old configs. + if err := nvramRestore(nvramKV()); err != nil { + return err + } buf, err := os.ReadFile(merlinDNSMasqPostConfPath) if err != nil && !os.IsNotExist(err) { return err diff --git a/internal/router/nvram.go b/internal/router/nvram.go new file mode 100644 index 0000000..79a7657 --- /dev/null +++ b/internal/router/nvram.go @@ -0,0 +1,84 @@ +package router + +import ( + "bytes" + "fmt" + "os/exec" + "strings" +) + +func nvram(args ...string) (string, error) { + cmd := exec.Command("nvram", args...) + var stdout, stderr bytes.Buffer + cmd.Stdout = &stdout + cmd.Stderr = &stderr + if err := cmd.Run(); err != nil { + return "", fmt.Errorf("%s:%w", stderr.String(), err) + } + return strings.TrimSpace(stdout.String()), nil +} + +func nvramKV() map[string]string { + switch Name() { + case DDWrt: + return map[string]string{ + "dns_dnsmasq": "1", // Make dnsmasq running but disable DNS ability, ctrld will replace it. + "dnsmasq_options": "", // Configuration of dnsmasq set by ctrld, filled by setupDDWrt. + "dns_crypt": "0", // Disable DNSCrypt. + } + case Merlin: + return map[string]string{ + "dnspriv_enable": "0", // Ensure Merlin native DoT disabled. + } + } + return nil +} + +func nvramSetup(m map[string]string) error { + // Backup current value, store ctrld's configs. + for key, value := range m { + old, err := nvram("get", key) + if err != nil { + return fmt.Errorf("%s: %w", old, err) + } + if out, err := nvram("set", nvramCtrldKeyPrefix+key+"="+old); err != nil { + return fmt.Errorf("%s: %w", out, err) + } + if out, err := nvram("set", key+"="+value); err != nil { + return fmt.Errorf("%s: %w", out, err) + } + } + + if out, err := nvram("set", nvramCtrldSetupKey+"=1"); err != nil { + return fmt.Errorf("%s: %w", out, err) + } + // Commit. + if out, err := nvram("commit"); err != nil { + return fmt.Errorf("%s: %w", out, err) + } + return nil +} + +func nvramRestore(m map[string]string) error { + // Restore old configs. + for key := range m { + ctrldKey := nvramCtrldKeyPrefix + key + old, err := nvram("get", ctrldKey) + if err != nil { + return fmt.Errorf("%s: %w", old, err) + } + _, _ = nvram("unset", ctrldKey) + if out, err := nvram("set", key+"="+old); err != nil { + return fmt.Errorf("%s: %w", out, err) + } + } + + if out, err := nvram("unset", "ctrld_setup"); err != nil { + return fmt.Errorf("%s: %w", out, err) + } + // Commit. + if out, err := nvram("commit"); err != nil { + return fmt.Errorf("%s: %w", out, err) + } + return nil +}