-
Notifications
You must be signed in to change notification settings - Fork 21
NextDNS Mode
v1.3.2 or newer must be installed in order to use this guide.
ctrld
is a customizable DNS forwarding proxy server that runs on any operating system, most routers, and can be used to send DNS queries to any upstream, using any DNS protocol. NextDNS mode allows for a 1 liner command setup of ctrld
with NextDNS service, while relaying client specific metadata (MAC address, IP address, Hostname) to a NextDNS upstream, similar to the native app.
As far as I can tell, ctrld
is feature complete with the NextDNS analog (all functionality of the NextDNS app is supported as of v1.3.2), but also includes other functionality such as support for all DNS protocols, multiple listeners, richer configuration syntax, support for more routers, and highly advanced modes of operation.
- Asus Merlin
- DD-WRT
- Firewalla
- FreshTomato
- GL.iNet
- OpenWRT
- pfSense / OPNsense
- Synology
- Ubiquiti (UniFi, EdgeOS)
- Windows
- MacOS
- Linux (any)
We want you to try our app with NextDNS, love all the things you can do with it, and then maybe check out this Control D thing.
You can get the binaries here, but the simplest way to get ctrld
on your device is using the installer command:
sh -c 'sh -c "$(curl -sL https://api.controld.com/dl)"'
Run this in cmd
not Powershell.
powershell -Command "(Invoke-WebRequest -Uri 'https://api.controld.com/dl' -UseBasicParsing).Content | Set-Content 'ctrld_install.bat'" && ctrld_install.bat
The above commands will install the binary into the correct directory (installer will show you where), based on your platform. Here is an example from pfSense, but all platforms are the same.
[2.7.0-RELEASE][root@pfSense.home.arpa]/root: sh -c 'sh -c "$(curl -sSL https://api.controld.com/dl)"'
__ .__ .___
_____/ |________| | __| _/
_/ ___\ __\_ __ \ | / __ |
\ \___| | | | \/ |__/ /_/ |
\___ >__| |__| |____/\____ |
\/ installer \/
---------------------
| System Info |
---------------------
OS Type : freebsd
OS Vendor : pfSense
Arch : amd64
CPU : 13th Gen Intel(R) Core(TM) i7-13700K
Free RAM : 70 MB / 448 MB
---------------------
| Install Details |
---------------------
Binary URL : https://assets.controld.com/ctrld/freebsd/amd64/ctrld
Install Path : /usr/local/bin
---------------------
Install binary and run it? (y/n): y
- Starting download
- Making binary executable
- Launching /usr/local/bin/ctrld
---------------------
__ .__ .___
_____/ |________| | __| _/
_/ ___\ __\_ __ \ | / __ |
\ \___| | | | \/ |__/ /_/ |
\___ >__| |__| |____/\____ |
\/ dns forwarding proxy \/
Usage:
ctrld [command]
Available Commands:
run Run the DNS proxy server
service Manage ctrld service
start Quick start service and configure DNS on interface
stop Quick stop service and remove DNS from interface
restart Restart the ctrld service
reload Reload the ctrld service
status Show status of the ctrld service
uninstall Stop and uninstall the ctrld service
clients Manage clients
Flags:
-h, --help help for ctrld
-s, --silent do not write any log output
-v, --verbose count verbose log output, "-v" basic logging, "-vv" debug level logging
--version version for ctrld
Use "ctrld [command] --help" for more information about a command.
[2.7.0-RELEASE][root@pfSense.home.arpa]/root:
The binary is installed, but currently not doing anything. In order for it to do stuff, use the start
command with the --nextdns
flag, while supplying your ID.
[2.7.0-RELEASE][root@pfSense.home.arpa]/root: ctrld start --nextdns 8cec72
Nov 20 22:44:21.000 NTC Starting service
Nov 20 22:44:21.000 NTC Generating nextdns config: /etc/controld/ctrld.toml
Nov 20 22:44:26.000 NTC Service started
That's it, you're done here. You can check that it works using a dig or nslookup command, or simply view your Logs in NextDNS.
[2.7.0-RELEASE][root@pfSense.home.arpa]/root: dig test.com
; <<>> DiG 9.18.14 <<>> test.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 25793
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;test.com. IN A
;; ANSWER SECTION:
test.com. 3600 IN A 67.225.146.248
;; Query time: 42 msec
;; SERVER: 127.0.0.1#53(127.0.0.1) (UDP)
;; WHEN: Mon Nov 20 22:44:38 UTC 2023
;; MSG SIZE rcvd: 53
[2.7.0-RELEASE][root@pfSense.home.arpa]/root:
By default, ctrld
will send all traffic from your device or router to the chosen NextDNS profile, using DOH3 protocol, while appending LAN metadata just like the native app. If you wish to get fancy, read on.
Everything is config driven, and the start
command will tell you where the config was written to, usually it's /etc/controld/
but the path can differ based on your router platform. You can edit this config to get ctrld
to route your DNS queries in highly advanced ways. Here is some relevant material to get you started:
Once you crafted your perfect config, simply run: ctrld restart
in order for changes to kick in. To see what LAN clients ctrld
discovered using DHCP leases file, arp, mDNS, PTR probes or hosts file, you can run the ctrld clients list
command. This client data will be appended to DNS queries. Be mindful, that this only works when DNS-over-HTTPS (any version) is used. DOT and DOQ don't support this.
[2.7.0-RELEASE][root@pfSense.home.arpa]/root: ctrld clients list
+-----------------------------------------+------------+-------------------+------------+
| IP | Hostname | Mac | Discovered |
+-----------------------------------------+------------+-------------------+------------+
| 10.0.10.1 | | 00:50:56:9f:0e:84 | arp |
| 10.0.10.209 | pfSense | 00:0c:29:f5:a3:55 | arp,dhcp |
| 10.0.10.238 | Office-Box | 74:56:3c:44:eb:5e | arp,mdns |
| 10.0.10.245 | Test-W11 | | mdns |
| 127.0.0.1 | pfSense | 00:0c:29:f5:a3:55 | dhcp |
| ::1 | pfSense | 00:0c:29:f5:a3:55 | dhcp |
| 2607:f0c8:8000:8210:10a:e664:e855:1f61 | Office-Box | | mdns |
| 2607:f0c8:8000:8210:20c:29ff:fef5:a355 | pfSense | 00:0c:29:f5:a3:55 | dhcp |
| 2607:f0c8:8000:8210:2d11:e044:9e90:a14c | Test-W11 | | mdns |
| 2607:f0c8:8000:8210:4d66:459f:6b76:1c16 | Test-W11 | | mdns |
| 2607:f0c8:8000:8210:dcf4:5b74:4f7e:bd7f | Office-Box | | mdns |
| fe80::20c:29ff:fef5:a355 | pfSense | 00:0c:29:f5:a3:55 | dhcp |
| fe80::1554:c4ab:cfba:189 | Office-Box | | mdns |
| fe80::ab3f:8a1c:df6b:91b9 | Test-W11 | | mdns |
+-----------------------------------------+------------+-------------------+------------+
[2.7.0-RELEASE][root@pfSense.home.arpa]/root:
By the way, ctrld
will resolve any LAN-local A or PTR record for you, using the data it has in the client list.
[2.7.0-RELEASE][root@pfSense.home.arpa]/var: dig +short Test-W11
10.0.10.245
[2.7.0-RELEASE][root@pfSense.home.arpa]/var: dig +short -x 10.0.10.245
Test-W11.
Much like in the native app, you can steer DNS queries to different NextDNS Profiles based on:
- hostnames
- MAC addresses
- IP networks
This is accomplished using policies. Let's take a look at an example config file. Before you panic, it's simpler (and more powerful) than it looks.
[listener]
[listener.0]
ip = '0.0.0.0'
port = 53
[listener.0.policy]
name = 'My Policy'
networks = [
{'network.0' = ['upstream.0']},
{'network.1' = ['upstream.1']}
]
rules = [
{ '*.cool.domain' = ['upstream.1']},
{ '*.in-addr.arpa' = ['upstream.1']}
]
macs = [
{"14:54:4a:8e:08:2d" = ["upstream.1"]}
]
[network]
[network.0]
name = 'Main Subnets'
cidrs = ['10.0.0.0/24', '10.0.1.0/24']
[network.1]
name = 'Secret Subnet'
cidrs = ['10.0.99.0/24']
[upstream]
[upstream.0]
name = 'My NextDNS Resolver'
type = 'doh3'
endpoint = 'https://dns.nextdns.io/qwerty'
timeout = 5000
[upstream.1]
name = 'My Fancy Control D Resolver'
type = 'doh3'
endpoint = 'https://dns.controld.com/abcd1234'
timeout = 5000
Not all params are needed, and shown for illustrative purposes only. Let's go over the config section by section.
- In the
[listener]
block we define our.... listener with an IP + port. - In the
[listener.0.policy]
block we define the policy of how DNS traffic should be routed, let's skip that over for a second. - In the
[network]
block we define our subnets if you want to leverage source IP based routing. If you do not, don't define any. - In the
[upstream]
block we define our DNS upstreams where DNS traffic should be sent. You should have at least one of these, but here we have 2. - Coming back to the
[listener.0.policy]
block. It strings together the definednetworks
andupstreams
, as well as new concepts likerules
andmacs
and defines which upstream should be used if there is a match. - The matching order is: rules => macs => networks
So for example:
- A DNS query from
10.0.0.5
would be sent toupstream.0
, while a query from10.0.99.123
would be sent toupstream.1
- A DNS query for
my-host.cool.domain
from any subnet would be sent toupstream.1
(since host rules match first) - A DNS query from a device with MAC address
14:54:4a:8e:08:2d
from any subnet would be sent toupstream.1
(since MAC rules match 2nd). - All PTR queries would be sent to
upstream.1
You can find more example configs for different use cases in the Wiki.
That's all there is to it. If you spot any issues with this guide, let us know.