Roman Dmytriv
← All writing Firewall hygiene

Finding shadowed, redundant, and unreachable firewall rules

Every long-lived firewall accumulates rules that never fire. Some are harmless bloat; one kind quietly undoes your security policy. How to find each — and why you can't do it with a text diff.

Roman Dmytriv~7 minRule hygiene

Every firewall that's been in production for a few years accumulates rules that never fire. Some are harmless bloat. Others are actively dangerous — a permissive rule sitting above a restrictive one means the restriction never applies, and nobody notices because the config looks fine. Here's how to tell the categories apart and find each one.

Four things people call the same thing

These get used interchangeably and they shouldn't. Firewalls evaluate top-down, first match wins, so all of this is about a rule's position relative to the rules above it.

Why you can't find these with a text diff

This is the part that makes it hard by hand. Shadowing isn't about rules that look alike — it's about whether one rule's match set is a superset of another's. And rules reference object groups, not raw addresses. Two rules can share zero object names and still shadow each other, because the groups resolve to overlapping IP ranges.

So the only reliable comparison is to expand every rule to the actual sets it matches — resolve address groups to IP ranges, service groups to protocol/port sets — and compare those sets across the full tuple: source zone, source address, destination zone, destination address, service/application, and action.

The shadowing test

Rule B (lower) is shadowed by an earlier rule A when, with objects expanded: A's sources ⊇ B's sources, A's destinations ⊇ B's destinations, A's services ⊇ B's services, the zones line up, and A's action applies to the traffic. If all hold, B never sees a packet.

The shadow that changes your security posture

Most shadowed rules are just clutter. The dangerous case is an action conflict: a broad allow sitting above a specific deny.

Say someone added a permissive allow any → any for a troubleshooting session and never removed it. Every deny rule below it is now shadowed — the traffic you meant to block is allowed, because the allow matched first. The config still contains your deny rules; they just never execute. This is the finding that turns a hygiene exercise into a security one, and it's invisible unless you're checking superset relationships against action.

What hit counters do and don't tell you

PAN-OS tracks rule hit count and last-hit time, and it's genuinely useful — a rule with zero hits over a long, representative window is a candidate for removal. But hit count is a blunt instrument:

So use both: logic to find rules that can't match (shadowed, unreachable — safe to fix on structure alone), and hit counters to flag rules that can match but don't (unused — investigate before removing).

A practical pass

A firewall policy is one of the few places where "we never remove anything" is a security problem, not just a tidiness one. The rules that never fire are exactly the ones nobody's looked at — which is why that's where the surprises live.

Written by Roman Dmytriv — network security engineer (CISSP), two decades securing and modernizing enterprise networks. More writing at blog.dmytriv.com, and I'm on LinkedIn.