pfSense is a FreeBSD-based firewall and router platform that gives you enterprise-grade network control on commodity hardware. I ran it as a VM on Proxmox before moving to a UniFi Dream Machine. This writeup covers the full setup from installation through to a working multi-VLAN configuration with DNS over TLS.
Why pfSense
I evaluated OPNsense, pfSense, and a plain Linux iptables setup. pfSense won for three reasons: the volume of documentation available, the maturity of the package ecosystem, and the WebGUI which makes complex firewall rule management approachable without sacrificing depth.
Running pfSense in Proxmox
pfSense runs as a full VM rather than an LXC — it needs its own kernel for the FreeBSD network stack.
VM configuration:
CPU: 2 cores (KVM64)
RAM: 2048MB
Disk: 16GB (virtio-scsi)
NIC 1: vtnet0 → vmbr0 (WAN — bridged to physical NIC)
NIC 2: vtnet1 → vmbr1 (LAN bridge)
Download the pfSense CE ISO from netgate.com, attach it as a CD drive, and boot the VM. The installer is straightforward — accept defaults, choose the correct WAN and LAN interfaces when prompted.
Initial WebGUI setup
Once installed, pfSense is accessible at 192.168.1.1 from the LAN. The setup wizard runs on first login:
- Set hostname and domain
- Set upstream DNS servers (I use
1.1.1.1and9.9.9.9initially, then switch to DNS over TLS) - Set timezone to
Europe/London - Configure WAN (DHCP from ISP or static)
- Set a strong admin password
VLAN configuration
pfSense handles VLAN tagging on the LAN interface. Navigate to Interfaces → Assignments → VLANs → Add:
VLAN 10 — DMZ
Parent: vtnet1
VLAN tag: 10
Desc: DMZ
VLAN 20 — IoT
Parent: vtnet1
VLAN tag: 20
Desc: IoT
VLAN 30 — Trusted
Parent: vtnet1
VLAN tag: 30
Desc: Trusted LAN
Assign each VLAN as an interface under Interfaces → Assignments, then enable and configure each:
DMZ: 10.10.10.1/24
IoT: 10.20.20.1/24
Trusted: 192.168.1.1/24
Enable DHCP for each under Services → DHCP Server.
Firewall rules
Navigate to Firewall → Rules and configure per interface.
DMZ rules:
Allow DMZ → WAN (for outbound updates)
Block DMZ → Trusted LAN (isolation)
Block DMZ → IoT
Block DMZ → RFC1918 (catch-all private ranges)
IoT rules:
Allow IoT → WAN (internet access for devices)
Block IoT → Trusted LAN
Block IoT → DMZ
Trusted LAN rules:
Allow Trusted → any (full access)
The block rules must come before any allow rules — pfSense processes rules top to bottom and stops at the first match.
DNS over TLS
Navigate to Services → DNS Resolver → General Settings:
- Enable DNS Resolver: ✅
- DNSSEC: ✅
- DNS over TLS: ✅
Under DNS over TLS Servers, add:
Server: 1.1.1.1 Port: 853 Hostname: cloudflare-dns.com
Server: 9.9.9.9 Port: 853 Hostname: dns.quad9.net
This encrypts all DNS queries leaving the network. Verify it’s working:
# From a client on the LAN
dig @192.168.1.1 example.com
# Should return results via the pfSense resolver
Split-horizon DNS
A useful feature of pfSense’s DNS resolver is host overrides — you can make internal services resolve differently internally than they do externally. Under Services → DNS Resolver → Host Overrides:
Host: nas
Domain: home.local
IP: 192.168.1.20
Desc: Synology NAS internal resolution
Clients on the LAN can then reach nas.home.local which resolves to the internal IP, bypassing any external DNS.
Performance
Running on 2 cores and 2GB RAM, pfSense handles gigabit throughput without breaking a sweat. CPU usage sits at around 2-3% under normal load, spiking briefly during large file transfers. For a home lab it’s significantly over-specced.