A rule can be correct and still never be reached. That is not a bug; it is the evaluation model. Every firewall reads its policy from the top, stops at the first rule that matches, and applies that rule's action. Everything below the match is irrelevant to that packet.

Most "the firewall is broken" tickets are a rule that is correct, well-written, and below something broader.

Two models, one idea

Model What it matches Where you see it
Interface ACL Source/destination IP, port, protocol, direction Routers, older firewalls
Zone-based Source zone, destination zone, then addresses UniFi Network 9+, modern NGFWs

Zone-based policy is the better abstraction because it describes intent: "students may reach the internet, not the servers." You write one rule for the zone pair instead of one per subnet.

But the abstraction has a consequence that surprises people: intra-zone traffic is allowed by default. If 98 networks all sit in one Internal zone, the predefined rule that permits Internal → Internal applies to all of them, and your carefully written inter-zone rules never see that traffic.

That is exactly the situation in the district today: one Internal zone holding 98 networks, and a predefined allow-all between them carrying more than 100 billion hits. Every segmentation rule written inside that zone is decorative.

Zones are the trust boundary; rules are the detail

Adding rules to a flat zone does not segment it. The move from one Internal zone to Student, Staff, Guest, IoT, and Infrastructure zones is what creates a boundary. Rules then describe what may cross it. If you skip the zone work, you are writing policy for traffic that never reaches it.

First match wins

Consider this policy for Internal → WAN:

# Name Destination Port Action Hits
1 3CX HTTPS Any 443 Allow 3.0 B
2 Block Powerwash domains Group 443 Block 10.5 M
3 Allow Securly Group 443 Allow 240 K
4 Allow All Traffic (predefined) Any Any Allow 2.9 B

Rule 2 is a block for a domain group. It is below rule 1, which permits any destination on 443. Every packet rule 2 was written to block matched rule 1 first and was allowed. The block rule has 10 million hits only because some traffic reached it through other ports or paths.

The fix is not to rewrite rule 2. The fix is to make rule 1 specific — destination 23.90.72.193, the 3CX host — so that the packets rule 2 cares about fall through to it.

Evaluation stops at the first match: a broad rule above a specific one hides it.

Statefulness: one rule, both directions

Firewall rules are unidirectional in what they permit, but stateful in what they allow back. A rule permitting Internal → WAN on 443 also permits the return packets, because the firewall remembers the flow.

Consequences:

  • You do not need a rule for WAN → Internal for replies.
  • You do need state to be consistent: if the return path goes through a different device, that device has no state and drops the reply.
  • UDP is "stateful" on a timer. A reply arriving after the timeout is dropped and looks like packet loss.

Predefined rules are still rules

Every zone-based firewall ships with predefined entries: allow intra-zone, allow return traffic, block IoT to internal, and a final allow or deny depending on vendor. They sit in the same list, with the same evaluation order, and they can shadow your custom policy.

Read them before writing anything. In UniFi the predefined rules appear in the same policy table as custom ones, and the final Allow All Traffic at index 2147483647 is why a scoped rule at index 10004 changes nothing for general browsing.

Worked example: writing one rule correctly

Goal: students may reach the internet, and nothing else except DNS and printing.

# Source Destination Service Action
1 Student zone Infrastructure DNS 53, NTP 123 Allow
2 Student zone Printers 9100, 631 Allow
3 Student zone WAN Any Allow
4 Student zone Any Any Block

Order matters: the specific allows are above the general block. If rule 4 were first, nothing would work. If rule 3 were first, rules 1 and 2 would never be reached but would appear to work by accident — an important distinction when you later tighten rule 3.

What breaks in production

  • Shadowing. A broad rule above a specific one. The specific rule's hit counter stays at zero, which is the tell.
  • An allow-any at the top "temporarily," which then lives for three years.
  • Rules written for the wrong zone pair. The rule exists, the traffic never matches it because the source network is still in Internal.
  • No implicit deny. Some platforms end with allow-all; if you assume deny, you will over-permit.
  • Duplicate rules with different actions. The first one wins and the second is a mystery during an audit.

Checklist

  1. You know every predefined rule in the path and what it permits.
  2. No custom rule sits below a broader rule it depends on being reached.
  3. Intra-zone traffic is understood, not assumed to be restricted.
  4. Every allow has a matching explicit deny for the rest of that zone pair.
  5. Each rule has a name that states intent, not protocol.

Next

Order decides whether a rule is reached. State decides whether the reply comes back. Continue with State Tables and Connection Tracking.

  • Firewall
  • Zones
  • Policy
  • UniFi