PiHole setup
Server setup | |
← Previous | Next → |
Backups | Discourse |
I use PiHole as a layer in my DNS setup. PiHole filters DNS requests and drop requests to known advertising and tracking sites. The idea is that you don't leak information to them, and adverts don't get served on web sites you visit (making them faster to load).
Inserting PiHole into the DNS query chain requires some fiddling.
To keep things simple, I use the an instance of PiHole in a Docker container. That minimises installation worries, and helps keep PiHole separated from my existing services (DNS and Web servers). It does mean that PiHole needs its own IP numbers, and its own hostnames.
The DNS query chain looks like this:
+--------+ +--------+ +--------+ +----------+ +------------+ | Client | ---> | Router | ---> | PiHole | ---> | Bind DNS | ---> | Upstream | | device | +--------+ +--------+ +----------+ | DNS server | +--------+ +------------+
I have two PiHole instances running; one on my server machine, one on my desktop machine. This gives redundancy when one of them falls over. I considered using Nebula Sync to exchange configuration settings between the two PiHoles, but decided that was unnecessary in my case.
Additional IP numbers
PiHole needs its own IP numbers (IPv4 and IPv6) to listen on. These are set up in the Netplan config files, /etc/netplan/01-network-manager-all.yaml
:
On the both machine, add the new IPs for the PiHole:
# Let NetworkManager manage all devices on this system network: version: 2 renderer: NetworkManager ethernets: eno1: dhcp4: no dhcp6: no addresses: [10.191.106.252/24, ... 10.191.106.242/24, # IPs for Pi-hole container 2a02:390:62aa::8100:53/64 ]
(Use different IPs for the two machines)
Apply the changes on both machines.
root@desktop:~# netplan apply
Hostnames
Now we have IP numbers, we give them names. On the server machine, edit the zone files /etc/bind/db.domain.tld to make reference to the PiHoles.
; Name servers ns1 IN AAAA aaaa:bbbb:cccc:dddd::53 IN A 192.168.1.252 ns2 IN AAAA aaaa:bbbb:cccc:dddd::54 IN A 192.168.1.251 pihole IN AAAA aaaa:bbbb:cccc:pppp::53 IN A 192.168.1.242 pihole2 IN AAAA aaaa:bbbb:cccc:pppp::54 IN A 192.168.1.241
Refresh DNS then check the new names are available.
root@server:~# rndc reload
user@desktop:~$ host pihole
Prevent other services listening
The PiHole container needs to connect to ports 53, 80, and 443 (DNS, HTTP, and HTTPS). The default configuration is for the existing Bind9 and Apache servers to listen to all IPs on these ports. This will conflict with PiHole, so we need to restrict Bind9 and Apache to listen to only the interfaces they actually serve.
Do this on both server and desktop machines.
Bind9 config
Edit /etc/bind/named.conf.options
// listen-on-v6 { any; }; listen-on-v6 { aaaa:bbbb:cccc:dddd::53; ::1; ::53; }; // listen-on { any; }; listen-on { 192.168.1.252; 127.0.0.1; 127.0.0.53; };
(change the IP numbers for the interfaces on the desktop machine.)
Refresh DNS.
root@server:~# rndc reload
Apache2 config
Edit /etc/apache2/ports.conf
Listen 127.0.0.1:80 Listen [::1]:80 Listen 192.168.1.252:80 Listen [aaaa:bbbb:cccc:dddd::443]:80 Listen [aaaa:bbbb:cccc:eeee::443]:80 <IfModule ssl_module> # Listen 443 Listen 127.0.0.1:443 Listen [::1]:443 Listen 192.168.1.252:443 Listen [aaaa:bbbb:cccc:dddd::443]:443 Listen [aaaa:bbbb:cccc:eeee::443]:443 # NameVirtualHost *:443 </IfModule> <IfModule mod_gnutls.c> # Listen 443 Listen 127.0.0.1:443 Listen [::1]:443 Listen 192.168.1.252:443 Listen [aaaa:bbbb:cccc:dddd::443]:443 Listen [aaaa:bbbb:cccc:eeee::443]:443 # NameVirtualHost *:443 </IfModule>
(change the IP numbers for the interfaces on the desktop machine.)
Refresh Apache2.
root@server:~# systemctl restart apache2.service
Docker configuration
Copy the PiHole docker file from the PiHole site into /etc/pi-hole/docker-compose.yml
. Make the changes shown.
services: pihole: container_name: pihole image: pihole/pihole:latest hostname: pihole # Add this networks: # Add these two lines to enable IPv6 in Docker - pihole-network ports: # Adjust these, according to your IP numbers # DNS Ports - "192.168.1.252:53:53/tcp" - "10.191.106.222:53:53/udp" - "[aaaa:bbbb:cccc:pppp::53]:53:53" # Default HTTP Port - "192.168.1.252:80:80/tcp" - "[aaaa:bbbb:cccc:pppp::53]:80:80/tcp" # Default HTTPs Port. FTL will generate a self-signed certificate - "192.168.1.252:443:443/tcp" - "[aaaa:bbbb:cccc:pppp::53]:443:443/tcp" environment: FTLCONF_webserver_api_password: 'your-password-here' # Add this stanza (at top level) to enable a network that supports IPv6 networks: pihole-network: enable_ipv6: true
Then create the container.
root@server:/etc/pi-hole# docker compose up -d
Do the same on the desktop machine.
You may need to increase the inotify limit:
root@desktop:# cat /proc/sys/fs/inotify/max_user_instances 128 root@desktop:# echo "fs.inotify.max_user_instances=500" >> /etc/sysctl.conf root@desktop:# sysctl -p root@desktop:# docker compose restart pihole
You should be able to log into the PiHole's web interface at https://pihole.domain.tld/admin/
to view what it's doing and make changes.
PiHole configuration
In the PiHole web interface, in Settings > DNS > Upstream DNS servers > Custom DNS Servers , set your local Bind9 DNS servers as the upstream servers.
192.168.1.251 192.168.1.252 aaaa:bbbb:cccc:dddd::53 aaaa:bbbb:cccc:dddd::54
Also set the Settings > DNS > Conditional forwarding section, enable "Expert" settings rather than "Basic", and allow PiHole to do reverse DNS lookups on the local network. Add these lines.
true,192.168.1.0/24,192.168.1.251,domain.tld true,aaaa:bbbb:cccc:dddd::1/64,aaaa:bbbb:cccc:dddd::53,domain.tld
Router configuration
We now need to tell the router to direct DNS queries to the PiHoles.
The details will depend on your router. I'm using a Unifi Dream Machine.
I connect to the router's web interface, go to Settings > Internet > Primary .
- Under IPv4 configuration and IPv6 configuration, I uncheck the DNS Server: Auto and add the IP numbers of the PiHoles.
(This makes the router connect to the Piholes.)
I then connect to the router's web interface, go to Settings > Networks > Select my network .
- In the IPv4 tab, under DHCP Service Management, uncheck DNS Server: Auto and add the IP numbers of the two PiHoles.
- In the IPv6 tab, uncheck DNS Server: Auto and add the IP numbers of the two PiHoles.
(This makes the DHCP clients connect directly to the PiHoles, so I can see the different clients in the PiHole logs.)