Skip to content

Conversation

@apschultz
Copy link

@apschultz apschultz commented Aug 20, 2025

In large networks with many zones where simple allow/deny rules are not sufficient, zones become tedious to manage. Many use cases can be simplified by providing an ability to define a default ruleset for traffic from other zones. This change proposes adding the follwing syntax:
set firewall zone default_firewall name
set firewall zone default_firewall ipv6_name

The proposed behavior is the following:

  • local in:
    • The default firewall ruleset for the local zone will be appended after all from configurations.
  • local out:
    • If a non-local zone does not have a from local ruleset but does have a default_firewall ruleset, the default_firewall ruleset will be appended using oifname
  • forward:
    • The default firewall ruleset for the zone will be appended after all from configurations

To keep the behavior consistent with from ruleset configurations, a return is appended after the default_firewall ruleset.

The proposed behavior differs slightly from the default_policy configuration for the local out chains. The default_policy applied in the out templates comes from the local zone, not the actual outbound zone. The proposed change does not amend this, but does make default_firewall logically consistent with the intent of the out rules.

Change summary

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Code style update (formatting, renaming)
  • Refactoring (no functional changes)
  • Migration from an old Vyatta component to vyos-1x, please link to related PR inside obsoleted component
  • Other (please describe):

Related Task(s)

https://vyos.dev/T7739

Related PR(s)

How to test / Smoketest result

Added additional firewall smoketest case to validate. All smoke tests are passing.

Checklist:

  • I have read the CONTRIBUTING document
  • I have linked this PR to one or more Phabricator Task(s)
  • I have run the components SMOKETESTS if applicable
  • My commit headlines contain a valid Task id
  • My change requires a change to the documentation
  • I have updated the documentation accordingly

@github-actions
Copy link

github-actions bot commented Aug 20, 2025

All contributors have signed the CLA ✍️ ✅
Posted by the CLA Assistant Lite bot.

@github-actions
Copy link

github-actions bot commented Aug 20, 2025

👍
No issues in PR Title / Commit Title

@apschultz
Copy link
Author

I have read the CLA Document and I hereby sign the CLA

vyosbot added a commit to vyos/vyos-cla-signatures that referenced this pull request Sep 2, 2025
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR implements default firewall rulesets for firewall zones, allowing administrators to define fallback rules that apply when specific zone-to-zone rules are not configured. This simplifies management of large networks with many zones by reducing the need to explicitly configure rules between every zone pair.

Key changes:

  • Adds default-firewall configuration syntax for zones with IPv4 and IPv6 ruleset options
  • Implements logic to apply default rulesets when explicit zone-to-zone rules are absent
  • Updates nftables templates to generate appropriate rules for default firewall behavior

Reviewed Changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

File Description
src/conf_mode/firewall.py Adds configuration parsing and validation for default firewall rulesets
interface-definitions/firewall.xml.in Defines XML schema for new default-firewall configuration node
data/templates/firewall/nftables-zone.j2 Updates nftables template to generate rules for default firewall behavior
smoketest/scripts/cli/test_firewall.py Adds comprehensive test case validating default firewall functionality

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

Copy link
Member

@sarthurdev sarthurdev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR!

A few changes needed, also please address the indentation issue raised by copilot.

Comment on lines 1022 to 1028
['jump NAME_smoketest-default'],
['chain VZONE_smoketest-eth1'],
['jump NAME_smoketest-default'],
['chain VZONE_smoketest-eth2'],
['chain VZONE_smoketest-local_IN'],
['iifname "eth0"', 'jump NAME_smoketest'],
['jump NAME_smoketest-default'],
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These duplicate ['jump NAME_smoketest-default'] searchs are redundant.

If you want to check for these jumps in specific chains you can use verify_nftables_chain https://github.com/vyos/vyos-1x/blob/current/smoketest/scripts/cli/base_vyostest_shim.py#L181

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've struggled to understand exactly how the smoke tests actually function. I more or less hoped there was some ordering expectation in the matching. I'll investigate verify_nftables_chain as just looking to see that something like the string I want does not actually make sure the feature works as intended.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the nftables verify functions, each list item is expecting to match all of the specified criteria on a single line of nftables output.

For example ['iifname "eth0"', 'jump NAME_smoketest'], expects to find a rule matching both the interface and the jump.

verify_nftables_chain is best suited to assert your jump NAME_smoketest-default is present on each expected chain.

For example (excuse formatting, also not tested):

self.verify_nftables_chain([['jump NAME_smoketest-default']], 'ip vyos_filter', 'VZONE_smoketest-eth1')
self.verify_nftables_chain([['jump NAME_smoketest-default']], 'ip vyos_filter', 'VZONE_smoketest-eth2')

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the reference. I reorganized the smoke test to test chain existence and content.

@apschultz apschultz force-pushed the zone_default_firewall_ruleset branch from 5a05887 to 51850f5 Compare September 19, 2025 13:55
@apschultz apschultz force-pushed the zone_default_firewall_ruleset branch from 51850f5 to 112264c Compare September 19, 2025 14:04
@apschultz apschultz force-pushed the zone_default_firewall_ruleset branch 2 times, most recently from 5ee339a to f72bbd1 Compare October 19, 2025 15:44
@l0crian1
Copy link
Contributor

l0crian1 commented Oct 19, 2025

@apschultz

Your smoketest is failing; likely because you meant to do iifname "eth0" here:

        smoketest_eth0_search = [
            ['iifname "eth1"', 'jump NAME_smoketest'],
            ['jump NAME_smoketest-default']
        ]
        self.verify_nftables_chain_exists('ip vyos_filter', 'VZONE_smoketest-eth0')
        self.verify_nftables_chain(smoketest_eth0_search, 'ip vyos_filter', 'VZONE_smoketest-eth0')

Something you might find useful when building your smoketest is you can run just your test by using a -k switch and then calling your function. That way you're not needing to wait for the full test to run each time:

/usr/libexec/vyos/tests/smoke/cli/test_firewall.py -k test_zone_with_default_firewall

In large networks with many zones where simple allow/deny rules are not sufficient,
zones become tedious to manage. Many use cases can be simplified by providing an
ability to define a default ruleset for traffic from other zones. This change proposes
adding the follwing syntax:
   set firewall zone <name> default_firewall name <name>
   set firewall zone <name> default_firewall ipv6_name <name>

The proposed behavior is the following:
   local in:
      The default firewall ruleset for the local zone will be appended after all
      from configurations.
   local out:
      If a non-local zone does not have a from local ruleset but does have a
      default_firewall ruleset, the default_firewall ruleset will be appended using
      oifname
   forward:
      The default firewall ruleset for the zone will be appended after all from
      configurations

To keep the behavior consistent with from ruleset configurations, a return is appended
after the default_firewall ruleset.

The proposed behavior differs slightly from the default_policy configuration for the
local out chains. The default_policy applied in the out templates comes from the local
zone, not the actual outbound zone. The proposed change does not amend this, but does
make default_firewall logically consistent with the intent of the out rules.
@apschultz apschultz force-pushed the zone_default_firewall_ruleset branch from f72bbd1 to cc5895f Compare October 21, 2025 23:46
@apschultz
Copy link
Author

apschultz commented Oct 21, 2025

@apschultz

Your smoketest is failing; likely because you meant to do iifname "eth0" here:

        smoketest_eth0_search = [
            ['iifname "eth1"', 'jump NAME_smoketest'],
            ['jump NAME_smoketest-default']
        ]
        self.verify_nftables_chain_exists('ip vyos_filter', 'VZONE_smoketest-eth0')
        self.verify_nftables_chain(smoketest_eth0_search, 'ip vyos_filter', 'VZONE_smoketest-eth0')

Something you might find useful when building your smoketest is you can run just your test by using a -k switch and then calling your function. That way you're not needing to wait for the full test to run each time:

/usr/libexec/vyos/tests/smoke/cli/test_firewall.py -k test_zone_with_default_firewall

I feel rather silly. I did my test debugging in a vm and forgot to copy out the final version. The last set of tests failed. The local out chain should use oifname instead of iifname

@github-actions
Copy link

CI integration ❌ failed!

Details

CI logs

  • CLI Smoketests (no interfaces) 👍 passed
  • CLI Smoketests VPP 👍 passed
  • CLI Smoketests (interfaces only) ❌ failed
  • Config tests 👍 passed
  • Config tests VPP 👍 passed
  • RAID1 tests 👍 passed
  • TPM tests 👍 passed

Copy link
Member

@sarthurdev sarthurdev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code looks sound, adds smoketest coverage and now passes.

If you wouldn't mind contributing documentation for the new syntax, that would be appreciated. https://github.com/vyos/vyos-documentation

@apschultz
Copy link
Author

Code looks sound, adds smoketest coverage and now passes.

If you wouldn't mind contributing documentation for the new syntax, that would be appreciated. https://github.com/vyos/vyos-documentation

I'd be happy to. Anything outside of docs/configuration/firewall/zone.rst that needs to be updated?

@sarthurdev
Copy link
Member

Code looks sound, adds smoketest coverage and now passes.
If you wouldn't mind contributing documentation for the new syntax, that would be appreciated. https://github.com/vyos/vyos-documentation

I'd be happy to. Anything outside of docs/configuration/firewall/zone.rst that needs to be updated?

Shouldn't be anything else, as this is new CLI and nothing is changed/removed. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Development

Successfully merging this pull request may close these issues.

3 participants