firewall: add default-policy to policy config v2 - #15944
Conversation
AppProtoToString(ALPROTO_HTTP1) returns "http", so an HTTP/1 policy had to be written as `http:` while its rule hooks were already spelled `http1:`. Use the same name in both places. Ticket: 8712
The policy config was a flat map mixing packet hooks and app-layer
protocols: `packet-filter` next to `dns`. There was no node that meant
"the packet hooks" or "the app-layer hooks", so a setting could not be
scoped to one group.
Move each group under its own node:
packet-filter -> packet.filter
packet-pre-flow -> packet.pre-flow
packet-pre-stream -> packet.pre-stream
<proto>.<hook> -> app.<proto>.<hook>
Ticket: 8712
Every hook has a built-in default policy, but expressing anything other
than the built-in meant naming each hook explicitly. Add a
`default-policy` setting that covers all hooks below it, so unlisted
hooks still get a policy. For any hook the most specific setting present
wins:
app.<proto>.<sub state>.<hook>
app.<proto>.<sub state>.default-policy
app.<proto>.default-policy
app.default-policy
default-policy
built-in
The packet hooks follow the same pattern under `packet`.
Resolution moves into ResolveFirewallPolicy(), which walks the candidate
paths most-specific-first and stops at the first one that is configured.
A path that is present but empty is now a startup error rather than being
treated as unset.
DoParseAppSubStatePolicy() collapses into DoParseAppPolicy() as a sub state
hook only differs by an extra path segment. Path assembly and hook-name
normalisation move to helpers now that both are needed in more places.
Ticket: 8712
Not every action scope means something at every hook: `tx` is app-layer only, `packet` is packet only. While a policy had to be written per hook this was self-evident, but a `default-policy` reaches hooks the user never named, so a single global setting can now arrive somewhere its scope makes no sense. Validate the resolved scope against the class of hook it is being applied to and fail at startup if it does not fit, naming the config path and the scopes that would be accepted there. A global `accept:tx` is now a startup error instead of being applied silently at the packet hooks. Ticket: 8712
There was a problem hiding this comment.
Pull request overview
This PR updates Suricata’s firewall policy configuration (v2) to support hierarchical default-policy inheritance with “most specific wins”, restructures policy keys into packet.* and app.* namespaces, and adds startup-time validation to reject incompatible action scopes reaching a given hook class.
Changes:
- Introduce hierarchical
default-policyresolution for firewall hooks with packet/app subtree scoping. - Validate action scopes against the hook class (packet vs app) and emit clearer error hints on invalid scopes.
- Update example configuration and firewall user guide docs to reflect the new
packet/apppolicy layout.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| suricata.yaml.in | Updates the example policy config layout and documents default-policy inheritance behavior. |
| src/detect.h | Adds a small enum to classify firewall policy hook classes (packet vs app) for validation logic. |
| src/detect-parse.c | Implements multi-level policy resolution and scope validation; refactors packet/app policy loading accordingly. |
| doc/userguide/firewall/firewall-example.rst | Updates the HTTP example to the new firewall.policies.app.http1.* structure. |
| doc/userguide/firewall/firewall-design.rst | Documents the new defaults structure, precedence rules, and scope-validation behavior. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #15944 +/- ##
==========================================
- Coverage 83.03% 83.00% -0.03%
==========================================
Files 1003 1003
Lines 276582 276602 +20
==========================================
- Hits 229647 229602 -45
- Misses 46935 47000 +65
Flags with carried forward coverage won't be shown. Click here to find out more. 🚀 New features to boost your workflow:
|
|
WARNING:
Pipeline = 32727 |
|
follow-up in #15950 |
Follow-up of #15942
Add a
default-policysetting that applies to all hooks below it. For any hook the most specific setting present wins.The flat layout had no way to express a default covering only the packet hooks or only the app hooks, so both move under their own node:
packet-filterbecomespacket.filterand<proto>becomesapp.<proto>.Action scopes are now validated against the hook they reach. A global
accept:txarriving at a packet hook is a startup error instead of being applied silently.Link to ticket: https://redmine.openinfosecfoundation.org/issues/8712
Describe changes:
SV_BRANCH=OISF/suricata-verify#3252
To consider:
As we changed the config structure for default policies, we can consider adding upgrade checks.
But since the firewall mode is experimental in 8, I avoided any conversion checks from the previous versions to keep the code simpler.