Reading a rulebase tells you what someone intended. Hit counters tell you what actually happens. The gap between those two numbers is the audit.
This is the method, applied to a real district firewall with 109 policies: 82 predefined, 27 custom, one Internal zone holding 98 networks, and counters in the billions.
The method
- Export the table with index, name, source, destination, service, action, and hits.
- Sort by hits. The top of that list is your actual policy; the bottom is your intent.
- Flag zero-hit rules. New rules are exempt; anything older than 30 days with zero hits is either shadowed or unnecessary.
- Check every broad allow for what sits beneath it. Any specific rule below an allow-any is unreachable.
- Map rules to zones. If most traffic is intra-zone, the rules are not the problem — the zones are.
- Write down three lists: remove, narrow, and redesign.
What the numbers showed
| Rule | Flow | Hits | Reading |
|---|---|---|---|
| Allow All Traffic (predefined) | Internal → Internal | 104.3 B | Every VLAN can reach every VLAN |
| Allow All Traffic (predefined) | Internal → WAN | 2.93 B | The edge permits everything |
| 3CX HTTPS | Internal → WAN, 443, any destination | 3.04 B | A host-specific rule permitting the internet |
| Allow DNS | Internal → WAN, 53, any destination | 23.6 M | Any resolver, including public ones |
| Block Powerwash from Other Domains | Domain group | 10.5 M | Real, and working |
Three conclusions follow directly from the counters:
- Segmentation does not exist. 104 billion hits on intra-zone allow means every rule written between VLANs was never in the path.
- The 3CX rule is an internet permit. Three billion hits for a rule intended for one host.
- DNS is unrestricted. 23 million queries to any resolver, which is the filtering bypass in network form.
Shadowing, concretely
For each allow-any in the table, list the specific rules below it:
10004 3CX HTTPS any -> any, 443 ALLOW 3.04 B
10005 Block Powerwash group, 443 BLOCK 10.5 M <- partially unreachable
10006 Allow Securly group, 443 ALLOW 240 K <- only non-443 traffic
...
2147483647 Allow All Traffic any -> any ALLOW 2.93 B
The Powerwash block still gets hits because some traffic uses other ports or arrives via a different path. It is working by accident, not by design. Narrowing rule 10004 to the 3CX address makes both rules behave as written.
The three lists
Remove. Rules with zero hits for 90 days whose service no longer exists. Disable first, delete after a week.
Narrow. Any allow with any destination on a specific port. Replace with the actual address or
group. This is where most of the security value is, and it costs nothing operationally because the
traffic continues to be permitted by the rule beneath.
Redesign. Zone membership. Moving Student, Guest, IoT, and Building Management out of Internal is a project, not a rule edit, and it is the only thing that makes the other 26 rules matter.
A quarterly cadence
| Step | Time | Output |
|---|---|---|
| Export and sort by hits | 10 min | Table with counts |
| Flag zero-hit and any-any rules | 20 min | Candidate lists |
| Verify top 10 rules against intent | 30 min | Confirmed or corrected |
| Update documentation | 20 min | Policy table matches reality |
| Record the review | 5 min | Date, reviewer, findings |
One hour a quarter, and the rulebase stops drifting.
Do not delete on hit count alone
A rule with zero hits may be a break-glass path used twice a year, or a rule whose traffic arrives after a zone move. Check ownership before removal, and disable rather than delete so the rollback is one click.
Worked example: narrowing without an outage
Goal: scope 3CX HTTPS from any-destination to 23.90.72.193.
- Confirm the destination address of the PBX.
- Confirm the rule below it (the predefined allow-all) still permits general browsing.
- Change the destination, leave the index and port unchanged.
- Test: browse from staff and student VLANs; confirm the PBX still registers.
- Watch the hit counter for 24 hours: it should grow only with PBX traffic.
- If browsing breaks, revert the destination — the change is one field.
Because the broad rule remains below, the worst case is a revert, not an outage.
What breaks in production
- Auditing by name. Rule names describe intent; counters describe behavior. Read both.
- Deleting the wrong rule. Disable for a week, then delete.
- Assuming zero hits means unused. Check whether a broad rule above it shadows it.
- Ignoring predefined rules. They are usually the largest counters in the table.
- Auditing once. A rulebase drifts continuously; the review has to be a cadence.
Checklist
- The exported table includes hits, and it is sorted.
- Every any-any allow has a written justification or a narrowing plan.
- Zero-hit rules older than 90 days are disabled, then removed.
- Zone membership is reviewed alongside the rules.
- The review is dated and stored with the policy documentation.
- A narrowing change has been tested with the broad rule still in place as a fallback.
Next
Policy is now measurable. The next series takes the same discipline to the outside world: VPNs and Remote Access.