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 decided to learn more about networking and went down the rabbit hole of DNS and DNS encryption.This is my personal experience; use it as a starting point for your own explorations.
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 (for unencrypted, unsupported devices). On devices capable of DNS-over-HTTPS (DoH) or DNS-over-TLS (DoT), full encryption is applied from the client onward. Otherwise, DNS requests remain unencrypted at the client level.
 
- pfSense to AdGuard Home: - pfSense forwards DNS requests to AdGuard Home using SSL/TLS with the designated certificates (to be created later).
 
- AdGuard Home: - Processes DNS requests, applying filtering rules.
- Forwards DNS requests to Mullvad’s DNS servers using either DNS-over-HTTPS (DoH) or DNS-over-TLS (DoT).
 
- Tailscale: - Routes DNS traffic through pfSense for mobile devices when off the home network.
- This ensures that DNS queries are encrypted between mobile devices and pfSense, though not necessarily end-to-end.
 
DNS Request and Return Route Diagram#
graph TD
    A[Client Device] -->|1. Sends DNS (Plain, DoH, or DoT: device dependent) request| B[pfSense]
    B -->|2. Forwards DNS request with SSL/TLS| C[AdGuard Home]
    C -->|3. Sends DNS request using DoH/DoT| D[Mullvad DNS Server]
    D -->|4. Returns DNS response| C
    C -->|5. Forwards DNS response with SSL/TLS| B
    B -->|6. Returns DNS response (Plain, DoH, or DoT: device dependent)| A
Summary of Security Benefits#
- Encryption from pfSense to AdGuard Home: DNS queries are encrypted with SSL/TLS.
- Encryption from AdGuard Home to Mullvad’s DNS Servers: DNS queries are encrypted using DoH or DoT.
- Privacy: Minimizes logging risks from third-party DNS providers and cell carriers.
- Ad and Tracker Blocking: AdGuard Home blocks ads and trackers at the DNS level.
- Consistency: The same DNS filtering rules apply both at home and on the go (via 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): AdGuard Home Automated Install - curl -s -S -L https://raw.githubusercontent.com/AdguardTeam/AdGuardHome/master/scripts/install.sh | sh -s -- -v
- Proxmox Helper Script: Proxmox Helper Script - bash -c "$(wget -qLO - https://github.com/tteck/Proxmox/raw/main/ct/adguard.sh)"
 
- Access the Web Interface: 
 In your web browser, navigate to:- http://<your_server_ip>:3000
 and complete the setup.
Step 2: Configure AdGuard Home#
- Access the AdGuard Home Web Interface: 
 Navigate to- http://<your_server_ip>:3000.
- Set Up Upstream DNS Servers: - Go to Settings → DNS Settings.
- Under Upstream DNS servers, add:- https://dns.mullvad.net/dns-query(for DoH)
- tls://dns.mullvad.net(for DoT)
 
 
- Configure Encryption: 
 More details can be found in the AdGuard Home Encryption Wiki.- Go to Settings → Encryption Settings. 
- Configure SSL/TLS certificates. 
- Set up Let’s Encrypt certs using Certbot: - sudo certbot certonly --manual --preferred-challenges=dns --preferred-chain="ISRG Root X1"- Follow the instructions provided by Certbot. Provide your domain (and wildcard if needed) during the process. 
 After completion, you’ll receive two files:- fullchain.pem– PEM-encoded SSL certificate.
- privkey.pem– PEM-encoded private key.
 - Either paste the contents into the fields or provide the full file paths, then save and apply. 
 
Step 3: Configure pfSense for Secure DNS Forwarding#
- Install the Certificate: - In pfSense, navigate to System → Cert Manager.
- Import your SSL/TLS certificate and private key (simply use cat <path>to copy the full output contents).
 
- Set Up AdGuard as the DNS Server: - Go to System → General Setup.
- Under DNS Settings, add the IPv4 and (if applicable) IPv6 addresses for AdGuard.
- Save and apply.
 
- Configure the DNS Resolver (Unbound): - Navigate to Services → DNS Resolver.
- Enable the DNS Resolver.
- Leave ports as default.
- Enable SSL/TLS Service.
- Select the certificate installed previously.
- Choose the interfaces to use (e.g., All if unsure).
- Under DNS Query Forwarding:- Enable Forwarding Mode.
- Use SSL/TLS for outgoing DNS queries to forwarding servers (this forwards DNS queries to AdGuard via DoT).
 
- Save and apply.
 
Step 4: Configure Tailscale#
Enable SSH Access:
- In pfSense, navigate to System → Advanced → Admin Access. 
- Under Secure Shell, check “Enable Secure Shell”. 
- (Optional) Change the default port from 22. 
- From your terminal, connect using: - ssh -p <port-if-changed> <your-admin-name>@<your-pfsense-ip>
- Select option - 8(Shell) from the pfSense menu.
- Run the following to install Tailscale: - pkg add -f https://pkg.freebsd.org/FreeBSD:14:amd64/latest/All/tailscale-1.70.0.pkg- (Replace the URL with the latest version if updated; - 1.70.0was released on 07/17/24.)
- (Optional) Add firewall rules to restrict SSH access from WAN for increased security. 
- Install Tailscale on pfSense: - Follow the official Tailscale documentation to install it via pfSense’s package manager.
- Go to System → Package Manager → Available Packages.
- Note: At times the available version might lag behind; check this forum discussion for updates.
 
- Configure Tailscale to Use pfSense as DNS: - Navigate to VPN → Tailscale → Settings.
- Under DNS, uncheck “Accept DNS” (if checked) to prevent Tailscale from overriding your DNS settings.
- Under Routing, uncheck “Accept Subnet Routes” if it’s enabled.- Add the IP of pfSense (for example, 192.168.1.1/32) to Advertised Routes.
- Optionally, add AdGuard’s IP if you wish to access its admin panel remotely.
 
- Add the IP of pfSense (for example, 
- Save and apply the changes.
 
- Approve Routes and Configure DNS in Tailscale Admin: - Visit Tailscale’s Admin Console, select your pfSense machine.
- Under the “Subnets” section, approve the awaiting routes.
- In the “DNS” tab, enable “override local DNS”.
- Add a custom nameserver pointing to your advertised pfSense IP.
- Optionally, disable key expiry by selecting the three vertical dots (ellipsis) next to your pfSense machine and opting for “Disable key expiry”. More details can be found here.
 
- Install Tailscale on Mobile Devices: - Download and install the Tailscale app on your mobile devices.
- Log in with your Tailscale account and enable the Tailscale DNS settings.
 
Optional Step 5: Configure Clients#
Configure macOS & iOS for DoH/DoT#
- Using Built-in Support (macOS 11+ and iOS 14+): - Refer to the following resources:
 
- Using AdGuard Profiles: - Under Setup Guide → DNS Privacy, configure a profile using a hostname (e.g., adguard.<your-domain>).
- Refer to the AdGuard Teams documentation on ClientIDs.
 
- Under Setup Guide → DNS Privacy, configure a profile using a hostname (e.g., 
- Alternative: pfSense Profile Configuration: - Create a configuration profile pointing to pfSense instead of AdGuard using Apple’s DNS profile docs or an online tool.
- Note: This setup works only on your home network unless paired with Tailscale. Do not reverse proxy pfSense.
 
- Caveats with Profiles: - Profiles without a reverse proxy will only work on your Home Network. With Tailscale, encrypted DNS is still maintained via the VPN tunnel to pfSense.
- If using an AdGuard profile, the VPN bypasses pfSense, but round-trip encryption remains intact.
- For a signed profile, use your Apple developer account; more info is available here.
 
Android#
- Android 9+ supports DNS-over-TLS natively. To configure, go to:
 Settings → Network & internet → Advanced → Private DNS and enter your domain name.
Windows#
- Windows 10 Build 19628 and later support DNS-over-HTTPS natively.
Conclusion#
This setup ensures that DNS requests remain encrypted and private between pfSense and AdGuard Home, and from AdGuard Home to Mullvad’s DNS servers. Although client-to-pfSense queries may not always be encrypted, using Tailscale secures connections for mobile devices when away from home. By leveraging pfSense, AdGuard Home, and Tailscale, you’ve built a robust and secure DNS resolution process.
Is this the ultimate solution? Probably not—it’s the framework I built while learning about networking. I hope you enjoy this journey down the rabbit hole with me. Until next time, happy exploring!
Open to suggestions or additional insights on any weak points!