Summary

  Subject:

Setup Pi-Hole DNS Ad-Blocker

  Updated:

2023-09-06

  Author:

Tim Hammond ([email protected])

Derek Pasnick ([email protected])

  Operating Systems:

Ubuntru 20.04

  Background:

This guide was written to setup pi-hole to block the nasty adds, trackers, and cookie monsters.

After a good bit of reading on DNS over HTTPS vs TLS, we decided to abort pursuing the technologies. DNS over HTTPS (DoH) is not an offical RFC-standard while DNS over TLS (DoT) is. The HTTPS technology is more for privacy while the TLS is more for security. I already wrote up the instrcutions for DoH so let left them in this guide. Either way, both technologies seem to be still very experimental along with numberous pros vs cons. This might be something to re-investigate at a later date.

The DNS over HTTPS (DoH) notes below were not tested.

 

Table of Contents

VM Config

VM Specifications:

  • CPU: 1vCPU (2 cores)
  • RAM: 2 GB
  • HD: 100 GB

Change the hostname:

sudo hostnamectl set-hostname ph01.domain.local sudo hostnamectl set-hostname ph02.domain.local

Update the IP:

sudo sed -i 's/192.168.30.200/192.168.30.121/g' /etc/netplan/00-installer-config.yaml sudo sed -i 's/192.168.30.200/192.168.30.122/g' /etc/netplan/00-installer-config.yaml sudo cat /etc/netplan/00-installer-config.yaml

Install

Update the system

sudo apt update sudo apt -y upgrade

Install the bits

sudo curl -sSL https://install.pi-hole.net | bash

Firewall Changes

IPv6 is disabled in the template.

UFW is enabled in the template with a default policy to deny incoming, allow outgoing, and allow ssh.

Add firewall rules:

sudo ufw allow 53/tcp comment piHole_-_DNS sudo ufw allow 53/udp comment piHole_-_DNS sudo ufw allow 80/tcp comment piHole_-_admin_web_interface sudo ufw allow 443/tcp comment piHole_-_admin_web_interface

Restart UFW.

sudo service ufw restart

Show the policies in a numbered order.

sudo ufw status numbered

Pi Hole Config

To log into the web interface, go to:

http://ph01.domain.local/admin
http://ph02.domain.local/admin

Change the default web interface password.

You have to log into the web interface first. Otherwise, the command below will clear the password. If you didn't read this, log into the web interface with the blank password, then use the command below to set a new pwd.

Enter the command and then you will be prompted twice for the login. Use this method in order to avoid having the password remain in the bash history.

sudo pihole -a -p

Update block list (Gravity)

Go to: Tools > Update Gravity > Update button.

To customize themes and contacts:

Go to: Settings > API/Web Interface.

Web interface settings: Pi-hole midnight theme (dark) Administrator Email Address: [email protected]

DNS Setup

Background:

There are really two options on where to place Pihole:

OPTION 1: client > adDNS > pihole (internet forwardwers)

OPTION 2: client > pihole > adDNS (internet forwardwers)

OPTION 1

OPTION 1 is the preferred method as it is the simplest, easiest, but the downside is that you loose the logging on a per client basis. All logs would show which AD DNS server was taking care of the request instead of the client itself.

During the setup wizard, you can select a public DNS server or select custom. Verify the following settings:

In the Pihole Web Interface:

Go to: Settings > DNS > Upstream DNS Servers.

  1. Select a Public DNS provider (Quad9 (filtered, DNSSEC))
  2. Verify - Upstream DNS servers Custom 1-4 are NOT checked.
  3. Verify - "Conditional forwarding" is NOT checked.

OPTION 2

This would provide the client logging but in a lot of testing, the config is very kludgy. There are a lot of forums on the topic, but most of it is hobbists with odd setups.

If blocking is going to be required, it does not matter who requests the content so long as the target is controlled. Although, if per client logging is required, OPTION 2 is going to be required. OPTION 2, can be setup in two different ways (as described below).

During the setup wziard, you can select a public DNS server or select custom. We are using Active Directory for DHCP and DNS, so we want to set the upstream to be custom. Thare two differnt options here.

OPTION 2A

In the Pihole Web Interface:

Go to: Settings > DNS > Upstream DNS Servers

  1. Verify - Public DNS servers are NOT checked.
  2. Settings > DNS > Upstream DNS Servers
    1. Custom1 (IPv4): 192.168.30.100
    2. Custom2 (IPv4): 192.168.30.101
  3. Verify - "Conditional forwarding" is NOT checked.

OPTION 2B

Option 2B is preferred method (over 2A).

The problem with OPTION 2B is that there is only one text box for a single subnet. We have more than that.

In the Pihole Web Interface:

Go to: Settings > DNS > Upstream DNS Servers

  1. Verify - Public DNS servers are NOT checked.
  2. Verify - Upstream DNS servers Custom 1-4 are NOT checked.
  3. "Conditional forwarding" should be checked.
    1. Local network in CIDR notation: 192.168.30.0/24
    2. IP address of your DHCP server: 192.168.30.100
    3. Local domain name: domain.local

Additional Information

The active settings from the web interface are stored in: /etc/dnsmasq.d/01-pihole.conf. This file is over written every time their is a upgrade. So we have to create our own extra config file that will stay after updates.

sudo tee -a /etc/dnsmasq.d/01-pihole-custom.conf >/dev/null <<EOF rev-server=192.168.30.0/24,192.168.30.100 rev-server=192.168.30.0/24,192.168.30.101 rev-server=192.168.31.0/24,192.168.30.100 rev-server=192.168.31.0/24,192.168.30.101 rev-server=192.168.32.0/24,192.168.30.100 rev-server=192.168.32.0/24,192.168.30.101 rev-server=192.168.33.0/24,192.168.30.100 rev-server=192.168.33.0/24,192.168.30.101 server=/domain.local/192.168.30.100 server=/domain.local/192.168.30.101 EOF

Make sure to restart the service.

Verify that it restarted ok.

sudo systemctl restart pihole-FTL.service sudo systemctl status pihole-FTL.service

To verify the syntanx:

sudo pihole-FTL dnsmasq-test

Whichever option you pick for the Pihole DNS setup, update the Active Directory DNS servers DNS forwarders.

  1. Open the DNS server MMC for the Windows DNS server.
  2. Right click the DNS Server you would like to udpate.
  3. Select Properties.Open the Edit Forwarders window
  4. Select the Forwarders tab.
  5. click Edit.
  6. Make the appriate udpates based on OPTION X.
  7. Repeat these steps for each Windows AD DNS server.

Local DNS Fixes

If you are using OPTION 1, you will need to modify the local hosts config as the DNS resolver cannot find the Active Directory DNS servers.

sudo tee -a /etc/hosts >/dev/null <<EOF 192.168.30.1xx example01.domain.local 192.168.30.1xx example02.domain.local 192.168.30.121 ph01.domain.local 192.168.30.122 ph02.domain.local EOF

Verify the change.

sudo cat /etc/hosts | grep -i 10

Certificate Creation

Certificate creation is out of the scope of this document.

When settting the Subject Name and Alternate names, make sure to add the second Pi-Hole host to the setup in the same certifciate.

Certificate Install

This section was taken from the domain join guide.

Pihole requires the certs to be in a "base-64 encoded x.509 (.pem)" format. The *.pem is required. Disregard the note below about the *.crt extension. They are effectively the same content just a different file extension.

The PEM format is the most common format used for certificates. Extensions used for PEM certificates are: cer, crt, and pem. They are Base64 encoded ASCII files that contain human readable content between --BEGIN CERTIFICATE-- and --END CERTIFICATE--. The DER format is the binary form of the certificate. DER formatted certificates do not contain the "BEGIN CERTIFICATE/END CERTIFICATE" statements. DER formatted certificates most often use the '.der' extension.

The certs should have already been converted from the a "base-64 encoded x.509 (.cer)" Windows encoding to a Unix encoding. If this has not already happened:

Run the following OpenSSL commands:

openssl x509 -inform PEM -in chain-root.cer -out chain-root.crt openssl x509 -inform PEM -in chain-inter.cer -out chain-inter.crt

Combine the files (if needed):

Combine the intermediate cert in to the root CA.

Combine the private key in to the system cert.

sudo cat ph01-priv.pem ph01-cert.pem >> chain-ph01.pem sudo cat ph02-priv.pem ph02-cert.pem >> chain-ph02.pem sudo cat chain-inter.pem chain-root.pem >> chain-ca.pem

Download the certs to the local system.

In the respective distro cert install commands, adding a combined chain would be redundant. So we only use the root and intermediate, not cert chain.

/tmp/chain-ph01.pem /tmp/chain-ph02.pem /tmp/chain-ca.pem

Create directory to store the certs.

sudo mkdir -p /etc/lighttpd/ssl/

Move the certs to their proper home.

sudo mv /tmp/chain-ph01.pem /etc/lighttpd/ssl/chain-ph01.pem sudo mv /tmp/chain-ph02.pem /etc/lighttpd/ssl/chain-ph02.pem sudo mv /tmp/chain-ca.pem /etc/lighttpd/ssl/chain-ca.pem

Sercure the certs.

sudo chmod 600 /etc/lighttpd/ssl/* sudo chown www-data:www-data /etc/lighttpd/ssl/*

Update the Lighttpd config to see the certs and to redirect from http to https.

The active settings from the web interface are stored in: /etc/lighttpd/lighttpd.conf. This file is over written every time their is a upgrade. So we have to create our own extra config file that will stay after updates.

sudo tee -a /etc/lighttpd/external.conf >/dev/null <<EOF # This was painful to find. server.modules += ( "mod_openssl" ) \$HTTP["host"] == "ph01.domain.local" { # Ensure the Pi-hole Block Page knows that this is not a blocked domain. setenv.add-environment = ("fqdn" => "true") # Enable the SSL engine with a local CA cert, only for this specific host. \$SERVER["socket"] == ":443" { ssl.engine = "enable" ssl.pemfile = "/etc/lighttpd/ssl/chain-ph01.pem" ssl.ca-file = "/etc/lighttpd/ssl/chain-ca.pem" ssl.cipher-list = "HIGH" ssl.use-sslv2 = "disable" ssl.use-sslv3 = "disable" } # Redirect HTTP to HTTPS. \$HTTP["scheme"] == "http" { \$HTTP["host"] =~ ".*" { url.redirect = (".*" => "https://%0\$0") } } } EOF

ph02 ONLY

Update the external config from ph01 to ph02.

sudo sed -i 's/ph01/ph02/g' /etc/lighttpd/external.conf

Verify the changes.

sudo cat /etc/lighttpd/external.conf | grep -i ph0

Verify the syntax of the changes to the config file before restarting Lighttpd service.

sudo lighttpd -t -f /etc/lighttpd/lighttpd.conf sudo lighttpd -t -f /etc/lighttpd/external.conf

Restart Lighttpd

sudo systemctl restart lighttpd

DNS over TLS (DoT)

!!! DO NOT USE !!!

See the "Summary - Description" above.

DNS over HTTPS (DoH)

!!! DO NOT USE !!!

See the "Summary - Description" above.

Download the latest bits.

wget https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb

Install the deb package.

sudo apt -y install ./cloudflared-linux-amd64.deb

Point the app to a public DoH provider.

sudo tee -a /etc/default/cloudflared >/dev/null <<EOF # Source: Cloudflare # CLOUDFLARED_OPTS=--port 5053 --upstream https://1.1.1.1/dns-query # Source: Quad9 CLOUDFLARED_OPTS=--port 5054 --upstream https://9.9.9.9/dns-query EOF

Create a local service account for the service.

  • -s specifies shell account to allow.
  • -r is a system account.
  • -M is to NOT create a home dir.
sudo useradd -s /usr/sbin/nologin -r -M cloudflared

Change the user password

sudo passwd cloudflared

Configure the app to start

sudo tee -a /lib/systemd/system/cloudflared.service >/dev/null <<EOF [Unit] Description=cloudflared DNS over HTTPS proxy After=syslog.target network-online.target [Service] Type=simple User=cloudflared EnvironmentFile=/etc/default/cloudflared ExecStart=/usr/local/bin/cloudflared proxy-dns $CLOUDFLARED_OPTS Restart=on-failure RestartSec=10 KillMode=process [Install] WantedBy=multi-user.target EOF

Make sure that the new cloudflared user has access to the config files.

sudo chown cloudflared:cloudflared /etc/default/cloudflared sudo chown cloudflared:cloudflared /usr/local/bin/cloudflared

Enable and then start the cloudflared service.

sudo systemctl enable cloudflared sudo systemctl start cloudflared

Configure Pihole to now use the app.

If you want to use Cloud flare, you could add it to as another "Upstream DNS Servers" Custom: 127.0.0.1#5053

In the Pihole Web Interface:

Go to: Settings > DNS > Upstream DNS Servers

  1. Verify - Public DNS servers are NOT checked.
  2. Settings > DNS > Upstream DNS Servers
    1. Custom1 (IPv4): 127.0.0.1#5054
  3. Verify - "Conditional forwarding" is NOT checked.

Never a bad idea for a reboot.

sudo reboot

Troubleshooting

To backup config through web interface

Go to: Settings > Teleporter > Backup button

References

Install

DNS forwarding

Cert Install

Additional lighttpd documenation

DNS over HTTPS

DNS over LTS