I’ve been wanting to block ads on a dns level on my home network for awhile lately.
Today wasn’t going to be a productive day, so I said I may as well make it productive.
Setting up a pi hole is the obvious choice, but I couldn’t find any SD cards after moving a few months ago. I did want to to setup on a dedicated pi to have some redundancy in case my home server was down, but I decided to be a grown up about and set up a docker image to do it.
Fortunately a docker image already exists for this project. It does want to take over ports 53, 80, but I’m already using them for a named daemon for openvpn and nginx.
Instead I decided to add a vip to the docker host and have it used 53 and 80 for the pi hole bound on that address instead.
It’s quite easy.
ip addr add 10.2.2.250/24
And then a systemd unit to to make it persistent across reboots.
view /etc/systemd/system/eno1-vip.service [Unit] Description=Add vip to eno1 after dhcp Requires=dhcpcd@eno1.service [Service] ExecStart=/usr/bin/ip addr add 10.2.2.250/24 dev eno1 [Install] WantedBy=default.target
This looks slightly at odds with itself, but I still prefer to use DHCP for the primary IP on the box.
The docker image is built with:
#!/bin/bash IMAGE='diginc/pi-hole:alpine' NIC='eno1' IP="10.2.2.250" #opennicproject.org public DNS DNS1="5.9.49.12" DNS2="5.135.183.146" #Bind ports to the vip docker run -p 10.2.2.250:53:53/tcp -p 10.2.2.250:53:53/udp -p 10.2.2.250:80:80 \ --cap-add=NET_ADMIN \ -e ServerIP="$IP" \ -e DNS1=$DNS1 -e DNS2=$DNS2 \ --name pihole \ -d "$IMAGE"
This will result in the following iptables rules:
# iptables -t nat --list .... Chain DOCKER (2 references) target prot opt source destination RETURN all -- anywhere anywhere DNAT tcp -- anywhere Farnsworth tcp dpt:http to:172.17.0.2:80 DNAT tcp -- anywhere Farnsworth tcp dpt:domain to:172.17.0.2:53 DNAT udp -- anywhere Farnsworth udp dpt:domain to:172.17.0.2:53
and the systemd unit for the pi hole docker image will look like:
view /etc/systemd/system/pihole.service [Unit] Description=pihole ad blocker Requires=docker.service After=eno1-vip.service [Service] Restart=always ExecStart=/usr/bin/docker start -a pihole ExecStop=/usr/bin/docker stop -t 2 pihole [Install] WantedBy=default.target
I had issue getting the http working on my openwrt setup. It did transpire to be a safety mechanism within dnsmasq, it won’t return a DNS record for an address that is the DNS server. This is due to rebind_protection.
Edit /etc/config/dhcp and set:
config dnsmasq
option rebind_protection '0'
and restart dnsmasq. You’ll know this will have worked as you should be able to
dig +short pi.hole 10.2.2.250
In short it wasn’t too bad. I need to explore further how to incorporate a local DNS server, but I enjoyed putting this together and I may use docker more with this vip setup.
