Cybersecurity / Networking / Infrastructure
Pi-hole DNS Filtering & Secure Remote Access
A self-hosted, containerized DNS filtering solution deployed on a Raspberry Pi 5 and integrated with WireGuard VPN to provide network-level advertisement blocking, DNS management, and secure remote access for multiple devices.
Introduction
Project Overview
As part of developing my personal cybersecurity homelab, I wanted to gain practical experience with DNS infrastructure, Linux administration, containerization, and secure remote networking.
To accomplish this, I deployed Pi-hole on a Raspberry Pi 5 using Docker and Docker Compose. Pi-hole operates as a DNS filtering service, allowing configured devices to block requests to known advertising, tracking, and other unwanted domains.
I integrated the service with my existing WireGuard VPN infrastructure, allowing my MacBook and iPhone to access the self-hosted DNS server while connected to external networks.
This project provided hands-on experience configuring DNS services, managing Docker containers, implementing network access controls, troubleshooting connectivity, and validating network traffic.
Infrastructure Challenge
The Problem
By default, most devices rely on DNS resolvers provided by their internet service provider, network administrator, or a third-party DNS provider.
These DNS services typically resolve requested domains without applying personalized filtering policies to advertising and tracking domains.
I wanted greater visibility into the DNS requests generated by my devices, along with the ability to create and manage custom domain-blocking policies.
Additionally, I wanted this functionality to remain available when my devices were connected to networks outside my home.
This introduced several technical challenges: deploying a reliable DNS service, integrating it with existing network infrastructure, maintaining secure remote connectivity, and ensuring DNS requests reached the appropriate server.
Implementation
Technical Solution
1. Raspberry Pi Server Configuration
I used a Raspberry Pi 5 running a Linux-based operating system as the host for my DNS filtering infrastructure.
The Raspberry Pi was configured for remote administration using SSH public-key authentication and a hardened SSH configuration.
This allowed me to manage the system remotely through an authenticated, encrypted connection.
2. Docker Containerization
Rather than installing Pi-hole directly onto the host operating system, I deployed it inside a Docker container.
Containerization allows the DNS filtering application to operate separately from other services hosted on the Raspberry Pi.
Docker Compose was used to define the application's configuration, network ports, persistent storage, and restart behavior.
This approach also simplifies future maintenance, updates, and redeployment.
3. DNS Service Configuration
Pi-hole was configured to receive DNS requests on TCP and UDP port 53.
The administrative dashboard was exposed through port 8080 on the Raspberry Pi, allowing DNS activity and filtering statistics to be reviewed through a web interface.
Persistent Docker storage was configured to preserve Pi-hole settings and filtering data across container restarts.
4. WireGuard VPN Integration
I integrated Pi-hole with my existing WireGuard VPN server to extend DNS filtering to devices outside my home network.
The WireGuard server was configured with the VPN address 10.10.10.1.
My MacBook and iPhone were configured as separate WireGuard peers with individual VPN addresses.
Each client was configured to use 10.10.10.1 as its DNS resolver while the VPN connection was active.
This allowed DNS requests to reach the Raspberry Pi through an encrypted WireGuard tunnel.
5. Split-Tunnel Networking
I implemented split-tunnel routing rather than routing all device traffic through the VPN.
The WireGuard clients were configured to route traffic destined for the 10.10.10.0/24 VPN subnet through the encrypted tunnel.
This configuration allowed devices to access the Pi-hole DNS server remotely while keeping ordinary internet traffic on their existing network connection.
6. Firewall Configuration
I used Uncomplicated Firewall (UFW) to manage network access to services hosted on the Raspberry Pi.
Firewall configuration was designed to permit necessary DNS, VPN, and administrative traffic while limiting unnecessary exposure.
The WireGuard server used UDP port 51821 for incoming VPN connections.
DNS services were made accessible to authorized clients through the appropriate network interfaces.
System Design
System Architecture
The infrastructure combines a containerized DNS filtering service with an encrypted VPN connection.
Remote devices connect to the Raspberry Pi through WireGuard and forward DNS requests to the Pi-hole container.
Remote Devices
--------------
MacBook Air
10.10.10.2
iPhone
10.10.10.3
|
|
v
WireGuard VPN
Encrypted Tunnel
|
|
v
Home Router
UDP Port 51821
|
|
v
Raspberry Pi 5
10.10.10.1
|
|
v
Docker Engine
|
|
v
Pi-hole Container
DNS: TCP/UDP 53
Dashboard: 8080
|
|
v
DNS Filtering
|
_____|_____
| |
v v
Allowed Blocked
Domains Domains
|
v
Upstream DNS
Resolution
DNS queries are evaluated against Pi-hole's configured filtering rules.
Requests for blocked domains are denied, while permitted requests are resolved through the configured upstream DNS service or an available cached response.
Containerization
Docker Deployment
Docker Compose Configuration
I used Docker Compose to manage the Pi-hole container and define its required network services.
The following configuration illustrates the primary settings used in the deployment. Sensitive values and environment-specific details have been excluded.
services:
pihole:
image: pihole/pihole:latest
container_name: pihole
ports:
- "53:53/tcp"
- "53:53/udp"
- "8080:80/tcp"
environment:
TZ: "America/New_York"
FTLCONF_dns_listeningMode: "ALL"
volumes:
- "./etc-pihole:/etc/pihole"
restart: unless-stopped
Port Configuration
The container exposes DNS services through TCP and UDP port 53.
The administrative dashboard is mapped to port 8080 on the host.
This prevents the dashboard from occupying the host's default HTTP port, allowing other web services to be hosted separately.
Persistent Storage
A Docker bind mount preserves Pi-hole configuration data outside the container.
This allows the container to be recreated without losing the stored configuration.
Container Management
I used Docker CLI commands to verify container health and troubleshoot the deployment.
docker ps
docker compose ps
docker compose logs
docker compose up -d
These commands allowed me to inspect container status, review application logs, and manage the running service.
Secure Networking
WireGuard VPN Configuration
VPN Addressing
The WireGuard network uses the 10.10.10.0/24 address range.
- Raspberry Pi VPN Server: 10.10.10.1
- MacBook Client: 10.10.10.2
- iPhone Client: 10.10.10.3
Client DNS Configuration
Each WireGuard client was configured to use the Raspberry Pi as its DNS resolver.
[Interface]
Address = 10.10.10.2/32
DNS = 10.10.10.1
[Peer]
AllowedIPs = 10.10.10.0/24
The configuration above illustrates the MacBook's VPN addressing, DNS configuration, and split-tunnel routing settings. Cryptographic keys and endpoint details have been omitted.
Encrypted DNS Transport
By directing DNS requests through WireGuard, the traffic between remote clients and the Raspberry Pi travels through an encrypted tunnel.
This protects DNS traffic across the VPN connection while allowing Pi-hole to apply centralized filtering policies.
The encryption applies to the VPN connection between the client and server. Upstream DNS encryption depends on the resolver configuration.
VPN Connectivity Verification
I used WireGuard's command-line utilities to verify active peer connections and successful handshakes.
sudo wg
Successful handshakes confirmed that the MacBook and iPhone could establish VPN connectivity with the Raspberry Pi.
DNS Security
DNS Filtering & Monitoring
Domain-Based Filtering
Pi-hole uses configured blocklists and filtering rules to identify unwanted DNS requests.
When a configured client requests a blocked domain, Pi-hole responds according to its blocking policy rather than returning the domain's normal DNS resolution.
This can reduce connections to advertising, tracking, and other unwanted domains.
Query Logging
Pi-hole provides a query log that records DNS activity from configured clients.
I used this functionality to verify that DNS requests from my MacBook and iPhone were reaching the Raspberry Pi.
The query log successfully identified requests associated with both WireGuard clients.
Custom Domain Blocking
I tested Pi-hole's filtering functionality by manually adding test domains to its denylist.
After applying the rules, I generated DNS requests and verified that Pi-hole blocked the configured domains.
This confirmed that the DNS filtering service was correctly processing requests from connected clients.
Security Engineering
Security Considerations
SSH Authentication
The Raspberry Pi was configured to support SSH public-key authentication.
This provides a stronger authentication mechanism than relying solely on passwords.
VPN-Based Remote Access
WireGuard provides authenticated, encrypted connectivity between authorized devices and the Raspberry Pi.
This allows remote administrative access and DNS communication without requiring those services to be directly exposed to the public internet.
Firewall Access Controls
UFW was used to configure network access controls for services running on the Raspberry Pi.
The configuration focused on allowing necessary administrative, VPN, and DNS traffic.
Container Isolation
Pi-hole was deployed inside a Docker container rather than being installed directly onto the host operating system.
This provides application-level separation and simplifies service management, although containers still share the host operating system's kernel.
DNS Security Limitations
DNS filtering provides an additional layer of network control but does not replace endpoint security, firewalls, or other cybersecurity controls.
Applications using alternative DNS resolvers or encrypted DNS mechanisms may bypass Pi-hole unless additional controls are implemented.
Problem Solving
Challenges & Troubleshooting
Docker Networking
During deployment, I encountered DNS connectivity issues related to how the container accepted requests from different network interfaces.
I investigated Docker port mappings, network interfaces, and Pi-hole configuration settings to identify the issue.
Configuring Pi-hole's DNS listening mode to accept requests from the required interfaces helped resolve the connectivity problem.
DNS Port Verification
I used Linux networking utilities to verify that DNS services were listening on the expected ports.
sudo ss -tulpn | grep ':53'
This helped confirm that the DNS service was bound to TCP and UDP port 53.
Remote DNS Resolution
Integrating Pi-hole with WireGuard required configuring both DNS settings and VPN routing rules.
I verified that the remote clients could reach the Raspberry Pi through the VPN and that their DNS requests appeared in Pi-hole's query log.
Client Configuration
I also investigated how device-level DNS settings behave when a client leaves its home network.
This reinforced the importance of understanding DNS resolver configuration, network reachability, and the relationship between VPN routing and DNS resolution.
Quality Assurance
Testing & Validation
After completing the deployment, I performed several tests to validate DNS filtering, network connectivity, and VPN functionality.
- Verified that the Pi-hole Docker container was running successfully.
- Confirmed DNS services were listening on TCP and UDP port 53.
- Successfully accessed the Pi-hole administrative dashboard.
- Verified successful WireGuard handshakes from both macOS and iOS clients.
- Confirmed DNS queries from both VPN clients appeared in Pi-hole's query log.
- Tested custom domain blocking rules using manually configured denylist entries.
- Observed filtering of advertising and tracking domains.
- Validated split-tunnel routing to the WireGuard VPN subnet.
Project Outcomes
Results & Technical Impact
The completed project established a functional, self-hosted DNS filtering service integrated with secure remote networking.
- Successfully deployed Pi-hole on a Raspberry Pi 5 using Docker.
- Implemented centralized DNS filtering for configured devices.
- Extended DNS filtering to remote devices through WireGuard VPN.
- Successfully configured and tested macOS and iOS VPN clients.
- Established visibility into client DNS requests through Pi-hole's query logging.
- Verified custom domain blocking functionality.
- Gained practical experience troubleshooting Docker networking, DNS resolution, and VPN connectivity.
Future Development
Planned Improvements
- Integrate Raspberry Pi system logs with a Wazuh SIEM deployment for centralized security monitoring.
- Configure additional DNS filtering policies and custom blocklists.
- Implement automated monitoring for Pi-hole service availability.
- Explore encrypted upstream DNS resolution using DNS-over-HTTPS or DNS-over-TLS.
- Expand DNS filtering to additional devices across the home network.
- Evaluate DNS query patterns to identify unusual or potentially suspicious activity.
Technical Development