pfSenseLab
A router and switch on separate platforms connect via shield icons to a server, NAS, laptop, and smart home devices like a bulb and camera, showing segmented network zones.
Networking

pfSense VLAN Setup for Homelab: Design, Rules, and Tests

pfSense VLAN setup for homelab: trunk layout, a four-VLAN plan, firewall rules in apply order, mDNS reflection, DNS pinning, and the tests that prove it.

By pfSenseLab Editorial · · 6 min read

Most guides to pfsense vlan setup for homelab use stop at “create the VLAN, assign it, add a pass-any rule”. That leaves you with four subnets and zero isolation, because pfSense evaluates rules per interface, first match wins, and a pass-any rule at the top of the IoT tab hands traffic to your NAS before any block rule is read. This post is the design layer under the click-by-click pfSense VLAN configuration guide: topology, address plan, rule order, discovery, and the tests that prove it.

The goal

Four segments on one pfSense box and one 802.1Q switch: trusted clients, homelab servers, IoT, guests. Trusted reaches everything. Servers reach the internet and answer trusted. IoT and guest get internet plus DNS from pfSense and nothing else. The pfSense GUI and the switch are managed from trusted only.

Topology

Router-on-a-stick: igc0 on WAN, igc1 as the LAN trunk. Netgate’s VLAN documentation lists the Intel em(4), igb(4) and ix(4) families as having hardware VLAN tagging and warns that some Realtek rl(4) parts “will not accept 802.1Q tagged frames at all”. The tag adds 4 bytes, so a tagged frame reaches 1522 bytes and a NIC without long-frame support has to run a lower MTU. The hardware requirements guide covers which boxes ship Intel.

ISP modem ── igc0 (WAN)
pfSense igc1 ── trunk, tagged 10,20,30,40 ── switch port 1  (USW-Pro-24-PoE, CRS328-24P, any 802.1Q switch)
switch port 2 ── trunk, tagged 10,30,40 ─── AP  (SSID Home→10, IoT→30, Guest→40)
switch ports 3-8 ── access, PVID 20 ──────── Proxmox host, NAS
switch ports 9-24 ── access, PVID 10 ─────── desks

Stay off VLAN 1. Netgate’s VLANs and Security page notes switches send STP, VTP and CDP untagged over the native VLAN and says to treat VLAN 1 like a default-allow firewall policy: you have 2 through 4094 to pick from. Set the trunk PVID to an unused ID such as 999 so an untagged frame from a misconfigured port lands nowhere. If you want a break-glass path, assign the untagged parent igc1 as MGMT with exactly one switch access port.

Inter-VLAN traffic crosses the trunk twice, in on one tag and out on another, so every trusted-to-NAS flow shares that link with everything else. A 2.5GbE or 10GbE trunk is the fix; putting the workstation and NAS on the same VLAN is the cheap one.

If pfSense is a VM, the Proxmox network docs describe the VLAN-aware bridge (bridge-vlan-aware yes, bridge-vids 2-4094); leave the VM NIC’s VLAN tag empty so the tags reach vtnet1 and create the VLANs inside pfSense. The Proxmox bridge and VLAN guide covers the host side.

VLAN plan

VLANNameCIDRGatewayDHCP rangeInter-VLAN policy
10TRUSTED10.10.10.0/2410.10.10.1.100 to .199any
20SERVERS10.10.20.0/2410.10.20.1static mappings; .200 to .220 for new boxesinternet only, answers TRUSTED
30IOT10.10.30.0/2410.10.30.1.100 to .250internet, pfSense DNS and NTP only
40GUEST10.10.40.0/2410.10.40.1.100 to .250internet and pfSense DNS only

Third octet equals VLAN ID; that one convention removes most “which subnet is this” mistakes. All three RFC 1918 blocks still go in one alias, because a 192.168.x device will turn up eventually.

Per VLAN: Interfaces > Assignments > VLANs, parent igc1, tag, description; then assign, enable, static IPv4 /24. Leave “Block private networks” and “Block bogon networks” unchecked on every VLAN interface. Netgate’s interface docs say the first is “typically only desirable on WAN type interfaces” and the second “can potentially block required local traffic”; on GUEST it blocks the guests themselves. Enable DHCP per interface with static mappings for anything a rule will name. ISC DHCP is deprecated; the Kea switch is under System > Advanced > Networking.

IPv6 needs the same per-VLAN plan. Netgate’s IPv6 Configuration Types describes both options: Track Interface assigns each VLAN a /64 from a delegated WAN prefix using a distinct Prefix ID, while Static IPv6 assigns an address from a unique routed prefix. Equivalent IPv6 firewall rules are required because the IPv4 RFC1918 alias does not match IPv6 traffic.

Firewall rules

Aliases first: RFC1918 (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16) and MGMT_PORTS (22, 443).

Netgate’s rule methodology is the whole game: rules apply “always in the inbound direction on that interface”, processed until a match, stateful, and “outbound rules are never required”. Unmatched traffic is silently dropped. A NAS replying to a trusted client therefore needs no rule on SERVERS; the state created on TRUSTED carries the reply.

IOT tab, in apply order:

  1. Pass, TCP/UDP, source IOT net, destination IOT address, port 53.
  2. Pass, UDP, source IOT net, destination IOT address, port 123.
  3. Pass, ICMP echo request, source IOT net, destination IOT address.
  4. Reject, any, source IOT net, destination “This Firewall (self)”.
  5. Block, any, source IOT net, destination RFC1918.
  6. Pass, any, source IOT net, destination any.

Rule 4 matches every address on every pfSense interface, so IoT cannot reach the GUI via 10.10.10.1 or the WAN IP; Netgate’s management-restriction recipe says “reject is preferred on internal networks”. Rules 1 to 3 use “IOT address” rather than “This Firewall” so the only pfSense IP IoT can talk to is its own gateway.

Shadowing, in the order people hit it: rule 6 above rule 5 is a flat network with extra configuration. Rule 4 above rule 1 kills DNS. A floating rule with Quick set, or a rule on an Interface Group tab, runs before any of these; Netgate’s troubleshooting page is explicit that once one matches, “a block rule on an interface would have no chance to match”. A RESTRICTED group holding rules 4 and 5 for IOT and GUEST is tidy, but every per-VLAN exception then has to live in the group tab too.

GUEST: the same list minus rule 2. SERVERS: rules 1, 2, 4, 5, 6, with narrow passes above rule 5 where a server must initiate into IoT (a Home Assistant VM reaching a hub). TRUSTED: pass any, plus an explicit pass to “This Firewall” on MGMT_PORTS from an admin-hosts alias before you disable the anti-lockout rule.

Same troubleshooting page: an existing state is not cut off by a new block rule. After adding rule 5, reset states under Diagnostics > States, or the TV keeps talking to the NAS until its session times out.

DNS and discovery

Unbound’s access lists permit “networks residing on internal interfaces” by default, so every VLAN resolves against its gateway with no extra work. Devices hard-coded to 8.8.8.8 bypass that; Netgate’s DNS redirect recipe is a port forward on the interface with destination inverted, port 53, target 127.0.0.1, so “DNS requests from local clients to any external IP address will result in the query being answered by the firewall itself”. It cannot catch DNS over TLS or HTTPS; redirecting 853 helps with some clients.

mDNS is why IoT segmentation gets a bad name. RFC 6762 sends .local queries to 224.0.0.251 on UDP 5353 and defines the names as link-local, “meaningful only on the link where they originate”. A router does not forward them. The pfSense Avahi package fixes this by reflection: per the avahi-daemon.conf man page, enable-reflector makes the daemon “reflect incoming mDNS requests to all local network interfaces”. Allow TRUSTED and IOT, deny GUEST, and run exactly one reflector; two between the same networks loop.

Reflection only carries the advertisement. The unicast session that follows (Chromecast on TCP 8008/8009, AirPrint on 631) is opened from TRUSTED, which passes any, and the reply rides the state. You need a pass above the RFC1918 block only when the IoT device initiates. Enable IGMP snooping on the switch so multicast stops flooding every port, and leave pfSense’s IGMP proxy alone unless you need real multicast streams across VLANs. If the APs are UniFi, the SSID-to-VLAN mapping is the controller’s job; the UniFi VLAN setup guide covers that half.

Things to test before you call it done

From a laptop on the IoT SSID (10.10.30.x):

ping -c 3 10.10.30.1                   # gateway answers (rule 3)
ping -c 3 10.10.10.1                   # must fail (rule 4)
nc -vz -w 3 10.10.20.10 445            # NAS SMB, must fail (rule 5)
dig +short example.com @10.10.30.1     # answers (rule 1)
dig +short pfsense.home.arpa @8.8.8.8  # answers only if the DNS redirect works
curl -sI https://example.com | head -1 # 200 (rule 6)

From TRUSTED:

mtr -n -c 20 10.10.20.10               # one hop via 10.10.10.1, no loss
iperf3 -c 10.10.20.10 -P 4 -t 20       # inter-VLAN throughput across the trunk
avahi-browse -art | grep -i chromecast # reflected services from IOT

Then Diagnostics > States: filter on 10.10.30 and confirm nothing points at 10.10.10.0/24 or 10.10.20.0/24. Finally Status > System Logs > Firewall, where pfSense logs dropped traffic by default; a rule 5 hit from a bulb you never expected to see there is the first sign it is scanning your network.

Sources

  1. Netgate Docs: Virtual LANs (VLANs)
  2. Netgate Docs: VLANs and Security
  3. Interface Configuration
  4. DHCP
  5. IPv6 Configuration Types
  6. Netgate Docs: Firewall Rule Processing Order
  7. Netgate Docs: Restrict Access to the Management Interface
  8. Netgate Docs: Troubleshooting Firewall Rules
  9. Netgate Docs: Redirecting Client DNS Requests
  10. DNS Resolver Access Lists
  11. Avahi package
  12. RFC 6762: Multicast DNS
  13. RFC 1918: Address Allocation for Private Internets
  14. Proxmox VE Wiki: Network Configuration
  15. avahi-daemon.conf(5) man page
#pfsense #vlan #homelab #network-segmentation#iot #firewall-rules

Related