diff --git a/README.md b/README.md index 69018d6..9839d88 100644 --- a/README.md +++ b/README.md @@ -73,7 +73,13 @@ $ go install github.com/Control-D-Inc/ctrld/cmd/ctrld@latest $ docker build -t controld/ctrld . $ docker run -d --name=ctrld -p 53:53/tcp -p 53:53/udp controld/ctrld --cd=p2 -vv ``` +----- +*NOTE* +When running inside container, and listener address is set to "127.0.0.1:53", `ctrld` will change +the listen address to "0.0.0.0:53", so users can expose the port to outside. + +---- # Usage The cli is self documenting, so free free to run `--help` on any sub-command to get specific usages. @@ -176,6 +182,15 @@ In order to start `ctrld` as a DNS provider, simply run `./ctrld setup auto` com In this mode, and when Control D upstreams are used, the router will [relay your network topology](https://docs.controld.com/docs/device-clients) to Control D (LAN IPs, MAC addresses, and hostnames), and you will be able to see your LAN devices in the web panel, view analytics and apply unique profiles to them. +---- +*NOTE* + +`ctrld` will try leveraging default setup on routers, so changing routers default configuration would causes things won't work as expected (For example, changing dnsmasq configuration). + +Advanced users who want to play around, just run `ctrld` in [Service Mode](#service-mode) with custom configuration. + +---- + ### Control D Auto Configuration Application can be started with a specific resolver config, instead of the default one. Simply supply your Resolver ID with a `--cd` flag, when using the `run` (foreground) or `start` (service) or `setup` (router) modes. diff --git a/cmd/ctrld/cli.go b/cmd/ctrld/cli.go index 5e16aae..dc80ebd 100644 --- a/cmd/ctrld/cli.go +++ b/cmd/ctrld/cli.go @@ -751,11 +751,10 @@ 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 setupRouter { if lc := cfg.Listener["0"]; lc != nil { - lc.IP = "127.0.0.1" - lc.Port = 53 + lc.IP = router.ListenIP() + lc.Port = router.ListenPort() } } } else { @@ -776,7 +775,7 @@ func processCDFlags() { rules = append(rules, ctrld.Rule{domain: []string{}}) } cfg.Listener = make(map[string]*ctrld.ListenerConfig) - cfg.Listener["0"] = &ctrld.ListenerConfig{ + lc := &ctrld.ListenerConfig{ IP: "127.0.0.1", Port: 53, Policy: &ctrld.ListenerPolicyConfig{ @@ -784,6 +783,11 @@ func processCDFlags() { Rules: rules, }, } + if setupRouter { + lc.IP = router.ListenIP() + lc.Port = router.ListenPort() + } + cfg.Listener["0"] = lc processLogAndCacheFlags() } diff --git a/cmd/ctrld/dns_proxy.go b/cmd/ctrld/dns_proxy.go index 626c329..970d52e 100644 --- a/cmd/ctrld/dns_proxy.go +++ b/cmd/ctrld/dns_proxy.go @@ -402,8 +402,11 @@ func needLocalIPv6Listener() bool { } func dnsListenAddress(lcNum string, lc *ctrld.ListenerConfig) string { - if addr := router.ListenAddress(); setupRouter && addr != "" && lcNum == "0" { - return addr + addr := net.JoinHostPort(lc.IP, strconv.Itoa(lc.Port)) + // If we are inside container and the listener address is localhost, + // Change it to 0.0.0.0:53, so user can expose the port to outside. + if addr == "127.0.0.1:53" && cdUID != "" && inContainer() { + return "0.0.0.0:53" } return net.JoinHostPort(lc.IP, strconv.Itoa(lc.Port)) } diff --git a/docs/config.md b/docs/config.md index 8af8e40..c652afe 100644 --- a/docs/config.md +++ b/docs/config.md @@ -316,14 +316,14 @@ IP address that serves the incoming requests. If `ip` is empty, ctrld will liste - Type: ip address string - Required: no -- Default: "" +- Default: "" or "127.0.0.1" in [Router Mode](../README.md#router-mode). ### port Port number that the listener will listen on for incoming requests. If `port` is `0`, a random available port will be chosen. - Type: number - Required: no -- Default: 0 +- Default: 0 or 5354 in [Router Mode](../README.md#router-mode). ### restricted If set to `true` makes the listener `REFUSE` DNS queries from all source IP addresses that are not explicitly defined in the policy using a `network`. diff --git a/internal/router/firewalla.go b/internal/router/firewalla.go index 7b7e6ea..1182890 100644 --- a/internal/router/firewalla.go +++ b/internal/router/firewalla.go @@ -69,7 +69,7 @@ func cleanupFirewalla() error { // Restart dnsmasq service. if err := restartDNSMasq(); err != nil { - return fmt.Errorf("cleaupFirewalla: restartDNSMasq: %w", err) + return fmt.Errorf("cleanupFirewalla: restartDNSMasq: %w", err) } return nil diff --git a/internal/router/router.go b/internal/router/router.go index d3beda7..153f97e 100644 --- a/internal/router/router.go +++ b/internal/router/router.go @@ -214,16 +214,21 @@ func Cleanup(svc *service.Config) error { return nil } -// ListenAddress returns the listener address of ctrld on router. -func ListenAddress() string { +// ListenIP returns the listener IP of ctrld on router. +func ListenIP() string { + return "127.0.0.1" +} + +// ListenPort returns the listener port of ctrld on router. +func ListenPort() int { name := Name() switch name { case DDWrt, Firewalla, Merlin, OpenWrt, Synology, Tomato, Ubios: - return "127.0.0.1:5354" + return 5354 case Pfsense: // On pfsense, we run ctrld as DNS resolver. } - return "" + return 53 } // Name returns name of the router platform.