Zero-Trust Homelab: Network Segmentation with VLANs and pfSense
Published: June 15, 2026 | CommsNet
If everything on your network can reach everything else, you don't have a network — you have a single point of failure the size of your entire infrastructure. One compromised IoT lightbulb becomes a pivot to your NAS. One breached container becomes a foothold on your management VLAN. In a flat network, trust is binary: you're either in, or you're out.
Zero-trust networking changes the assumption. Nothing is trusted by default. Every segment, every device, every flow must prove it belongs. And the mechanism that enforces this at the homelab scale isn't some expensive SDN controller — it's VLANs on a managed switch, enforced by pfSense firewall rules.
In this article, I'll walk through designing and implementing a zero-trust network segmentation strategy using IEEE 802.1Q VLANs, a managed switch, and pfSense as the inter-VLAN router and policy enforcement point. By the end, your IoT devices won't be able to touch your servers, your guest WiFi will be isolated at L2, and your management interfaces will require explicit allow rules.
Why Zero-Trust for a Homelab?
The Flat Network Problem
Most homelabs start as flat networks — one /24, everything plugged into one switch, maybe a consumer router doing NAT. It works until it doesn't:
| Attack Vector | Flat Network Impact | Segmented Network Impact |
|---|---|---|
| Compromised IoT device | Lateral movement to NAS, servers | Contained to IoT VLAN, blocked at firewall |
| Malware on guest laptop | Access to all L2 hosts | Isolated to guest VLAN, no cross-VLAN routing |
| Exposed service exploit | Direct path to management interfaces | Must traverse firewall rules between VLANs |
| DNS poisoning on one host | Affects entire broadcast domain | Limited to single VLAN scope |
Zero-Trust Principles (Adapted for Homelab)
Enterprise zero-trust frameworks (NIST SP 800-207, Forrester ZTX) assume things homelabbers don't have — identity providers, microsegmentation platforms, continuous verification. But the core principles translate:
- Never trust, always verify — Every inter-VLAN flow is denied by default, explicitly allowed
- Least privilege access — VLANs get only the routing rules they need
- Assume breach — Design so that compromising one VLAN doesn't compromise others
- Verify explicitly — pfSense rules are the policy; logging proves enforcement
Network Design
VLAN Architecture
Here's the segmentation model I use. It's designed around the principle of isolation by trust level:
┌─────────────────────────────────────────────────────────┐
│ VLAN Architecture │
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌─────────┐ │
│ │ VLAN 10 │ │ VLAN 20 │ │ VLAN 30 │ │ VLAN 40 │ │
│ │Management│ │ Servers │ │ IoT │ │ Guest │ │
│ │10.0.10/24│ │10.0.20/24│ │10.0.30/24│ │10.0.40 │ │
│ │ TRUST: H │ │ TRUST: H │ │ TRUST: L │ │TRUST: N│ │
│ └─────┬────┘ └─────┬────┘ └─────┬────┘ └────┬────┘ │
│ │ │ │ │ │
│ └──────────────┴──────┬───────┴────────────┘ │
│ │ │
│ ┌────────┴────────┐ │
│ │ pfSense │ │
│ │ Inter-VLAN │ │
│ │ Router + FW │ │
│ └────────────────┘ │
└─────────────────────────────────────────────────────────┘
VLAN Definitions
| VLAN ID | Name | Subnet | Trust Level | Purpose |
|---|---|---|---|---|
| 10 | Management | 10.0.10.0/24 | High | pfSense, Proxmox, switches, IPMI/iDRAC |
| 20 | Servers | 10.0.20.0/24 | High | NAS, Docker hosts, application servers |
| 30 | IoT | 10.0.30.0/24 | Low | Smart devices, sensors, cameras |
| 40 | Guest | 10.0.40.0/24 | None | Guest WiFi, untrusted devices |
| 50 | Services | 10.0.50.0/24 | Medium | Exposed services, reverse proxy, tunnel endpoints |
Trust Model and Flow Rules
The firewall policy is the heart of zero-trust. Every rule is explicit:
Source VLAN → Destination VLAN → Allowed? → Reason
─────────────────────────────────────────────────────
Management → Any → ALLOW → Admin access
Servers → Management → DENY → No reverse access to mgmt
Servers → Servers → ALLOW → Internal service communication
Servers → IoT → DENY → No need to reach IoT
Servers → Services → ALLOW → Publish services
IoT → Servers → LIMITED → Only specific ports (DNS, NTP, specific API)
IoT → Management → DENY → No access to mgmt interfaces
IoT → Internet → ALLOW → Firmware updates, cloud APIs
IoT → Guest → DENY → Mutual isolation
Guest → Any (internal) → DENY → Complete isolation
Guest → Internet → ALLOW → Internet-only access
Services → Servers → ALLOW → Reverse proxy to backends
Services → Management → DENY — No access to mgmt
Hardware Requirements
You don't need enterprise gear. Here's what works at the homelab scale:
Managed Switch (Required)
You need a switch that supports 802.1Q VLAN tagging. Options by budget:
| Switch | Ports | VLAN Support | Price (Used) | Notes |
|---|---|---|---|---|
| Cisco Catalyst 2960 | 24/48 | Full 802.1Q | $30-80 | Bulletproof, CLI only |
| HPE ProCurve 2530 | 24 | Full 802.1Q | $40-100 | Web UI + CLI |
| TP-Link SG108E | 8 | Basic 802.1Q | $25 | Budget starter, limited CLI |
| Ubiquiti USW-24 | 24 | Full + UI | $100-200 | UniFi ecosystem |
| MikroTik CRS326 | 24 | Full + RouterOS | $80 | Powerful but steep learning curve |
My pick: Cisco Catalyst 2960G — cheap on eBay, never dies, full VLAN feature set. The CLI is an investment that pays off.
pfSense Hardware
pfSense runs the inter-VLAN routing and firewall. Options:
| Option | Cost | Performance | Notes |
|---|---|---|---|
| Netgate SG-1100 | $179 | ~1 Gbps routing | Purpose-built, low power |
| Protectli Vault | $300+ | ~2 Gbps routing | Intel NICs, fanless |
| Repurposed PC + 4 NICs | $50-100 | 3+ Gbps routing | Best performance/$, more power draw |
| Proxmox VM + virtio NICs | $0 | ~10 Gbps routing | Already have Proxmox? Use it |
My pick: pfSense as a Proxmox VM with 4 virtio NICs. You already have the hardware.
Implementation: Step by Step
Step 1: Configure VLANs on pfSense
Navigate to Interfaces → Assignments → VLANs and create each VLAN:
Parent Interface: vmx0 (LAN)
VLAN Tag: 10 Priority: 0 Description: Management
VLAN Tag: 20 Priority: 0 Description: Servers
VLAN Tag: 30 Priority: 0 Description: IoT
VLAN Tag: 40 Priority: 0 Description: Guest
VLAN Tag: 50 Priority: 0 Description: Services
Then assign each VLAN as a new interface:
Interfaces → Assignments:
-
vmx0.10→ OPT1 → rename toMGMT -
vmx0.20→ OPT2 → rename toSERVERS -
vmx0.30→ OPT3 → rename toIOT -
vmx0.40→ OPT4 → rename toGUEST -
vmx0.50→ OPT5 → rename toSERVICES
Enable each interface and set its IPv4 Static address:
MGMT: 10.0.10.1/24
SERVERS: 10.0.20.1/24
IOT: 10.0.30.1/24
GUEST: 10.0.40.1/24
SERVICES: 10.0.50.1/24
Step 2: Configure DHCP for Each VLAN
Services → DHCP Server — enable on each VLAN interface:
| Interface | Range | DNS | Gateway | Lease Time |
|---|---|---|---|---|
| MGMT | 10.0.10.100-10.0.10.200 | 10.0.10.1 | 10.0.10.1 | 86400 |
| SERVERS | 10.0.20.100-10.0.20.200 | 10.0.20.1 | 10.0.20.1 | 86400 |
| IOT | 10.0.30.50-10.0.30.200 | 1.1.1.1, 9.9.9.9 | 10.0.30.1 | 3600 |
| GUEST | 10.0.40.50-10.0.40.200 | 1.1.1.1 | 10.0.40.1 | 3600 |
| SERVICES | Static only | 10.0.50.1 | 10.0.50.1 | N/A |
Key decisions:
- IoT/Guest DNS: Point to public resolvers (1.1.1.1), NOT your internal DNS. These VLANs don't need to resolve internal names.
- Services: No DHCP — all services get static IPs. If someone plugs into this VLAN, they get nothing.
- Short lease times on IoT/Guest: Limits how long a rogue device keeps an address.
Step 3: Configure the Managed Switch
This is where VLAN theory meets physical reality. Each switch port must be configured as access (untagged, single VLAN) or trunk (tagged, multiple VLANs).
Port assignments:
Port 1-8: Access, VLAN 20 (Servers) — NAS, Proxmox hosts, Docker servers
Port 9-12: Access, VLAN 30 (IoT) — Smart devices, cameras
Port 13-16: Access, VLAN 40 (Guest) — Guest WiFi AP
Port 17-20: Access, VLAN 10 (Management) — Management workstations
Port 21-24: Trunk, VLAN ALL (tagged) — pfSense, Proxmox, WiFi AP
Cisco 2960 example config:
! Trunk port to pfSense
interface GigabitEthernet0/21
switchport mode trunk
switchport trunk allowed vlan 10,20,30,40,50
switchport trunk native vlan 99 ! Never use VLAN 1 as native
spanning-tree portfast trunk
! Access port for server
interface range GigabitEthernet0/1 - 8
switchport mode access
switchport access vlan 20
spanning-tree portfast
! Access port for IoT
interface range GigabitEthernet0/9 - 12
switchport mode access
switchport access vlan 30
spanning-tree portfast
! Access port for management workstation
interface range GigabitEthernet0/17 - 20
switchport mode access
switchport access vlan 10
spanning-tree portfast
Critical: Set native vlan 99 (or any unused VLAN) on trunk ports. Never use VLAN 1 as the native VLAN — it's the default attack surface on every Cisco switch.
Step 4: Firewall Rules — The Zero-Trust Core
This is where zero-trust is actually enforced. Navigate to Firewall → Rules for each interface.
Management VLAN (Highest Trust)
# MGMT Interface Rules (evaluated top-to-bottom)
#
# 1. Allow MGMT to anything (admin access)
IPv4 * MGMT net * * * → ALLOW — "MGMT: Allow all outbound"
#
# 2. Allow pfSense DNS from MGMT
IPv4 TCP/UDP MGMT net * MGMT address 53 → ALLOW — "MGMT: DNS to pfSense"
#
# 3. Block everything else (implicit, but be explicit)
IPv4 * * * MGMT net * → DENY — "MGMT: Block all inbound"
Management is simple — full outbound access, no inbound from other VLANs. Admins initiate connections to infrastructure; infrastructure never reaches back.
Servers VLAN
# SERVERS Interface Rules
#
# 1. Allow Servers → Servers (internal communication)
IPv4 * SERVERS net * SERVERS net * → ALLOW — "SERVERS: Inter-server communication"
#
# 2. Allow Servers → Internet (updates, API calls)
IPv4 * SERVERS net * !RFC1918 * → ALLOW — "SERVERS: Internet access"
#
# 3. Allow Services → Servers (reverse proxy backends)
IPv4 TCP SERVICES net * SERVERS net 80,443,8080 → ALLOW — "SERVICES: Reverse proxy to backends"
#
# 4. Block everything else
IPv4 * * * SERVERS net * → DENY — "SERVERS: Block all other inbound"
Key rule: SERVERS → !RFC1918 allows internet access but blocks access to any other internal VLAN. Servers can reach the internet for updates but cannot reach IoT, Guest, or Management.
IoT VLAN (Low Trust)
# IOT Interface Rules — MOST RESTRICTIVE
#
# 1. Allow IoT → pfSense DNS
IPv4 TCP/UDP IOT net * IOT address 53 → ALLOW — "IOT: DNS to pfSense"
#
# 2. Allow IoT → pfSense NTP
IPv4 UDP IOT net * IOT address 123 → ALLOW — "IOT: NTP to pfSense"
#
# 3. Allow specific IoT → Server API (e.g., Home Assistant)
IPv4 TCP IOT net * 10.0.20.50 8123 → ALLOW — "IOT: Home Assistant API"
#
# 4. Allow IoT → Internet (firmware, cloud APIs)
IPv4 * IOT net * !RFC1918 * → ALLOW — "IOT: Internet access"
#
# 5. Block everything else
IPv4 * * * IOT net * → DENY — "IOT: Block all other inbound"
The IoT rules are surgical — only DNS, NTP, one specific API endpoint, and internet. This is the most important VLAN to lock down because IoT devices are the most likely to be compromised.
Pro tip: Use aliases in pfSense for the IoT API rules. Create an alias IoT_Allowed_Services with the specific server IPs and ports IoT devices need. This makes it easy to add new devices without creating new rules.
Guest VLAN (No Trust)
# GUEST Interface Rules — TOTAL ISOLATION
#
# 1. Allow Guest → Internet only
IPv4 * GUEST net * !RFC1918 * → ALLOW — "GUEST: Internet only"
#
# 2. Allow Guest → pfSense DNS (DHCP-assigned)
IPv4 TCP/UDP GUEST net * GUEST address 53 → ALLOW — "GUEST: DNS"
#
# 3. Block everything else
IPv4 * * * GUEST net * → DENY — "GUEST: Complete isolation"
Guests get internet. Nothing else. This is the simplest and most important rule set.
Services VLAN (Exposed Services)
# SERVICES Interface Rules
#
# 1. Allow Services → Servers (reverse proxy backends)
IPv4 TCP SERVICES net * SERVERS net 80,443,8080,8123 → ALLOW — "SERVICES: Proxy to backends"
#
# 2. Allow Services → Internet (cert renewal, API calls)
IPv4 * SERVICES net * !RFC1918 * → ALLOW — "SERVICES: Internet access"
#
# 3. Block everything else
IPv4 * * * SERVICES net * → DENY — "SERVICES: Block all other inbound"
Services VLAN is the DMZ equivalent. It can reach backends on specific ports and the internet for Let's Encrypt/certbot renewals. It cannot reach management, IoT, or guest.
Advanced: pfSense Aliases for Zero-Trust Maintenance
One of the most underused features in pfSense is aliases — named groups of networks, hosts, or ports that make firewall rules readable and maintainable.
Firewall → Aliases:
Name: MGMT_Net Type: Host(s) Value: 10.0.10.0/24
Name: SERVERS_Net Type: Host(s) Value: 10.0.20.0/24
Name: IOT_Net Type: Host(s) Value: 10.0.30.0/24
Name: GUEST_Net Type: Host(s) Value: 10.0.40.0/24
Name: SERVICES_Net Type: Host(s) Value: 10.0.50.0/24
Name: RFC1918 Type: Network Value: 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16
Name: IoT_API_Targets Type: Host(s) Value: 10.0.20.50 (Home Assistant)
Name: Web_Ports Type: Port(s) Value: 80, 443, 8080
Name: IoT_Allowed Type: Port(s) Value: 8123, 1883, 5353
Now your rules use human-readable names:
DENY IOT_Net → RFC1918 — * — "IOT: Block internal access"
ALLOW IOT_Net → IoT_API_Targets → IoT_Allowed — "IOT: Allowed services only"
When you add a new IoT device that needs to reach a different service, you update the alias — not the rule. This prevents rule sprawl, which is the #1 way zero-trust degrades over time.
Verification: Proving Your Segmentation Works
Setting up rules isn't enough. You need to verify they work. Here's how:
Test 1: IoT Cannot Reach Management
From an IoT device (or a laptop plugged into an IoT port):
# Should FAIL — blocked by firewall
nmap -p 22 10.0.10.1 # pfSense SSH
nmap -p 443 10.0.10.1 # pfSense WebUI
nmap -p 8006 10.0.10.5 # Proxmox WebUI
# Should SUCCEED — allowed
ping 1.1.1.1 # Internet
dig @10.0.30.1 example.com # DNS
Test 2: Guest Cannot Reach Any Internal Host
From a guest device:
# All should FAIL
ping 10.0.10.1 # Management
ping 10.0.20.1 # Servers
ping 10.0.30.1 # IoT
nmap 10.0.20.0/24 # Scan entire server VLAN
# Should SUCCEED
ping 1.1.1.1 # Internet
Test 3: Servers Cannot Reach Management
From a server:
# Should FAIL
ssh admin@10.0.10.1 # pfSense
curl https://10.0.10.5:8006 # Proxmox
# Should SUCCEED
ping 10.0.20.1 # Servers gateway
curl https://example.com # Internet
Test 4: pfSense Firewall Logs
Status → System Logs → Firewall:
Watch for denied packets between VLANs. If you see unexpected allowed traffic, your rules are wrong. If you see denied traffic that should be allowed, check your alias definitions.
Pro tip: Enable Log packets that are handled by this rule on every DENY rule. This gives you a complete audit trail of every attempted cross-VLAN connection.
WiFi Considerations
If you're running WiFi (and you should for IoT/mobile), the AP must support multiple SSIDs mapped to VLANs.
UniFi AP VLAN Configuration
SSID: "CommsNet-Home" → VLAN 20 (Servers/Trusted devices)
SSID: "CommsNet-IoT" → VLAN 30 (IoT only)
SSID: "CommsNet-Guest" → VLAN 40 (Guest, rate-limited)
Each SSID gets its own DHCP scope from pfSense, its own firewall rules, and complete L2 isolation. The AP tags frames with the appropriate VLAN ID; pfSense routes and enforces policy.
WiFi-Specific Firewall Additions
# Rate limit Guest WiFi
IPv4 * GUEST net * * * → ALLOW — "GUEST: Rate limited"
↑ Limit: 10 Mbps down, 5 Mbps up per client
↑ Connection limit: 100 concurrent per /32
pfSense traffic shaping (limiter queues) can enforce per-client bandwidth caps on guest and IoT VLANs. This prevents one guest device from consuming your entire upstream.
Monitoring and Alerting
Zero-trust without monitoring is just wishful thinking. You need to know when segmentation fails.
pfSense Integration with Zabbix/Grafana
Install the pfSense Zabbix Agent package:
Package Manager → Available Packages → pfSense-zabbix-agent
Monitor these key metrics:
| Metric | What It Tells You | Alert Threshold |
|---|---|---|
| Firewall deny rate | How many cross-VLAN attempts blocked | Sudden spike = scanning/recon |
| Interface traffic per VLAN | Normal traffic baseline | IoT VLAN talking to server VLAN = breach |
| DHCP lease count per VLAN | Device count per segment | New device on Management VLAN = investigate |
| State table utilization | Active connections | >80% = possible flood or compromised host |
| pfSense CPU/memory | Router health | >80% sustained = capacity issue |
Suricata IDS on pfSense
Enable Suricata on each VLAN interface for deep packet inspection:
Services → Suricata → Interfaces → Add
Interface: VLAN_30 (IoT)
Mode: IPS (Inline Prevention)
Block offenders: Yes
Alert only on new threats: Yes
Suricata on the IoT VLAN catches:
- IoT devices phoning home to unexpected IPs
- Malware C2 beacon patterns
- Known exploit signatures targeting IoT firmware
Common Mistakes and Fixes
Mistake 1: Forgetting to Disable VLAN 1
VLAN 1 is the default on every switch. Every port is in it. If you don't explicitly disable it, you have a shadow flat network running alongside your segmented one.
Fix: Create a VLAN 99 as the native VLAN on all trunk ports and move all unused ports to a dead VLAN.
! Move all unused ports to dead VLAN
interface range GigabitEthernet0/22 - 24
switchport mode access
switchport access vlan 99
shutdown
Mistake 2: Over-Allowing on Trunk Ports
switchport trunk allowed vlan all is lazy and dangerous. Only allow the VLANs that need to traverse each trunk.
Fix:
interface GigabitEthernet0/21
switchport trunk allowed vlan 10,20,30,40,50
! NOT: switchport trunk allowed vlan all
Mistake 3: pfSense Floating Rules Bypassing Interface Rules
Floating rules in pfSense apply globally and can bypass per-interface rules. If you use floating rules, make sure they don't accidentally allow cross-VLAN traffic.
Fix: Avoid floating rules for inter-VLAN policies. Use interface-specific rules. Use floating rules only for traffic shaping or QoS.
Mistake 4: No Logging on Deny Rules
If you don't log denied packets, you have no way to detect reconnaissance, failed intrusion attempts, or misconfigured devices.
Fix: Enable logging on every DENY rule. Set up a syslog server to aggregate and analyze firewall logs.
Cost Summary
| Item | Cost | Notes |
|---|---|---|
| Cisco 2960G (used) | $50 | eBay, 24-port managed |
| pfSense (VM on Proxmox) | $0 | Already have hardware |
| Cat6 patch cables | $15 | Monoprice 10-pack |
| UniFi AP AC Lite (used) | $40 | Multi-SSID VLAN support |
| Total | $105 | One-time cost |
No subscriptions. No per-device licensing. No cloud dependencies. This is infrastructure you own, understand, and control.
What's Next?
This article covers L2/L3 segmentation. In the next article in this series, we'll add:
- WireGuard VPN for remote management VLAN access (never expose pfSense to the internet)
- Cilium eBPF policies for micro-segmentation within the server VLAN (container-to-container)
- pfSense CARP for high-availability firewall failover
- Automated compliance checks — scripts that verify your firewall rules match your zero-trust policy
Key Takeaways
- Flat networks are the enemy — one compromised device becomes a pivot to everything
- VLANs + pfSense rules = zero-trust at homelab scale — no enterprise license required
- Deny by default, allow by exception — every inter-VLAN flow must be justified
- IoT is your biggest risk — isolate it to DNS + NTP + one API endpoint
- Guest gets internet only — no exceptions, no "just this once"
- Log every deny — visibility is how you prove zero-trust works
- Aliases keep rules maintainable — rule sprawl is how zero-trust dies
- Test your segmentation — if you haven't verified it, it's probably broken
CommsNet — Building infrastructure that respects your privacy and your intelligence.
Follow on Medium and Dev.to for more homelab, networking, and self-hosting content.









