Set up local DNS and ad blocking
As mentioned in my Valid TLS cert for local services with Traefik post, I run local services with a valid domain. I could’ve set up a custom non-existent domain + funny TLD, but creating a certificate for that would’ve made things much harder. Now I wanted to make a few services available via subdomains. I didn’t really like the fact of setting up these records on Cloudflare, where my domain is hosted, so a local DNS server was the way to go.
There are DNS servers like BIND, Knot and a few more alternatives but when setting this up, why not also block Ads and possible malicious domains at the same time? There are options like Pi-hole or AdGuardHome. For whatever reason I went with something different: blocky. I can’t even give a proper reason why I choose it. Maybe it had something to do with the fact that it is entirely written in Go and or that some benchmarks compared it against Pi-hole putting it in the first place when it comes to speed and performance.
Blocky doesn’t provide a web interface. It does have an API though. Said API provides the ability to enable/disable blocking, has an extra query endpoint and provides an endpoint to refresh the configured blocking lists. That’s it. Everything else has to be configured via its configuration file.
This is the first part of my configuration which basically handles the name resolution.
upstream: default: - tcp-tls:184.108.40.206:853 - tcp-tls:220.127.116.11:853 customDNS: mapping: example.com: 192.168.0.7 conditional: mapping: fritz.box: tcp+udp:192.168.0.1 168.192.in-addr.arpa: tcp+udp:192.168.0.1 17.172.in-addr.arpa: tcp+udp:192.168.0.7:15353 clientLookup: upstream: 192.168.0.1 singleNameOrder: - 1
upstream DNS, I stick to Cloudflare’s 18.104.22.168. Blocky has the ability to perform upstream requests
via standard DNS over UDP/TCP, DoH and DoT. In my case it’s the latter: DNS over TLS. The
default keyword indicates the DNS
servers that are used as default (duh), but Blocky has the ability to group clients. If I want all my iot devices to use a
different DNS server, I could in theory do so.
customDNS is the main option, that makes my setup work the way it is. Blocky will return
192.168.0.7 for all queries for
example.com, which also includes all subdomains like
foobar.example.com. This is the behaviour I
want because on this IP address, a traefik server is listening and will handle the proxying based on the host name / subdomain.
conditional entries are another nice feature. DNS lookups like
foobar.fritz.box will be handled by
of my configured DNS servers. The same thing works for reverse DNS lookups. In my case it’s again for normal clients in my
network and for an experimental Docker reverse DNS resolver. Somewhat redundant, but for blocky’s internal client lookup that is
being used in logs, Prometheus output etc, the
clientLookup should be configured as well.
Second part of my configuration:
filtering: queryTypes: - AAAA blocking: blockType: zeroIP refreshPeriod: 4h downloadTimeout: 4m downloadCooldown: 10s blackLists: malware: - https://urlhaus.abuse.ch/downloads/hostfile/ ads: - https://s3.amazonaws.com/lists.disconnect.me/simple_ad.txt - https://someonewhocares.org/hosts/zero/hosts - https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts - https://raw.githubusercontent.com/notracking/hosts-blocklists/master/hostnames.txt - https://adaway.org/hosts.txt - https://raw.githubusercontent.com/bigdargon/hostsVN/master/hosts - https://raw.githubusercontent.com/mitchellkrogza/Badd-Boyz-Hosts/master/hosts clientGroupsBlock: default: - ads - malware httpPort: 4000 bootstrapDns: tcp+udp:22.214.171.124 prometheus: enable: true queryLog: type: none
filtering settings allow me to filter out certain DNS queries. Since I didn’t have much luck with IPv6 in the past, I simply
kill all IPv6 requests.
blocking part is probably the most interesting one. You can configure blacklist sources. Only lists of the
hosts type are
supported. So in theory these lists can be placed in
/etc/hosts or the Windows’ hosts file. Instead of using the IP that is configured
in said lists, blocky will replace it with the IP that is configured via
blockType. Again, things can be grouped and then applied to
all or just a certain list of hosts as you can see in
clientGroupsBlock. This repository
is a good source for block lists. Blocky will handle duplicate entries by itself.
Beside that, you can configure the listening ports. Standard DNS will listen on port
53, DoT on
853 etc. The
blocky’s internal API and prometheus endpoint. The query log can be enabled and requires further configuration. This option will
enable logging for all DNS queries to a database, console or log file. I don’t want to log anything, which is why it’s disabled.
In order configure all my local clients to use my local DNS, I simply announce it via DHCP via my FRITZ!Box router.