Secure DNS Setup with pfSense, AdGuard Home, and Tailscale
Current Setup Overview
📘 Disclaimer: I am not an expert nor do I claim to be! I am simply a man who has decided to learn more about networking and went down the rabbit hole of DNS and DNS encryption.
My current setup involves the following components and configurations to ensure secure and private DNS resolution:
-
Client Device to pfSense:
-DNS requests from client devices are sent to pfSense in plain text (unencrypted unsupported devices). On devices capable of DNS-over-HTTPS (DoH) or DNS-over-TLS (DoT), we will have full encryption from the client and back. Otherwise, the DNS will be plain or unencrypted at the client when leaving and returning to the client.
-
pfSense to AdGuard Home:
- pfSense forwards DNS requests to AdGuard Home using SSL/TLS with the same certificates (these will be made later).
-
AdGuard Home:
- AdGuard Home processes DNS requests and applies filtering rules.
- AdGuard Home forwards DNS requests to Mullvad’s DNS servers using DNS-over-HTTPS (DoH) or DNS-over-TLS (DoT).
-
Tailscale:
- Tailscale is used to route DNS traffic through pfSense for mobile devices when not at home.
- This ensures that DNS queries are encrypted between mobile devices and pfSense, but not necessarily end-to-end.
DNS Request and Return Route Diagram
Summary of Security Benefits
- Encryption from pfSense to AdGuard Home: DNS queries are encrypted using SSL/TLS.
- Encryption from AdGuard Home to Mullvad’s DNS Servers: DNS queries are encrypted using DoH or DoT.
- Privacy: Avoids potential logging by third-party DNS providers and cell carriers.
- Ad and Tracker Blocking: AdGuard Home provides DNS-level blocking of ads and trackers.
- Consistency: The same DNS filtering rules are applied both at home and on the go with a reverse proxy or Tailscale.
Step-by-Step Setup Guide
Step 1: Install and Configure AdGuard Home
-
Download and Install AdGuard Home:
Automated install (Linux/Unix/MacOS/FreeBSD/OpenBSD)
curl -s -S -L https://raw.githubusercontent.com/AdguardTeam/AdGuardHome/master/scripts/install.sh | sh -s -- -v
bash -c "$(wget -qLO -https://github.com/tteck/Proxmox/raw/main/ct/adguard.sh)"
-
Access the Web Interface:
Open a web browser and go to
http://<your_server_ip>:3000
to complete the setup.
Step 2: Configure AdGuard Home
-
Access AdGuard Home Web Interface: Go to the web interface of AdGuard Home
http://<your_server_ip>:3000
. -
Set Up Upstream DNS Servers:
- Go to Settings -> DNS Settings.
- Under Upstream DNS servers, add secure upstream servers such as:
https://dns.mullvad.net/dns-query
(for DoH)tls://dns.mullvad.net
(for DoT)
-
Configure Encryption: More information can be found here
- Go to Settings -> Encryption Settings.
- Ensure that your SSL/TLS certificates are properly configured.
-
Setup Lets Encrypt certs using Certbot:
- Obtain a domain from any domain name provider e.g. Namecheap
- Run in terminal:
sudo certbot certonly --manual --preferred-challenges=dns --preferred-chain="ISRG Root X1"`or if root use`certbot certonly --manual --preferred-challenges=dns --preferred-chain="ISRG Root X1"
- Follow instructions in Certbot
- For the domain section, use your domain you purchased. Add a *
for a wildcard cert as well as the base domain separated by a ','. - The final result will give you two files: -
fullchain.pem
– PEM-encoded SSL certificate. -privkey.pem
– PEM-encoded private key. - Either paste the contents of these files into the fields or provide the full path.
- Save and Apply
Step 3: Configure pfSense for Secure DNS Forwarding
-
Install the Certificate:
- Go to System -> Cert Manager in pfSense and import the SSL/TLS certificate and private key from the last section. You can simply paste the output
cat <your-path>
for each file.
- Go to System -> Cert Manager in pfSense and import the SSL/TLS certificate and private key from the last section. You can simply paste the output
-
Setup Adguard as the DNS servers
- Go to System -> General Setup
- Look for DNS Setting
- Add the IPv4 and IPv6 (if applicable) addresses for Adguard
- Save And Apply
-
Configure DNS Resolver (Unbound):
- Go to Services -> DNS Resolver
- Enable DNS resolver
- Leave the ports default.
- Enable SSL/TLS Service
- Select the cert added earlier for SSL/TLS Certificate
- Pick the interfaces you wish to use. (I selected All, which might not be correct; I’m still new to this network stuff)
- Under DNS Query Forwarding
- Enable Forwarding Mode
- Use SSL/TLS for outgoing DNS queries to forwarding servers (this is needed to forward our DNS queries to Adguard using DoT).
- Save And Apply
Step 4: Configure Tailscale
Install Tailscale viva SSH
Enable SSH Access
- Go to System -> Advanced -> Admin Access
- Scroll to Secure Shell
- Check
Enable Secure Shell
underSecure Shell Server
- Port 22 is default, I would change it but totally up to you.
- Open your terminal of choice and
ssh -p <port-if-changed> <your-admin-name>@<your-pfsense-ip>
- Note:
-p
is not needed if the port number was left as22
.
- Note:
- Choose option
8
(Shell) from the pfSense menu. - Finally, run
pkg add -f https://pkg.freebsd.org/FreeBSD:14:amd64/latest/All/tailscale-1.70.0.pkg
- Ensure you replace the URL with the latest version if it has been updated.
1.70.0
was released on 07/17/24
- Optional: Add firewall rules to block SSH from WAN
- Security: Allowing SSH access from the WAN interface can expose your pfSense device to potential attacks. Add firewall rules to restrict access to specific IP addresses if possible.
-
Install Tailscale on pfSense:
- Follow the Tailscale documentation to install and configure Tailscale on pfSense using the built-in package manager.
- Go to System -> Package Manager -> Available Packages.
- Note: As of this writing, Tailscale has not been updated on pfSense’s package manager, which raises scrutiny concerns. This appears to be a recurring issue, as you can see.here.
-
Configure Tailscale to Use pfSense as DNS:
- Go to VPN -> Tailscale -> Settings
- DNS: Uncheck “Accept DNS” if checked. This ensures our DNS is not overridden by Tailscale.
- Under Routing unckeck Accept Subnet Routes if checked.
- Advertised Routes: Add the IP of pfSense, e.g., 192.168.1.1/32 or similar (needs to be the IP for your actual pfSense, the same one used to access the admin), as this will only advertise the single IP.
- Optionally, you can do the same for Adguard if you wish to access the admin panel while using your Tailnet.
- Save and Apply
-
Navigate to Tailscale admin
- Look for your PfSense machine and click into it.
- Under Subnets you will find Awaiting Approval; click edit and approve the routes.
- Navigate to DNS
- Under Nameservers, check “override local DNS”
- Next, go to Add nameserver -> Custom: add the route you advertised for pfSense.
- Optinally back on the Machines page 1) Click on the three vertical dots (ellipsis) next to the machine’s (pfsense) details to open the options menu. 2) In the dropdown menu, click on “Disable key expiry.” This will make sure the key for Tailscale to communicate with pfSense does not expire. More Information here
-
Install Tailscale on Mobile Devices:
- Install the Tailscale app on your mobile devices and log in with your Tailscale account.
- Ensure that the mobile devices are connected to your Tailscale network. And Use Tailscale DNS settings are enabled.
Optional Step 5: Configure Clients
Configure macOS & iOS for DoH/DoT
-
Using macOS Built-in Support (macOS 11 and Later iOS 14 and later):
- Refer to the following resources for configuring DoH/DoT via a configuration profile:
-
Adguard can also generate these profiles.
- Under Setup Guide -> DNS Privacy
- The hostname would be, for example,
adguard.<your-domain>
- “ClientIDs are identifiers that can be used with the following DNS protocols: DNS-over-HTTPS, DNS-over-TLS, and DNS-over-QUIC.” 1
-
Pfsense profile instead of Adguard
-
Caveats of profiles.
- It is worth noting that if you do not reverse proxy your Adguard, these profiles will only work on your Home Network. However, with Tailscale setup, you can still enjoy end-to-end encrypted DNS, as it routes through Tailscale (end-to-end VPN tunnel) to Pfsense, which will take the plain DNS and encrypt it using DoT.
- If you don’t use the Tailscale setup and choose a profile while not using a reverse proxy, you must manually disable it when on cellular or any other network.
- Also note that when using a profile that’s set up for your Adguard instance, it will bypass Pfsense, thus going back to the 3 points of encryption, but it will be encrypted round trip.
- If you want an a signed Profile config and you have an Apple developer account, you can sign it yourself. Information on that can be found here.
Android
- Android 9+ supports
DNS-over-TLS
natively. To configure it, go to Settings -> Network & internet -> ** Advanced** -> Private DNS and enter your domain name there.
Windows
- Windows 10 Build 19628 and higher support
DNS-over-HTTPS
natively.
Conclusion
This setup ensures that DNS requests are encrypted and private between pfSense and AdGuard Home, and between AdGuard Home and Mullvad’s DNS servers. While DNS queries from client devices to pfSense are not always encrypted by default, using Tailscale helps secure the connection for mobile devices when not at home. By using pfSense, AdGuard Home, and Tailscale, you achieve a robust and secure DNS resolution process.
Is this the absolute end-all be-all solution? Likely not, it’s what I put together while learning about some networking topics. It’s mine and it works for me! I hope you enjoyed this journey down the rabbit hole with me, until next time!
Open to suggestions or education on any weak understandings!