firewall: T8446: Prevent chain with offload rule on local zone#5100
firewall: T8446: Prevent chain with offload rule on local zone#5100sarthurdev wants to merge 1 commit intovyos:currentfrom
Conversation
* Add warning when defining `offload-target` without setting action to `offload`
|
👍 |
|
CI integration ❌ failed! Details
|
There was a problem hiding this comment.
Pull request overview
This PR updates the firewall configuration validation to prevent nftables flow-offload rules from being used in contexts where zone-policy traffic involves the local-zone (which would result in invalid/unsafe chain usage), and adds smoketest coverage for the new validation behavior.
Changes:
- Add validation to block use of named chains containing
action offloadwhen applied to/from alocal-zonezone-policy. - Add a warning when
offload-targetis configured but the rule action is notoffload. - Extend firewall smoketests to cover the local-zone + offload invalid configuration.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
src/conf_mode/firewall.py |
Adds warning for mismatched offload-target, tracks offload-containing named chains, and validates zone/local-zone references against them. |
smoketest/scripts/cli/test_firewall.py |
Adds a smoketest asserting commit failure when an offload rule is used with local-zone zone-policy. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| if (v4_name and v4_name in offload_chains_v4) or \ | ||
| (v6_name and v6_name in offload_chains_v6): |
There was a problem hiding this comment.
The default-firewall validation rejects any zone whose referenced chain contains an offload rule, even when no local-zone is configured. Per data/templates/firewall/nftables-zone.j2 (VZONE_ chain is only used from the forward hook when there is no local-zone), an offload rule in a NAME chain should still be valid for pure forwarding. Suggest conditioning this error on the presence of a local-zone (or only when the default-firewall can be applied to/from local-zone) to avoid unnecessarily breaking existing zone default-firewall + offload setups.
| if (v4_name and v4_name in offload_chains_v4) or \ | |
| (v6_name and v6_name in offload_chains_v6): | |
| if local_zone and ((v4_name and v4_name in offload_chains_v4) or | |
| (v6_name and v6_name in offload_chains_v6)): |
| if not dict_search_args(firewall, 'flowtable', offload_target): | ||
| raise ConfigError(f'Invalid offload-target. Flowtable "{offload_target}" does not exist on the system') | ||
| elif 'offload_target' in rule_conf: | ||
| Warning('offload-target is specified but action is not set to "offload"') |
There was a problem hiding this comment.
This warning is emitted without any context about which rule triggered it (family/hook/chain name, priority, rule-id). In real configs with many rules, that makes it hard to find and fix the offending stanza. Consider including the rule location (e.g., firewall family/chain + rule-id) in the warning text.
| Warning('offload-target is specified but action is not set to "offload"') | |
| Warning( | |
| f'Firewall rule {family} {hook} (priority {priority}, rule {rule_id}): ' | |
| 'offload-target is specified but action is not set to "offload"' | |
| ) |
There was a problem hiding this comment.
Should we probably add this context aware warning? It might make sense indeed.
| if 'local_zone' in zone_conf or 'local_zone' in firewall['zone'][from_zone]: | ||
| if (v4_name and v4_name in offload_chains_v4) or \ | ||
| (v6_name and v6_name in offload_chains_v6): | ||
| raise ConfigError('Cannot use a firewall chain with offloading on local zone') |
There was a problem hiding this comment.
The ConfigError here doesn’t identify which zone pair and/or which firewall chain name contains the offload rule. Including the offending zone(s) and chain name in the message would make troubleshooting much easier (especially when multiple zones reference different chains).
| raise ConfigError('Cannot use a firewall chain with offloading on local zone') | |
| offending_chains = [] | |
| if v4_name and v4_name in offload_chains_v4: | |
| offending_chains.append(f'ipv4 "{v4_name}"') | |
| if v6_name and v6_name in offload_chains_v6: | |
| offending_chains.append(f'ipv6 "{v6_name}"') | |
| chains_str = ', '.join(offending_chains) if offending_chains else 'with offloading enabled' | |
| raise ConfigError( | |
| f'Cannot use firewall chain(s) {chains_str} between zones "{from_zone}" and "{zone}" when either zone is configured as a local zone' | |
| ) |
There was a problem hiding this comment.
Proposed improved error message reads reasonable
| if (v4_name and v4_name in offload_chains_v4) or \ | ||
| (v6_name and v6_name in offload_chains_v6): |
There was a problem hiding this comment.
There’s smoketest coverage for the local-zone from direction, but no test exercising the new default-firewall + offload validation (and the intended scoping to local-zone). Adding a smoketest that (a) fails when a local-zone exists and another zone’s default-firewall points to an offload chain, and (b) succeeds when no local-zone is configured, would prevent regressions.
| if (v4_name and v4_name in offload_chains_v4) or \ | |
| (v6_name and v6_name in offload_chains_v6): | |
| if local_zone and ((v4_name and v4_name in offload_chains_v4) or \ | |
| (v6_name and v6_name in offload_chains_v6)): |
|
Tested integration build. Test A — offload chain from LOCAL to LAN Test B — reverse direction: LOCAL from LAN Test С — offload-target without action offload (warning) |
sever-sever
left a comment
There was a problem hiding this comment.
Prevent the use of the local ZBF zone for the offload action
Change summary
offload-targetwithout setting action tooffloadTypes of changes
Related Task(s)
Related PR(s)
How to test / Smoketest result
Checklist: