I ran Pi-hole as a docker container for several years now in order to block various unwanted DNS requests in my home network. That kind of worked but I had a lot of issues that I wasn’t able to solve or at least to figure out what caused them.
A few days ago this went sideways in a way that my entire network became unusable. So I decided to get rid of Pi-hole and use the normal DNS servers provided by my ISP.
I considered using AdGuard Home but I’ve read many things about it that let me hesitate. Fortunately I stumbled accross Blocky after looking for an altenative.
Blocky is a quote “DNS proxy and ad-blocker for the local network written in Go”. It ticked several of my checkboxes:
- Docker container available
- Small footprint
- Open Source Software
- Easy to configure
So I gave it a shot and it didn’t dissapoint me!
Here’s my docker-compose.yaml snippet
1 blocky:
2 container_name: blocky
3 image: spx01/blocky
4 restart: unless-stopped
5 hostname: blocky
6 ports:
7 - "53:53/tcp"
8 - "53:53/udp"
9 - "4000:4000/tcp"
10 environment:
11 - TZ=Europe/Berlin
12 volumes:
13 - /etc/localtime:/etc/localtime:ro
14 - /opt/docker/blocky/config.yml:/app/config.yml
And my config file (slightly redacted 😏)
1upstream:
2 default:
3 - 5.9.164.112
4 - 1.1.1.1
5 - tcp-tls:fdns1.dismail.de:853
6 - https://dns.digitale-gesellschaft.ch/dns-query
7
8upstreamTimeout: 2s
9
10connectIPVersion: dual
11
12customDNS:
13 customTTL: 1h
14 filterUnmappedTypes: true
15 mapping:
16 router: 192.168.88.1
17 heatpump: 192.168.88.5
18 feinstaubsensor: 192.168.88.20
19 homeassistant: 192.168.88.25
20
21blocking:
22 blackLists:
23 iot:
24 - |
25 /broadlink.com.cn/
26 ads:
27 - https://s3.amazonaws.com/lists.disconnect.me/simple_ad.txt
28 - https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts
29 - http://sysctl.org/cameleon/hosts
30 - https://s3.amazonaws.com/lists.disconnect.me/simple_tracking.txt
31 special:
32 - https://raw.githubusercontent.com/StevenBlack/hosts/master/alternates/fakenews/hosts
33 clientGroupsBlock:
34 default:
35 - ads
36 - special
37 - iot
38 blockType: zeroIp
39 blockTTL: 1m
40 refreshPeriod: 4h
41 downloadTimeout: 4m
42 downloadAttempts: 5
43 downloadCooldown: 10s
44
45caching:
46 minTime: 5m
47 maxTime: 30m
48 maxItemsCount: 0
49 prefetching: true
50 prefetchExpires: 2h
51 prefetchThreshold: 5
52 prefetchMaxItemsCount: 0
53 cacheTimeNegative: 30m
54
55prometheus:
56 enable: true
57 path: /metrics
58
59minTlsServeVersion: 1.3
60bootstrapDns:
61 - tcp+udp:1.1.1.1
62 - https://1.1.1.1/dns-query
63 - upstream: https://dns.digitale-gesellschaft.ch/dns-query
64 ips:
65 - 185.95.218.42
66
67ports:
68 dns: 53
69 tls: 853
70 http: 4000
71
72log:
73 level: info
74 format: text
75 timestamp: true
76 privacy: false
This config is mostly based on the reference config file
I copy and pasted this reference config file to my config.yml and started commenting out most of the file.
My router is a Mikrotik hAP which also acts as my DHCP server. So the only thing I had to do is to set the IP of my server in the DHCP server confog as DNS server address:
1[bouni@router] /ip/dhcp-server/network> print
2Columns: ADDRESS, GATEWAY, DNS-SERVER
3# ADDRESS GATEWAY DNS-SERVER
4;;; defconf
50 192.168.88.0/24 192.168.88.1 192.168.88.20
Whenever a client obtains a new DHCP lease it gets this IP as DNS server and all its DNS queries are served by Blocky.
I don’t bother that Blocky does not come with an UI for its configuration, for me that even a plus. But not having nice graphs was something that needs to be solved.
On a cloud server I already run Prometheus and Grafana wanted to use that for visualisation of Blocky’s data.
To make the /metrics
endpoint of blocky available for Prometheus I set up a subdomain metrics.tld.de
which is a CNAME for my DDNS.
Next I setup my local caddy to reverse proxy the /metrics
endpoint:
1
2*.tld.de, tld.de {
3
4 tls {
5 dns hetzner {env.HETZNER_AUTH_API_TOKEN}
6 }
7
8 @metrics host metrics.tld.de
9 handle @metrics {
10 basicauth * {
11 prometheus $2a$14$Zkx19XLiW6VYouLHR5NmfOFU0z2GTNmpkT/5qqR7hx4IjWJPDhjvG
12 }
13 reverse_proxy blocky:4000
14 }
15}
As you can see I configured HTTP basic auth so that not everybody can query the data. In my Prometheus scrape config I set this up as a target using the basic auth credentials:
1scrape_configs:
2 - job_name: 'blocky'
3 scrape_interval: 60s
4 static_configs:
5 - targets: ['metrics.tld.de']
6 basic_auth:
7 username: 'prometheus'
8 password: 'hiccup'
Blocky provides a ready to use dashboard for Grafana but that wants an API endpoint. I couldn’t figure out how to set this up properly as my Prometheus instance is not on the same network as my Blocky instance, so I edited that out and made my own version
All in all I’m very happy with Blocky. It was such a smooth experiance compared to Pi-hole that I can only recommend to switch to Blocky 😎