Introduction
I have been working on a RaspberryPi home server project for quite some time. The project is a collection of applications to run on RaspberryPi and all applications are deployable with docker-compose
files and ansible automation. One of the applications I was configuring is Pi-hole, a network-wide ad-blocker.
I decided to use Pi-hole as also DHCP server for my LAN. When I look into docs, it says it has to be run as network_mode: host
, because it allows Pi-hole to listen to DHCP broadcast packets. If the Pi-hole is deployed in bridge mode, there is a Linux bridge(Think of it as a router for a second!) which won’t allow broadcast packets.
But I want to run the Pi-hole container isolated and non-root, besides I’m using Nginx proxy for all of my apps(Check wiki pages). I kept scrolling docs, found this which I can use DHCP relay.
A DHCP relay listens to DHCP broadcast packets and unicasts to the DHCP server which is in another network(We will see how it works below section)
With help of DerFetzer’s I have created a simple project where you can deploy Pi-hole with DHCP relay.
$ git clone https://github.com/veerendra2/pihole-dhcp-relay-docker
$ cd pihole-DHCP-relay-docker
$ tree .
.
βββ dhcp-helper
β βββ Dockerfile
βββ dnsmasq.d
β βββ 07-dhcp-options.conf
β βββ 99-temp.conf
βββ docker-compose.yml
βββ LICENSE
βββ pihole
β βββ custom.list
βββ README.md
3 directories, 7 files
How it works
Here is the simple network diagram that you can see the definition indocker-compose.yml
βββββββββββββββββ
β dhcp-relay-netβ <-------- Linux bridge
βββ¬ββββββββββββ¬ββ
β βeth1
ββββββ΄βββ βββββ΄ββββ
βDHCP β βPiHole β
βRelay β β β
βββββ¬ββββ βββββ¬ββββ
β βeth0
β ββββββ΄ββββββββ
β β front-tier β <-- Linux bridge
β ββββββ¬ββββββββ
βββββββ΄βββββββββββββ΄ββββββββ
β Host Network β
| (RaspberryPi) |
ββββββββββββββββββββββββββββ
^ eth0 (192.168.0.120)
|
|
v
LAN
As you can see above the Pi-hole is deployed in bridge mode, there is a Linux bridge(front-tier
) between the host network stack and the Pi-hole container. So, any broadcasts won’t allow through front-tier
bridge(router*). So, I solve the problem by adding one more container DHCP Relay
run as network_mode: host
in which the container is attached to the host network stack as you can see there is no Linux bridge which means, DHCP Relay
container listens all DHCP broadcast and unicast to dhcp-relay-net
Linux bridge and Pi-hole also connected to it. That’s how devices in LAN get the IP from bridged Pi-hole
Further Configurations
DHCP Options Config
After I deploy the above setup, my phone gets an IP address but not the Internet. I wasn’t sure what was going on, maybe it is that DHCP is not providing the DNS address which is my RaspberryPI external LAN IP?
I installed Wireshark and capture the DHCP packets to see what it contains
Bing go!, it is 172.31.0.10
the IP I specified in DHCP relay
. So, after googling, I found
$ cat dnsmasq.d/07-dhcp-options.conf
dhcp-option=option:dns-server,192.168.0.120
Then, my phone gets the correct DNS address and accesses the Internet.
Suppress dnsmasq warnings
I noticed, in the Pi-hole dashboard, dnsmasq is throwing warnings
That is due to the IP range I set in the DHCP pool(.env) doesn’t cover the network 172.31.0.0/16
which Pi-hole
directly connect with eth1
interface(Above diagram). In this case, there are 2 options to get rid of these warnings.
Disable warnings
Like in the below screenshots, but you might miss any other important warnings
No DHCP Interface
Set no-dhcp-interfaces like below
$ cat dnsmasq.d/99-temp.conf
no-dhcp-interface=eth0,eth1
Conclusion
This simple trick allows me to run Pi-host in bridge mode and run behind the Nginx proxy. Hope you find a useful piece of information