Pi-Hole Setup on Raspberry Pi 3
In this post, I will cover how to install a Raspbian system from scratch, along with the setup of pi-hole, to block internet trackers on the network level.
Pi-Hole serves both as a DNS forwarder and cache, and should be configured as the DNS server for your network. This guarantees that all users of your network will be automatically shielded from internet tracking. You also might notice a reduction in bandwidth usage, since assets from ad networks and trackers are not loaded because of the ‘blackholing’. This process is explained further down in this post.
In order to follow this tutorial, there are a few hardware requirements:
- Raspberri Pi, either version 2 or 3 should work.
- HDMI cable
- Monitor with a HDMI port
- USB keyboard
- SD Card
- Ethernet cable, to connect the Pi to the router
If you have Raspbian already setup, you can skip to the section ‘Pi-hole and DNS Forwarding’. Make sure, however, that your Raspbian has a static IP address setup for it.
Insert the SD card in the computer, and check for its name using the following command:
Which shows an output like the following:
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT sda 8:0 0 931,5G 0 disk ├─sda1 8:1 0 512M 0 part /boot/efi ├─sda2 8:2 0 1G 0 part /boot └─sda3 8:3 0 930G 0 part ├─fedora-root 253:0 0 50G 0 lvm / └─fedora-home 253:1 0 880G 0 lvm /home mmcblk0 179:0 0 14,9G 0 disk ├─mmcblk0p1 179:1 0 1,6G 0 part ├─mmcblk0p2 179:2 0 1K 0 part ├─mmcblk0p5 179:5 0 32M 0 part ├─mmcblk0p6 179:6 0 69M 0 part └─mmcblk0p7 179:7 0 13,2G 0 part
In this case,
sda is the hard drive from the computer, and
mmcblk0 is the SD card. Therefore,
mmcblk0 is the device we must use to flash the SD card. Beware, that (wrongly) writing to the hard drive would corrupt your filesystem!
Download the Raspbian Lite image from the Raspbian website. Then, we extract the image and write its contents to the SD card using the
dd Linux utility, as follows:
unzip 2018-04-18-raspbian-stretch-lite.zip && \ sudo dd bs=4M conv=fsync status=progress \ if=2018-04-18-raspbian-stretch-lite.img \ of=/dev/mmcblk0
In Unix and Linux operating systems, everything is represented as a file, including disks and SD cards.
dd takes the content of a file specified by
if and writes its contents to the file
of. In our case, we are taking an input file (
2018-04-18-raspbian-stretch-lite.img) and writing it to a special file (
/dev/mmcblk0), which represents the SD card.
The parameters passed to dd have the following meaning:
- if: stands for input file, the file from which the content will be read.
- of: stands for output file, the file to which the contents of if will be written.
- bs: stands for block size, how many bytes are read from the input and written to the output file at once.
- conv: stands for conversion, it applies comma separated operations on top of the input file, before writing it to the output file.
fsyncensures that the kernel writes the data to the output file as well as metadata to the physical device before finishing. This is required, because the kernel might not promptly write the data to the SD card, which would leave the SD card corrupt if we took it off the computer before all the data was written to it.
- status: amount of information printed to
progressshows periodic transfer statistics, which allows one to track the speed and amount of data copied to the SD card.
Depending on your disk and SD card performance, this might take a while as the image is around 1.7 GB large. After the data is written to the SD card, take it off the computer and put it in to the Raspberry Pi.
Connect the Pi to an energy source, the keyboard and the monitor (using the HDMI cable). It should boot to a screen like the following:
Log in using
pi as the username and
raspberry as the password.
Change the default password for
You will have to provide the current password (
raspberry), and type the new password twice (once more, for verification purposes).
In the next section, a static IP address and SSH are setup, so there will be no more need for the monitor and keyboard.
Static IP Address
Add the following to the end of the file:
interface eth0 static ip_address=192.168.0.2/24 static routers=192.168.0.1 static domain_name_servers=18.104.22.168
In your setup, replace the:
- IP address (
ip_address) with the local IP address of the Pi in your network, in this case
192.168.0.2with a network mask of 24 bits, i.e.
routerswith the IP address of your router, in this case it is
domain_name_serverswith the IP address of the DNS resolver for your network. If you don't know what is the IP address of your DNS resolver, you can use either
22.214.171.124(Google DNS) or
systemctl enable ssh.service systemctl start ssh.service
After configuring the static IP adress and SSH, reboot the Pi:
You can now take off the keyboard, and HDMI cable from the Pi. After a couple of seconds, log in to the Pi using the SSH on your machine:
Note that we are using the user
pi with the static IP address configured in a previous step. Replace the IP address with the one you have configured.
Pi-hole and DNS Forwarding
Pi-Hole works both as a cache and DNS forwarder. This means that:
- It takes a domain name query such as
- If the domain is in one its blocklists, then the IP address returned is
0.0.0.0, which is not routable, i.e. it cannot be accessed over the internet. Therefore, its renders blocked domains unaccessible. Otherwise, it goes to step 3.
- If it doesn't know the IP address of this domain locally (i.e. the address is not in cache), it queries an upstream DNS server (e.g. Google DNS) to obtain the IP address
- The IP address is saved locally in the cache, and the address is returned to the user.
Update the system packages:
apt-get update && apt-get upgrade -y
Install pi-hole using the following command:
curl -sSL https://install.pi-hole.net | bash
Follow the installation process, selecting your upstream DNS providers (e.g. Google DNS or Cloud9). I would also recommend installing the web interface, this option will be shown in the pi-hole installer. Your output should be something like the this.
Change the administration password of Pi-Hole:
pihole -a -p
In order to secure our Pi, we will install ufw (short for ‘Uncomplicated Firewall’), which is simpler to configure than iptables.
First, install ufw:
sudo apt-get install -y ufw
Allow the ports of the services provided by pi-hole:
# SSH sudo ufw allow 22/tcp # DNS sudo ufw allow 53/udp # DHCP server (optional), only if pi-hole will be your DHCP server sudo ufw allow 67/udp sudo ufw allow 68/udp # pi-hole web interface sudo ufw allow 80/tcp
and enable the firewall:
sudo ufw enable sudo ufw status verbose
Access the web interface on
http://192.168.0.2/admin, and use the password you have configured earlier on. It should look like the following:
Make sure all the hosts on your network use the IP address of the pi-hole as their only DNS server.
As a bonus, one can also harden the SSH server, if the Pi is accessible to the public internet, and restrict the SSH port only to local addresses is also a good security measure.
If you reached this point, please let me know if you have any thoughts or comments on this post, the details for contact can be found in the About page.