UniFi's zone-based firewall is the best thing to happen to the platform and the easiest to misread. The interface shows a tidy list of policies; the behavior depends on two things that are not in that list — zone membership and the predefined rules at the bottom.
The model
Zone A (many networks) ──policy──▶ Zone B (many networks)
A zone is a group of networks that share a trust level. A policy is a rule between two zones. Traffic inside a zone is governed by that zone's intra-zone policy, which is usually allow all.
That last sentence is the whole game. If 98 networks sit in one Internal zone, the predefined allow between Internal and itself means every network can reach every other network, and any policy you write between them is never evaluated.
Reading the table
Each policy has:
| Field | Meaning |
|---|---|
| Index | Evaluation order — lower runs first |
| Name | Human label |
| Source | Zone, network, address, or group |
| Destination | Zone, network, address, or group |
| Service | Port/protocol or a predefined service |
| Action | Allow, block, reject |
| Hits | How many packets matched |
The table is evaluated top to bottom, first match wins, and the predefined policies sit at the end. The
final predefined Allow All Traffic at the highest index is why a rule you place above it behaves
differently from one you place below.
The legacy endpoint returns an empty list
/rest/firewallrule returns [] on Network 9. The real table is
/proxy/network/v2/api/site/default/firewall-policies. If a script or a support engineer tells you
there are no rules, they are reading the wrong endpoint. This has caused a real audit to conclude a
firewall was open when it was not, and vice versa.
The two settings that decide everything
1. Zone membership. A network in Internal is covered by intra-zone allow. Moving it to Student is the only thing that makes student policy apply.
2. Policy order. A specific rule below a broad allow never runs. The hit counter is the proof: a rule with billions of hits above your block is doing the blocking.
Custom policy fields that matter
- Source / destination can be a whole zone, one network, an address, or an address group. Prefer groups for services with several endpoints (the enrollment domains, the NVR pair).
- Service is a port or a predefined service. Custom port ranges exist; use them rather than "any."
- Logging is per policy on some builds. Turn it on for denies you care about; leave it off for high-volume allows or the log becomes noise.
- Before/after ordering is set by index, not by drag order in every build. After saving, reload and confirm the index.
Patterns worth copying
| Purpose | Source | Destination | Service | Action |
|---|---|---|---|---|
| Guest internet | Guest | WAN | Any | Allow |
| Guest DNS | Guest | Infrastructure | 53 | Allow |
| Guest isolation | Guest | Any internal | Any | Block |
| Student DNS | Student | Infrastructure | 53, 123 | Allow |
| Student internet | Student | WAN | Any | Allow |
| Student to servers | Student | Infrastructure | Any | Block |
| IoT vendor cloud | IoT | WAN | 443 | Allow |
| IoT internal | IoT | Any internal | Any | Block |
The block rows are what make the allow rows meaningful. A zone with only allows is a suggestion.
Worked example: scoping the 3CX rule
The rule 3CX HTTPS permits any Internal source to any WAN destination on 443 and carries three
billion hits. Intended: only the PBX at 23.90.72.193.
- Edit the policy; change destination from
Anyto the address23.90.72.193. - Leave the service and index unchanged.
- Confirm the predefined allow-all is still below it.
- Test browsing from staff and student VLANs, and PBX registration.
- Watch the hit count for a day: it should grow only with PBX traffic.
Because the broad rule remains below, a mistake is a revert, not an outage. That is the correct way to tighten a rule in a live network.
What breaks in production
- Intra-zone allow. The default that makes segmentation optional.
- Moving a network without its allow rules. The move is instant and retroactive.
- Assuming first-match from the UI order, when the index says otherwise.
- Policies for the wrong zone pair. The rule exists; the traffic never matches it.
- Predefined rules disabled without understanding — usually the return-traffic rule, which breaks every stateful flow.
Checklist
- Every network's zone membership is intentional.
- Intra-zone policy is understood per zone, not assumed.
- No custom allow sits below a broader rule it depends on.
- Every zone pair ends with an explicit deny.
- Hit counters are reviewed after each change.
- Audits read the v2 endpoint, not the legacy one.
Next
Policy governs the wire. Continue with Wi-Fi and PPSK for the wireless side of the same design.