6.8 KiB
Get started
Run nxdns on your own computer, point a query at it, and watch it block an ad domain from a real blocklist. Everything happens in one directory and on unprivileged ports, so nothing on your machine changes and nothing needs root. At the end you stop it and delete the directory.
You need a Linux machine (x86_64 or aarch64), curl, and dig (from bind-tools or dnsutils). nxdns is a single static binary with no dependencies.
1. Download
Make a directory to work in, download the release for your machine with its checksum file, and check the download:
mkdir ~/nxdns-try && cd ~/nxdns-try
curl -fLO https://git.mial.net/mokhtar/nxdns/releases/download/v<version>/nxdns-<version>-x86_64-linux-musl.tar.gz
curl -fLO https://git.mial.net/mokhtar/nxdns/releases/download/v<version>/SHA256SUMS.txt
sha256sum -c --ignore-missing SHA256SUMS.txt
nxdns-<version>-x86_64-linux-musl.tar.gz: OK
On a Raspberry Pi or another 64-bit ARM machine, replace x86_64 with aarch64 in the URL and in the commands below. The checksum file is signed; Verify a release shows how to check the signature as well, which is worth doing before a real install.
Unpack it and go into the directory it creates:
tar -xzf nxdns-<version>-x86_64-linux-musl.tar.gz
cd nxdns-<version>-x86_64-linux-musl
./nxdns version
nxdns <version>
zig 0.16.0
2. Write a configuration
nxdns needs two things before it starts: a group called default, which every device belongs to until you say otherwise, and an upstream resolver to forward the queries it does not answer itself. Create config.zon:
cat > config.zon <<'EOF'
.{
.dns = .{ .bind_ipv4 = "127.0.0.1", .bind_ipv6 = "::1", .port = 5300 },
.web = .{ .bind = "127.0.0.1", .port = 8080 },
.groups = .{ .{ .name = "default" } },
.upstreams = .{ .{ .url = "https://cloudflare-dns.com/dns-query" } },
}
EOF
DNS listens on port 5300 instead of 53, and both DNS and the web interface listen on this machine only. Port 53 needs root, which is a decision for a real install, not for a first try. Every field you did not set keeps its default; the configuration reference lists them all.
Check the file:
./nxdns check --config config.zon
checking configuration file config.zon
OK upstreams[0] https://cloudflare-dns.com
OK: no problems found
check validates the file and sends one real query to each upstream to confirm it answers. It changes nothing, so you can run it as often as you like.
3. Load it and start
Load the file into a new data directory, then start the server:
./nxdns import config.zon --data-dir data
./nxdns run --data-dir data
info(migrations): config.db migrated from schema version 0 to 1
imported config.zon
info(querylog_schema): created querylog database 'data/querylog.db'
info(blocklist_manager): blocklist snapshot generation 1: 0 of 0 sources loaded, 231 bytes
info(nxdns): authority: database
info(nxdns): nxdns <version> serving on udp [::1]:5300 udp 127.0.0.1:5300 tcp [::1]:5300 tcp 127.0.0.1:5300; 1 upstream(s); blocklist generation 1
info(web_server): web interface listening on 127.0.0.1:8080
authority: database means the configuration now lives in data/config.db, and you change it from the web interface. The file has done its job. (nxdns can also treat the file as the configuration at every start; the configuration model explains both modes.)
Leave the server running in this terminal and open a second one.
4. Resolve a name
dig @127.0.0.1 -p 5300 example.com A +noall +answer
example.com. 214 IN A 104.20.23.154
example.com. 214 IN A 172.66.147.243
nxdns forwarded the query to Cloudflare over HTTPS and returned the answer. It blocks nothing yet: the log said 0 of 0 sources loaded.
5. Add a blocklist
Open http://127.0.0.1:8080 in a browser. There is no password yet, so the Overview opens straight away; Set up admin authentication adds one before the interface leaves your machine.
- Go to Protection and open the Sources tab.
- Under Add source, set URL to
https://raw.githubusercontent.com/StevenBlack/hosts/master/hostsand Name toStevenBlack hosts, then press Add source. - Open the Groups tab. The
defaultgroup is selected. Under Assigned sources, tick StevenBlack hosts and press Save sources. - Back on the Sources tab, press Update now.
After a few seconds the source shows its size, something like 71,494 domains · 0 wildcards · 0 exceptions, and the server log says 1 of 1 sources loaded.
Step 3 matters. A source belongs to the whole installation, and each group picks the sources it uses, which is how one group of devices can get a strict list while another gets none. A source no group uses is downloaded and blocks nothing.
6. Watch a domain get blocked
In the browser, go to Activity and open the Live tab. Then, in your second terminal:
dig @127.0.0.1 -p 5300 doubleclick.net A +noall +answer
doubleclick.net. 5 IN A 0.0.0.0
0.0.0.0 is the block answer, with a short TTL so a device forgets it soon after you unblock a domain. The query appears in the Live tab at once, marked Blocked.
A domain that is not on the list still resolves normally:
dig @127.0.0.1 -p 5300 wikipedia.org A +short
The History tab keeps every query. It is written to disk about once a minute, so give it that long. Then select doubleclick.net to see why it was blocked: the decision, the reason (Blocklist (domain)), the entry that matched and the list it came from (StevenBlack hosts).
A hosts list blocks exactly the names it lists. doubleclick.net and ad.doubleclick.net are both on this one, but a name the file does not list resolves even when its parent is blocked. To block every name under a domain, add a wildcard rule such as *.doubleclick.net under Rules on the group; it covers the names below doubleclick.net, not doubleclick.net itself. An Adblock Plus list's ||doubleclick.net^ entries cover both.
7. Stop and clean up
Press Ctrl-C in the first terminal. nxdns logs shutting down and exits. Then remove the directory:
rm -rf ~/nxdns-try
Next
- Install it for real, on port 53 for your whole network: with Docker, with systemd, or on NixOS.
- Set up admin authentication before the web interface is reachable from other machines.
- The configuration model explains the choice between configuring nxdns in the web interface and keeping a file in git.