Breder.org

Setting up Pi-hole Is Plenty of Fun

Pi-hole is an open-source project which implements network-wide ad-blocking through a Domain Name Server (DNS) sinkhole.

To understand how it works, first we must understand how the act of visiting a website usually works:

1. Type in breder.org/some-page in the address bar

2. Request IP address of breder.org to the configured DNS servers

3. Request the webpage /some-page to the IP address returned by (2)

By default, DNS servers are set up by your Internet Service Provider (ISP). Other common options are Google's DNS service (8.8.8.8) and Cloudfare's DNS service (1.1.1.1).

All that a DNS server does is to convert domain names (e.g. “breder.org”) into IP addresses (e.g. 192.168.0.1), since IP addresses -- while impractical for us to remember -- are the actual identifiers for point-to-point communication between computers on the Internet.

Pi-hole acts as a DNS server -- so it intercepts all domain name requests at step (2) outlined above. If the domain is a known ad-serving domain -- according to the crowdsourced ad domains list -- it refuses to serve the IP address, thus the ads server is unreachable. Otherwise, it forwards the DNS request to some traditional DNS resolver.

The most popular way to set up the Pi-hole is by using an always-on Raspberry Pi connected at your home network (thus the “Pi” in the name of the project).

Devices on the network are set up so the DNS resolver is the Pi, which performs the domain filtering of ad-serving domains, only forwarding non-ads requests to the outer internet.

The Pi-hole also provides a nice web interface with reports of all blocked or allowed domain requests.

The application can run from a Docker (or Podman) container, which is super convenient for deploying it without interference with existing userspace libraries and distro of choice.

I'm using the following script derived from their examples:

#!/bin/bash

# https://github.com/pi-hole/docker-pi-hole/blob/master/README.md

PIHOLE_BASE="${PIHOLE_BASE:-$(pwd)}"
[[ -d "$PIHOLE_BASE" ]] || mkdir -p "$PIHOLE_BASE" || { echo "Couldn't create storage directory: $PIHOLE_BASE"; exit 1; }

sudo podman run -d \
    --name pihole \
    -p 53:53/tcp -p 53:53/udp \
    -p 80:80 \
    -e TZ="America/Sao_Paulo" \
    -e WEBPASSWORD="use some password here" \
    -e DNSMASQ_LISTENING=all \
    -v "${PIHOLE_BASE}/etc-pihole:/etc/pihole" \
    -v "${PIHOLE_BASE}/etc-dnsmasq.d:/etc/dnsmasq.d" \
    --dns=127.0.0.1 --dns=1.1.1.1 \
    --restart=unless-stopped \
    --hostname pi.hole \
    -e VIRTUAL_HOST="pi.hole" \
    -e PROXY_LOCATION="pi.hole" \
    -e FTLCONF_LOCAL_IPV4="192.168.0.2" \
    --replace \
    pihole/pihole:latest

The WEBPASSWORD sets the password for the web interface.

DNSMASQ_LISTENING=all is safe only if the Pi is not reachable through the wider Internet (e.g. with Router Port Forwarding). In our setup, the Pi is local to the home network.

The volumes help persist state and configuration when the container is stopped or upgraded.

Finally FTLCONF_LOCAL_IPV4 sets the listening address of the administration interface.

The pre-built official Docker image is available at: https://hub.docker.com/r/pihole/pihole.