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.

πŸ‘‰ https://github.com/veerendra2/pihole-dhcp-relay-docker

$ 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

wireshark-dhcp-capture.png

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

pihole-warinings.png

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

pihole-warinings-gone.png

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