Dnsmasq-based DNS blocking Published the 2019-11-11 Ads and trackers sucks (nothing new). They destroy websites, slow down the web, exclude mobile / low power computer users, and trace users in a way no sec. agency could achieve. I've been using Pihole[^pihole] for a long time, but I really have some issues with their tool: - The auto-updater is a standalone mechanism and not system-bound, which makes automated updates a pain; - The web UI is in PHP, which forces me to have both PHP *and* their reverse proxy set up if I don't want to spend 2h configuring everything by myself; - Debugging the DNS configuration is pretty painful due to almost no log. For this reason, I decided to re-do my DNS-based ad blocking setup and go for a raw `dnsmasq`[^dnsmasq] server, coupled with the [hosts-blocklists](https://github.com/notracking/hosts-blocklists) project. This article documents my setup. ## Server setup and configuration As said, I'm using `dnsmasq`, and the hosts-blocklists project. The first step is to create a directory in which I'll put the domains and host names. ``` $ mkdir /usr/lib/blocklists ``` The README provides the two direct raw links towards the list, which is nice. I'm putting both links in a file, one link per line, at `/etc/blocklists-sources.txt`, then I'm downloading them into my local directory. ``` $ cat < /etc/blocklists-sources.txt https://raw.githubusercontent.com/notracking/hosts-blocklists/master/hostnames.txt https://raw.githubusercontent.com/notracking/hosts-blocklists/master/domains.txt EOF $ wget -i /etc/blocklists-sources.txt -P /usr/lib/blocklists ``` Since I never used `dnsmasq` on this server, I can just destroy the entire configuration file, and make an almost-empty one with what I want. ``` $ mv /etc/dnsmasq.conf{,.original} $ cat < /etc/dnsmasq.conf conf-file=/usr/lib/blocklists/domains.txt addn-hosts=/usr/lib/blocklists/hostnames.txt EOF ``` I can now restart the dnsmasq server. ``` $ systemctl stop dnsmasq $ systemctl start dnsmasq ``` And just to keep it up even after a restart, I'll enable it. ``` $ systemctl enable dnsmasq ``` Now we can test it! Works fine for my own DN. ``` $ dig @127.0.0.1 artemix.org ; <<>> DiG 9.11.5-P4-5.1-Raspbian <<>> @127.0.0.1 artemix.org ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 56331 ;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 1452 ;; QUESTION SECTION: ;artemix.org. IN A ;; ANSWER SECTION: artemix.org. 3600 IN A 104.198.14.52 ;; Query time: 155 msec ;; SERVER: 127.0.0.1#53(127.0.0.1) ;; WHEN: Mon Nov 11 18:47:14 GMT 2019 ;; MSG SIZE rcvd: 56 ``` And successfully blocks the cancer that is Google! ``` $ dig @127.0.0.1 googletagmanager.com ; <<>> DiG 9.11.5-P4-5.1-Raspbian <<>> @127.0.0.1 googletagmanager.com ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 48980 ;; flags: qr aa rd ra ad; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 4096 ;; QUESTION SECTION: ;googletagmanager.com. IN A ;; ANSWER SECTION: googletagmanager.com. 0 IN A 0.0.0.0 ;; Query time: 32 msec ;; SERVER: 127.0.0.1#53(127.0.0.1) ;; WHEN: Mon Nov 11 18:47:18 GMT 2019 ;; MSG SIZE rcvd: 65 ``` ## Automating updates Now I want to be kept up to date, and I don't want to bother with ssh'ing every time. A quick script called by cron can easily do the job. Note that there is no file ownership control going on here. ```bash #!/usr/bin/env bash SOURCE_FILES=/etc/blocklists-sources.txt CACHE_DIR=/usr/lib/blocklists/ DNS_SERVICE=dnsmasq # Cleanup rm -rf /usr/lib/blocklists/*.txt # Download wget -i "$SOURCE_FILES" -P "$CACHE_DIR" # Service restart systemctl restart "$DNS_SERVICE" ``` Now, I can make it executable and add a cron job for it. ``` $ chmod +x /usr/bin/update-blocklists $ crontab -l > $HOME/tmp-crontab $ echo "0 * * * * /usr/bin/update-blocklists" >> $HOME/tmp-crontab $ crontab $HOME/tmp-crontab $ rm $HOME/tmp-crontab ``` > Note that dealing with temporary files is better done with mktemp[^mktemp] > instead of by hand. > I didn't, for convenience, and instead created the temporary file in the > user's home directory. Now, I have an easy-to-setup, easy-to-maintain ad-blocking server! [^pihole]: DNS-based ad blocking, see the [official website](https://pi-hole.net/). [^dnsmasq]: DNS masquerade, DNS server project made to simulate and proxy answers ([official website](http://www.thekelleys.org.uk/dnsmasq/doc.html)). [^mktemp]: "Safely creating and using temporary files" - [source](https://www.netmeister.org/blog/mktemp.html)