Installing & Configuring Pi‐Hole DNS with Conditional Forwarding - cfloquetprojects/homelab GitHub Wiki

Introduction:

  • The Pi-hole project was started in 2015, and has evolved into one of the most popular network-level advertisement and internet tracker blocking applications for DIY and tech enthusiasts, acting as a DNS server/sinkhole (and even DHCP server) for local clients within your network.

  • Today we will be deploying Pi-hole onto a virtualized instance of Ubuntu 22.04 LTS.

graph LR
   A[Local Network Device] <-- 53/UDP --> B{Pi-hole}
   B -- Malicious/Suspicious Query --> D(Not forwarded, but logged and rejected)
   B <--> C[Upstream Recursive DNS such as Cloudflare, OpenDNS]
   B <-- Conditionally Forwarded Internal Query --> E[Local DNS Server]

Resources:

Pre-Flight Check:

💡 If you are installing on a Raspberry Pi device, I highly recommend using the free Pi Imager software which is extremely intuitive and has Ubuntu v22.04 (as well as many other cool Linux distros you can check out).

  1. Properly networked (has a static internal IPv4 address, and local gateway defined) Ubuntu v22.04 LTS (core) virtual machine.

    1a. Preferably 2gb+ of RAM, 15-20gb storage (SSD best for performance, we will also be exporting logs to a SIEM on regular basis).

  2. Requisite software includes net-tools, curl, and optionally firewalld which I use to configure firewalls, but ufw is a native firewall for Ubuntu and works just as well, this software can be installed with the following on Ubuntu v22.04:

# sudo apt-get -y install net-tools curl firewalld

  1. The last portion of this blog includes instructions on how we can direct DNS queries according to the destination network of the target IPv4/hostname being resolved through "conditional forwarding" on the Pi-hole administration panel.

    3a. If you don't have an internal DNS server or domain controller and are using this guide strictly for guidance on how to deploy Pi-hole on Ubuntu v22.04 LTS, then feel free to ignore this (final) section..

💣 I strongly recommend taking additional steps to harden your device running Pi-hole such as changing any default account passwords, disabling remote login (via ssh) as root, and updating any out of date packages (which is our first/next step anyways).

Setting Up the System and Pi-hole User:

  • First things first, we need to make sure our host is has the latest packages & updates prior to any installations:

# sudo apt-get -y update && sudo apt-get -y upgrade

  • Additionally, while using the root user is required (via it's invocation through sudo) for the installation of Pi-hole, I will be creating a named user (called pihole for simplicities sake - separate from the root account).

💡 We will use the pihole user for accessing the system remotely (since it's best practice to disable root login within sshd_config), as well as for future projects where we enhance & augment our DNS blocking capabilities, where we can store scripts or keys within that user's profile, rather than the root account.

  • We can create a new named user using the native adduser command within Ubuntu, from which we will be prompted to set that users credentials, as well as some contextual information (name, contact, etc.) which we can leave blank/default (as shown in the screenshot below).

# adduser pihole

1

  • Next we need to add this user to the "sudoer" group, which will allow us to assume or invoke the root user via the sudo command (which is just a shortened version of 'super user do').

💡 If you're curious what the "-aG" flags are for, you can read more about it on the usermod manual page, but essentially it means we will be adding a group membership to this user.

# usermod -aG sudo pihole

Fetching & Running the Pi-hole Install Script:

  • The installation of Pi-Hole on Ubuntu is extremely simple, thanks to a very nifty shell script that we can fetch/save using curl, before using chmod to make it executable, and launching (as shown below):
$ curl -sSL https://install.pi-hole.net >> install-pihole.bash
$ chmod +x install-pihole.bash
$ sudo ./install-pihole.bash

2

💡 You can proceed with defaults, when prompted for upstream DNS server I typically opt for CloudFlare and OpenDNS, but you can choose whatever provider you want, and it shouldn't impact your success in completing this lab.

  • Once the installation completes, you should be presented with a screen similar to the one shown below, with the static IPv4 of your server, as well as the the URL that you can now use to access the administrative panel of your Pi-hole instance:

3

  • Navigate to http://<your_pi-hole_server_ip/admin using a browser of your choice to see if it loads properly for you:

4

💡 Now that we have confirmed general access/availability to the management/administration panel of our Pi-hole instance is possible, we can then take the OPTIONAL step to restrict what networks (and subsequently, devices) within our environment can access this page, reducing the chance of unauthorized access/discovery of this management panel by nosy end users or even malicious actors.

Restricting Access to Pi-hole Administration Panel using Rich FirewallD rules:

💣 This section covers the optional step of implementing "rich" rules within the firewalld utility on our Pi-hole instance, feel free to skip this section if you aren't looking to further restrict/harden access to your Pi-hole instance.

  • By invoking the root user through the sudo command, we can start the firewalld service that we installed earlier, and from there use the firewall-cmd command combined with the --list-all flag to display all current (default) rules:
$ sudo systemctl start firewalld
$ sudo systemctl enable firewalld
  • Let's use firewall-cmd to modify the local iptables rules to strictly limit connections over HTTP/HTTPS ports (80 and 443 respectively) from remote clients that are not within our designated management subnet (10.0.3.0/24), starting with 443/tcp:
$ sudo firewall-cmd --permanent --zone=public --add-rich-rule='
 rule family="ipv4"
 source address="10.0.3.0/28"
 port protocol="tcp" port="443" accept'
  • Next create a similar rule for port 80/tcp, for allowing HTTP traffic (since we don't yet have any PKI infrastructure with which we can apply valid certificates to our internal websites for authenticity etc.):
$ sudo firewall-cmd --permanent --zone=public --add-rich-rule='
  rule family="ipv4"
  source address="10.0.3.0/28"
  port protocol="tcp" port="80" accept'
  • Finally we need to allow 53/udp, which is the port & protocol used for DNS, and since we will be broadly accepting DNS queries from clients regardless of what their origin/network disposition, we won't apply any "rich" filters for this ingress rule:

$ sudo firewall-cmd --add-port=53/udp --permanent

  • With these rules applied, we can confirm our configuration is setup for success by using the firewall-cmd command combined with the --list-all flag:

$ sudo firewall-cmd --list-all

5

  • At this point, as a test for posterity we can test accessing our Pi-holes' administrative web dashboard (as we did before) from an IP not in the subnet we explicitly allowed earlier (in my case the management network of 10.0.3.0/24).

💡 The screenshot below depicts a successful connection from my management workstation (hera01) while a failing connection from my personal desktop:

6

Configuring Conditional Forwarding of Local DNS Record Queries on Pi-hole:

  • For our us to benefit from our domain clients forwarding their DNS queries any destination other than a domain controller for processing/review, we need to setup rules which can selectively forward DNS queries for internal records to our domain controller for resolution.

  • We can accomplish this using conditional forwarding, found under Settings > DNS > Advanced DNS Settings in the Pi-hole management dashboard, as shown in the screenshot below:

7

💣 Please note that failure to take this step to configure special forwarding of these requests will result in issues for future network clients using Pi-hole as it's primary DNS server when attempting to join the domain, or resolve hostnames for any internal network resources.

  • The screenshot below shows my management workstation hera01 after being reconfigured to use the Pi-hole server (10.0.3.12) as it's primary DNS, and first failing to resolve homer.local before I implemented the conditional forwarding rules, when after I was able to properly receive the IPv4 address associated with that A record (according to the local domain controller, not the Pi-hole server!).

8

  • At this point we've confirmed a successful install & configuration of our Pi-hole server, specifically for use in the context of our home lab to field DNS queries and forward them accordingly based on the target being resolved.