Pi-hole Extended - Part 1

The Pi-hole project is fantastic. It lets you easily set up an ad blocker on your home network to reduce both intrusive tracking and data usage. With people using home internet connections all day, this is more important than ever.

However, it does suffer from some limitations. To fix these problems I have mine set up as a WiFi repeater / range extender. This improves WiFi coverage, allows switching between the unfiltered / filtered connections and forces all traffic through the filter from devices that try to evade it.

I’ve named this project the Chambord1 Pi-hole. You can skip ahead for the guide on how to make your own but if you want a more detailed pitch then read on.

Rationale

Advertisements aren’t evil in principle but digital ads are the visible tip of a vast surveillance-machine-shaped iceberg2. The main reason that I run a network-wide ad blocker (and other measures3) isn’t actually to block ads. The primary purpose is to preserve privacy by preventing much of the tracking and profiling that is constantly performed on you.

Another first-class reason is to boost our internet connection performance by reducing unnecessary bits being needlessly transferred. All these ads and snooping require electricity to serve, transfer and run, and the generation of this energy by burning fossil fuels is impacting our ability to survive on our planet4.

It’s also a massive waste of human potential. Imagine if all these ML and AI experts were using their skills for virtuous projects rather than selling out to technology advertising companies. Analysing every swipe, scroll and audio snippet to see if you have a weakness for cookie dough ice cream when they could be aiding the transition to a sustainable future, and thus ensuring our continued prosperity for many years to come, but I digress.

Advantages

A WiFi repeater is useful on its own for extending the range of your wireless network beyond the reach of your router. Blocking ads and tracking is a nice extra benefit and installing this filter adds much of the software needed for the repeater.

We’ve been running this setup for most of the year with hardly any issues, apart from occasionally having to reset the WiFi that it connects to, as you would anyway. Between a quarter and half of all connections attempted are blocked on any day, with no noticeable loss of functionality.

It’s informative to see the statistics on the web interface of which vendors’ devices are the most chatty and with what companies’ services. This gives you a great insight into what your ISP and government get to see (if you don’t use protection).

Previously, Pi-hole wasn’t quite mature enough for my particular use case, so I rolled my own with a custom DNS and web server. However, it’s much better now, apart from the following niggles.

Limitations

There are three main issues that I wanted to resolve with this project:

  • Improve the client configuration experience
    • Ideally to be as ‘plug-and-play’ as possible
  • Force all connections through the filter
    • Even if devices are designed to be user-hostile
  • Make it easy to temporarily disable the filter
    • Crucially, on a per device basis

Pi-hole is great and very easy to install but the challenging bit can be setting the DNS server address on the clients. This can be especially difficult on an untrusted WiFi network, or with ISP hardware (or a portable hotspot) that doesn’t allow changing these settings. Even if possible, the instructions to do this are never the same, and so it makes it difficult for non-technical people.

I wanted to be able to give a configured Raspberry Pi to anyone and just have them connect it to their router. Either with an Ethernet cable or preferably with WiFi (where the credentials would be pre-set) so they just need to plug it in to power.

The second problem is you can’t force clients to use the DNS, some may ignore the DHCP instructions, even if they use it for an IP address. This bad behaviour is increasingly prevalent from devices made by Google and Amazon. There are further complications around DoH and DoT, but we can cover those later.

The third main issue is that it is hard to temporarily disable the filter for a single client. This may need to be done if the filter breaks some functionality, but I’ve never had to do this. You can only disable Pi-hole globally for the whole network (although this can be time limited) and this also removes the filter from devices that don’t need it disabled.

Extras

There are further features that this project enables. These include securing the upstream internet connection from snooping and meddling (either just DNS or fully with a VPN), and allowing remote access (to enjoy a filtered experience or bypass geographic restrictions) when on the go.

It also helps if you are using a 4G portable hotspot, which provides a faster upload speed than coax cable or even twisted-pair (great for video calls and remote access). Not only will it improve the range of the built-in antenna but it will also allow you to set the DNS and prevent devices from thinking they are on a metered connection when they aren’t.

There is a non-standard data limit flag that Google shoehorned into DHCP5, which a lot of software has jumped on (e.g. Android and Ubuntu). On many hotspots you can’t change the DNS settings or turn this “feature” off and it will cause client devices to not download important updates, among other things.

Finally, as we will be using NAT to merge multiple connections, this puts less strain on your router and it should crash less often. It also provides an extra firewall for protection from untrusted ISP hardware or networks.

Project Chambord

My setup uses a Raspberry Pi 3 to connect to the raw WiFi. A wireless access point is then connected over a wired Ethernet connection. This provides better signal coverage and you can plug wired devices in too.

It’s possible to use the on-board wireless for both the internet connection and as an access point but there are hardware limitations. You would need to use the same frequency and channel, limiting throughput. In my configuration I have the different networks running on 2.4 and 5GHz to avoid interference.

The hardware is connected as follows:

📶 Raw WiFi -> Pi -> Ethernet -> Switch -> Ethernet -> WiFi Access Point 📡

It should be simple to adapt this to your own needs, for example reversing the wired and wireless connections or sharing the WiFi interface.

Parts

You will need the following bill of materials:

  • A Raspberry Pi
    • I used a 3A+ as I already had one
      • USB 3.0 Gigabit Ethernet adaptor
    • 3B+ if you want a native wired connection
    • Zero is underpowered for our purposes (ok for a pure Pi-hole)
    • 4 is overkill for this so don’t buy one especially
  • USB power supply
  • Micro SD card
  • Pi case (optional)
  • Gigabit Ethernet switch (optional)
  • Wireless access point
  • Cat 5e Ethernet cable(s)

Method

Once you have the required parts then follow this how-to guide to get up and running. The steps assume you’re using Linux but won’t differ much for other platforms.

Fetch

Download the latest Raspbian Buster Lite minimal image. The most recent version is currently February 2020.

Next, validate that your SHA-256 checksum matches the one on the web page:

sha256sum Downloads/2020-02-13-raspbian-buster-lite.zip
12ae6e17bf95b6ba83beca61e7394e7411b45eba7e6a520f434b0748ea7370e8  Downloads/2020-02-13-raspbian-buster-lite.zip

Flash6

Burn the image to the SD card. I used Balena Etcher.

Headless

Set up the image for immediate headless use by creating files on the FAT boot partition.

In a Linux terminal change to the boot SD card partition e.g. cd /media/james/boot and create the extensionless ‘ssh’ file with touch ssh.

Next set up the WiFi by creating the config file. You could do this within rootfs mounted on Linux, but creating the file within boot works on other platforms too: nano wpa_supplicant.conf

Add the following contents:

ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
country=GB

network={
 ssid="<Name of your WiFi>"
 psk="<Password for your WiFi>"
}

Change GB to the country code of your location and fill in the network name and password. Save the file with Ctrl+x, y, enter.

Close the terminal, eject the partitions, remove the SD card, pop it in the Pi and power it up.

Initial Setup

If all goes well you should be able to SSH into the Pi after a few minutes with ssh pi@raspberrypi.local. The first time you will need to answer yes to the prompt.

If the local hostname doesn’t work then you will need to find the IP address. Find your address with hostname -I and run an nmap ping scan for the subnet with the last octet set to 0 e.g. nmap -sn 192.168.0.0/24.

The first thing to do is to change the password for the pi user to something long, random and secure with passwd. Don’t skip this step!

You can also change the device name to something more descriptive if you like. The easiest way is to use the raspberry pi config tool.

Update Raspbian

Next, update Raspbian with sudo apt update then sudo apt full-upgrade. Confirm with y, quit the changelogs with q, wait for the install to finish then restart with sudo reboot.

Install Pi-hole

Wait for the Pi to finish booting then SSH in again to install Pi-hole. Download the script with wget -O basic-install.sh https://install.pi-hole.net and optionally validate the checksum against another copy, such as this one:

sha256sum basic-install.sh
0ac56c60c752f318a51cd1b076bbac8645a313d96a6c752821e5231d5abbdd37  basic-install.sh

You can inspect the script but it is quite long. Next run the installer with sudo bash basic-install.sh and follow the prompts. You will mainly want the default values but tweak it to your needs. For example, this setup would be running on eth0 with a static address on a different subnet (e.g. 192.168.0.1/24) and no gateway (blank). A random password is generated and shown at the end of the install, and also on the command line after exiting.

Connect to the web interface and enable DHCP for eth0 (settings page / DHCP tab) then save the changes. You can check the results of your changes in the dnsmasq settings files over SSH with cat /etc/dnsmasq.d/01-pihole.conf and cat /etc/dnsmasq.d/02-pihole-dhcp.conf.

Restart again with sudo reboot or via the web interface.

Configure NAT

We now have a plain Pi-hole but we still need to turn the Pi into a router. We don’t want to simply bridge the two network interfaces, for reasons that will become clear later.

First check the current IP tables rules with sudo iptables -L -t nat then edit the config file with sudo nano /etc/sysctl.conf. Uncomment the net.ipv4.ip_forward=1 line (remove the #) then save the file with Ctrl+x, y, enter.

Next add the routing rule with sudo iptables -t nat -A POSTROUTING -o wlan0 -j MASQUERADE. Note this is wlan0 (the internet interface) in our case but you may want eth0. Use ifconfig to find the interface names.

Save the rule with sudo sh -c "iptables-save > /etc/iptables.ipv4.nat" and edit the startup config with sudo nano /etc/rc.local, adding the line iptables-restore < /etc/iptables.ipv4.nat above exit 0. Save the file with Ctrl+x, y, enter.

Restart again with sudo reboot and wait a couple of minutes.

Testing Time

Jack in to the network port with your WiFi off and check that you have internet access. You should be able to access the web interface at pi.hole and SSH in with ssh pi@pi.hole

If you don’t want to reconfigure all of your devices then you can edit the old WiFi to have a new name (and password) then use them in the Pi config file with sudo nano /etc/wpa_supplicant/wpa_supplicant.conf. You can then configure your wireless access point to use the old WiFi name and password, plug this into the Ethernet and it should all just work. If you need to disable the filter on a device for a bit then simply switch to the old WiFi (with the new name).

If you have previously set any clients up with manual network configurations then you should change them to use DHCP.

Next Time

You should now have a home-made router and filtering DNS server. Nice work.

In future posts I’ll cover some advanced topics such as updating, preventing DNS over HTTPS, extra filter lists, securing upstream requests and forcing all DNS traffic (e.g. Kindles and Chromecasts) through your filter.


  1. After the raspberry-flavoured Chambord Liqueur (header image cropped from Façade Nord-Ouest du Château de Chambord by Benh LIEU SONG CC BY-SA 3.0) ↩
  2. If you are reading this from the future, then icebergs were large blocks of freshwater ice that used to calve off glaciers and ice shelves into the sea ↩
  3. E.g. a trusted web browser (e.g. Firefox) on a respectful OS (e.g. Linux) with a few select add-ons (e.g. uBlock Origin, Privacy Badger and HTTPS Everywhere) ↩
  4. How Climate-Friendly Is Your Cloud Provider? and Masanet, Eric and Shehabi, Arman and Lei, Nuoa and Smith, Sarah and Koomey, Jonathan “Recalibrating global data center energy-use estimates” (American Association for the Advancement of Science, 10.1126/science.aba3758, 2020) ↩
  5. DHCP option 43 (vendor specific options) ANDROID_METERED ↩
  6. A ah! ↩

This blog is treeware! If you found it useful then please plant a tree.
Donate a treeDonate a tree🌳🌳