← Back to Wiki
Networking / Security

UniFi VLAN Isolation Firewall Rules Without Locking Yourself Out

Putting a device on its own VLAN feels like isolation. On most routers, by default, it is not. Here is how to check whether a VLAN has the isolation you assume it does, how to fix it properly, and a real gotcha that silently breaks the one direction you meant to keep working.

Share on X

The VLAN tag alone doesn't isolate anything

Modern routers with zone-based firewalls group networks into zones. UniFi, pfSense, OPNsense and similar all work this way. By default every "trusted" network you create lands in the same zone as everything else, with a standing rule permitting all traffic between zone members. Create a new VLAN for a specific purpose and it is not automatically isolated. A media network, a smart-home segment, a guest network you upgraded from basic. Check the zone assignment and the rules governing that zone pair before you assume a VLAN is isolated because it has its own subnet.

BE WARNED: do not assume. Check. A real case. A VLAN built to sandbox a group of lower-trust services shared a firewall zone with the main management network, with a blanket "allow everything within this zone" rule already in place. The VLAN boundary existed at Layer 2. Zero traffic filtering happened at Layer 3 or 4. Pull up your router's zone matrix or firewall rule list and look at what is configured for that zone pair. The VLAN's existence is no proof of isolation.
UniFi zone matrix showing Allow All, Allow Return, and Block All cells between zones
UniFi Network → Settings → Security → Zones, zone matrix at the bottom. Each cell is the live policy for that source and destination zone pair. This is what to check before assuming a VLAN is isolated.

Adding the isolation: one rule, correctly ordered

Most zone-based firewalls evaluate rules in order and stop at the first match. If a rule permitting everything already exists, an "Allow All" within a zone, a new block rule added after it is inert. Traffic hits the allow rule first and never reaches your block. The fix has two parts:

Scope the block rule's source specifically rather than "any" and traffic in the other direction is unaffected. Your management network reaching into the isolated VLAN for admin access, monitoring or a reverse proxy never matches the block rule's source condition at all.

The gotcha that will break the direction you meant to keep

BE WARNED: a block rule scoped only by source and destination network eats return traffic too. When your management network initiates a connection into the "isolated" VLAN, the response packets have the isolated VLAN as their source. That covers a reverse proxy fetching from a backend there, a monitoring agent polling it, a plain request from an admin workstation. A block rule matching "source = isolated network, destination = my zone", with connection state left at its default of all traffic, matches those response packets as readily as a genuine new connection attempt. It drops them. So the direction you explicitly wanted to keep working, management into the isolated VLAN, breaks too. The replies never make it back.

Fix: scope the block rule's connection-state matching to new connections only. Sometimes labeled "New" plus "Invalid", excluding "Established" and "Related". That blocks the isolated VLAN from initiating anything into your other networks and leaves already-permitted connections' return traffic untouched, whichever network technically owns the reply packets.

A second gotcha: your new block rule can shadow something added later, by someone else

BE WARNED: a broad block rule can silently shadow an unrelated rule added later, for a completely different purpose. It is not only a risk against the rules that existed when you wrote it. A real case. A block rule isolating one VLAN went in first. Later, a specific "allow this VLAN to reach one particular service" rule was added for something unrelated, a shared file server. It landed below the existing block in evaluation order. The firewall stops at first match, so the broad block caught the traffic every time. The new rule was dead on arrival the moment it was created, with no error on either rule.

Fix: whenever you add a specific-purpose allow rule to a zone pair that already has a block rule in it, check its position against every existing rule in that pair. Not just whether it is configured correctly on its own. The order that works is specific carve-outs first, broad isolation blocks next, broad catch-all allows last.

Lesson: when a specific-purpose rule does not work despite looking correct in isolation, check whether a broader block in the same zone pair now sits above it. Especially if that block was added by someone else, or in an earlier session, for an unrelated reason. It is easy to test your own new rule in isolation and never notice it is shadowed.

Verifying it actually worked

Do not trust ping alone in either direction. On some routers ICMP is deprioritized or filtered independently of your actual rule, which gives you a false failure or a false success. Test with a real connection instead:

# From the network that should still have access:
curl -s -o /dev/null -w '%{http_code}\n' http://<isolated-vlan-host>:<port>/

# From inside the isolated network, toward somewhere that should now be blocked:
timeout 5 bash -c "echo > /dev/tcp/<other-network-host>/<port>" && echo REACHED || echo BLOCKED

Confirm both directions explicitly. The network you isolated can no longer reach elsewhere. And everything that depended on reaching into it still works exactly as before. Admin access, reverse proxies, monitoring.