Pi-hole on Raspberry Pi with IPv6
Arif Amirani
Posted on February 23, 2021
I've had a Raspberry Pi 4B sitting in my cabinet for a few months now. I dusted it off and realized that the SD card was busted. Got a replacement 64GB U3 A2 card and got it up and running with Ubuntu server. The primary intended use was to run docker with DB containers that I use for my side projects such as Postgres/MySQL/MongoDB.
My current home network consists of several routers for WiFi reachability. I try to ensure 5Ghz coverage to all my devices. Due to the concrete walls a single router does not suffice, hence a home made mesh.
The earlier ISP was a IPv4 only provider. Easy to setup. Worked out of the box. To safeguard other users of the network, I use a privacy sensitive DNS provider, Adguard. The issue with Adguard DNS was no geo proximity. It caused large ping times, as the closest CDN was never picked.
When I moved to my new ISP which supports IPv6, I decided to also deploy Pi-hole alongwith my docker containers.
Installing Pi-hole
Pi-hole is quite easy to deploy, especially with the auto install script.
curl -sSL https://install.pi-hole.net | bash
Once I followed the steps I got Pi-hole running out of the box. As suggested you have to change your router settings to send the IP address of your Pi-hole server as your local DNS. Done and done.
The Problem
Ads still show!
To ensure that I wasn't fudging up DHCP/DNS discovery I used scutil:
scutil --dns
resolver #1
search domain[0] : lan
nameserver[0] : 2405:201:xxxx:xxxx:xxx:xxxx:4209:2091
nameserver[1] : fe80::a204:60ff:fe43:3005%en0
nameserver[2] : 192.168.2.50
if_index : 6 (en0)
flags : Scoped, Request A records, Request AAAA records
reach : 0x00020002 (Reachable,Directly Reachable Address)
IPv4 looked good. 192.168.2.50
is the IP of my pi-hole server.
However, the IPv6 didn't belong to pi-hole. The default ISP setting was to use stateless IPv6 config and DNS was being advertised by the router. It was using my upstream DNS (ISP) server.
To fix this, I made the following changes:
IPv6 on pi-hole
- Get your Ipv6 address for pi-hole
ip addr show
- Enable IPv6 support on pi-hole
- Set the
IPV6_ADDRESS
add/etc/pihole/setupVars.conf
This should've already been done during the installation of pi-hole but if isn't, you can manually set it up using the address above
IPV4_ADDRESS=192.168.2.50/24
IPV6_ADDRESS=2405:xxx:xxxx:xxxx::50/64
A neat trick I learnt while assigning static IPv6 addresses is to the use the same suffix as IPv4. Easy to remember and deal with.
Restart FTL:
systemctl restart pihole-FTL
- Enable AAAA query analysis for Pi-hole
Pi-hole by default will only analyse A
queries, so we need to add support for AAAA
.
DBINTERVAL=60
MAXDBDAYS=7
AAAA_QUERY_ANALYSIS=yes
PRIVACYLEVEL=0
I also added a throttling parameters to not wear out the SD Card.
- Refresh Pi-hole
Reboot the server. Fetch gravity lists again
pihole -g
- Stateful DHCPv6
My attempts at trying to get DHCP v4 and v6 from pi-hole failed. This is probably due to wrong assumptions of SLAAC + RA.
- Debug Pi-hole
At the end I made sure everything is kosher by running diagnosis on Pi-hole
pihole -d
Setting up Unbound
I do not like using any of the open DNS servers. They have their place and provide a lot of value but it's not for me. I prefer a combo of ad-block and recursive DNS. Unbound works perfectly with Pi-hole. Setting it up is again very simple.
apt install unbound
Update the unbound config to support Pi-hole
/etc/unbound/unbound.conf.d/pi-hole.conf
Make a note of the port, the default port 53
is used by Pi-hole and must be changed.
server:
interface: 0.0.0.0
interface: ::0
port: 5335
access-control: 192.168.2.0/24 allow
access-control: 127.0.0.0 allow
access-control: 2001:db8:dead:beef::/48 allow
# unbound optimisation
num-threads: 4
msg-cache-slabs: 16
rrset-cache-slabs: 16
infra-cache-slabs: 16
key-cache-slabs: 16
outgoing-range: 206
so-rcvbuf: 4m
so-sndbuf: 4m
so-reuseport: yes
rrset-cache-size: 100m
msg-cache-size: 50m
# unbound security
do-ip4: yes
do-ip6: yes
do-udp: yes
do-tcp: yes
cache-max-ttl: 86400
cache-min-ttl: 3600
hide-identity: yes
hide-version: yes
minimal-responses: yes
prefetch: yes
use-caps-for-id: yes
verbosity: 1
harden-glue: yes
harden-dnssec-stripped: yes
# download from ftp://ftp.internic.net/domain/named.cache
# root-hints: "/var/lib/unbound/root.hints"
# Ensure privacy of local IP ranges
private-domain: "lan"
private-address: 192.168.0.0/16
private-address: 169.254.0.0/16
private-address: 172.16.0.0/12
# private-address: 10.0.0.0/8
private-address: fd00::/8
private-address: fe80::/10
Tweak it as per your needs and restart Unbound
systemctl restart unbound
Check unbound
Will pass:
root@pi-desktop:~# dig sigok.verteiltesysteme.net @127.0.0.1 -p 5335
; <<>> DiG 9.16.6-Ubuntu <<>> sigok.verteiltesysteme.net @127.0.0.1 -p 5335
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 48863
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;sigok.verteiltesysteme.net. IN A
;; ANSWER SECTION:
sigok.verteiltesysteme.net. 3600 IN A 134.91.78.139
;; Query time: 499 msec
;; SERVER: 127.0.0.1#5335(127.0.0.1)
;; WHEN: Tue Feb 23 08:53:17 IST 2021
;; MSG SIZE rcvd: 71
Will fail:
root@pi-desktop:~# dig sigfail.verteiltesysteme.net @127.0.0.1 -p 5335
; <<>> DiG 9.16.6-Ubuntu <<>> sigfail.verteiltesysteme.net @127.0.0.1 -p 5335
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: SERVFAIL, id: 56203
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;sigfail.verteiltesysteme.net. IN A
;; Query time: 1147 msec
;; SERVER: 127.0.0.1#5335(127.0.0.1)
;; WHEN: Tue Feb 23 08:53:43 IST 2021
;; MSG SIZE rcvd: 57
DHCP Confirmation
At least for IPv4, you can run the debug tool to make sure DHCP is correct.
root@pi-desktop:~# pihole-FTL dhcp-discover
Scanning all your interfaces for DHCP servers
Timeout: 10 seconds
* Received 301 bytes from eth0:192.168.2.1
Offered IP address: 192.168.2.113
Server IP address: 192.168.2.1
Relay-agent IP address: N/A
BOOTP server: (empty)
BOOTP file: (empty)
DHCP options:
Message type: DHCPOFFER (2)
server-identifier: 192.168.2.1
lease-time: 3600 ( 1h )
renewal-time: 1800 ( 30m )
rebinding-time: 3150 ( 52m 30s )
netmask: 255.255.255.0
broadcast: 192.168.2.255
router: 192.168.2.1
dns-server: 192.168.2.50
dns-server: 192.168.2.50
domain-name: "lan"
--- end of options ---
Switching Pi-hole to use unbound
Disable all Upstream DNS servers and add custom DNS that you setup for Unbound.
Use the loopback addresses for Unbound:
IPv4 - 127.0.0.1#5335
IPv6 - ::1#5335
That should be it! Hope you enjoyed reading the article.
Posted on February 23, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.