-
Notifications
You must be signed in to change notification settings - Fork 340
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
T6841: firewall: improve config parsing for ZBF when using VRFs and interfaces attached to VRFs #4180
base: current
Are you sure you want to change the base?
Conversation
❌ |
✅ No issues found in unused-imports check.. Please refer the workflow run |
…nterfaces attached to VRFs
3359f05
to
409766f
Compare
Should I also change these files? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suggest a different syntax that I think is more intuitive (or less counter-intuitive ;) and there are some missing cases in the migration script logic.
@@ -464,24 +464,39 @@ | |||
</node> | |||
</children> | |||
</tagNode> | |||
<leafNode name="interface"> | |||
<node name="interface"> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
<node name="interface"> | |
<node name="member"> |
I agree with the idea to separate interface and VRF options but I have reservations about this syntax. The problem is that a VRF is not an interface, any VRF may include as many interfaces as it wants.
So the parent node should be named something else than interface
. I think member
might be a good generic word.
</properties> | ||
</leafNode> | ||
<children> | ||
<leafNode name="name"> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
<leafNode name="name"> | |
<leafNode name="interface"> |
@@ -905,7 +905,7 @@ def test_timeout_sysctl(self): | |||
def test_zone_basic(self): | |||
self.cli_set(['firewall', 'ipv4', 'name', 'smoketest', 'default-action', 'drop']) | |||
self.cli_set(['firewall', 'ipv6', 'name', 'smoketestv6', 'default-action', 'drop']) | |||
self.cli_set(['firewall', 'zone', 'smoketest-eth0', 'interface', 'eth0']) | |||
self.cli_set(['firewall', 'zone', 'smoketest-eth0', 'interface', 'name', 'eth0']) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
self.cli_set(['firewall', 'zone', 'smoketest-eth0', 'interface', 'name', 'eth0']) | |
self.cli_set(['firewall', 'zone', 'smoketest-eth0', 'member', 'interface', 'eth0']) |
self.cli_set(['firewall', 'zone', 'LOCAL', 'from', 'ZONE1', 'firewall', 'name', 'ZONE1-to-LOCAL']) | ||
self.cli_set(['firewall', 'zone', 'LOCAL', 'local-zone']) | ||
self.cli_set(['firewall', 'zone', 'ZONE1', 'from', 'ZONE2', 'firewall', 'name', 'ZONE2_to_ZONE1']) | ||
self.cli_set(['firewall', 'zone', 'ZONE1', 'interface', 'name', 'eth1']) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
self.cli_set(['firewall', 'zone', 'ZONE1', 'interface', 'name', 'eth1']) | |
self.cli_set(['firewall', 'zone', 'ZONE1', 'member', 'interface', 'eth1']) |
self.cli_set(['firewall', 'zone', 'LOCAL', 'local-zone']) | ||
self.cli_set(['firewall', 'zone', 'ZONE1', 'from', 'ZONE2', 'firewall', 'name', 'ZONE2_to_ZONE1']) | ||
self.cli_set(['firewall', 'zone', 'ZONE1', 'interface', 'name', 'eth1']) | ||
self.cli_set(['firewall', 'zone', 'ZONE1', 'interface', 'name', 'eth2']) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
self.cli_set(['firewall', 'zone', 'ZONE1', 'interface', 'name', 'eth2']) | |
self.cli_set(['firewall', 'zone', 'ZONE1', 'member', 'interface', 'eth2']) |
src/conf_mode/firewall.py
Outdated
# Get physical interfaces assigned to the zone if vrf is used: | ||
if 'vrf' in local_zone_conf['interface']: | ||
local_zone_conf['vrf_interfaces'] = {} | ||
for vrf_name in local_zone_conf['interface']['vrf']: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
for vrf_name in local_zone_conf['interface']['vrf']: | |
for vrf_name in local_zone_conf['member']['vrf']: |
# From | ||
# set firewall zone <zone> interface <iface> | ||
# To | ||
# set firewall zone <zone> interface name <iface> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
# set firewall zone <zone> interface name <iface> | |
# set firewall zone <zone> member interface <iface> |
# To | ||
# set firewall zone <zone> interface name <iface> | ||
# or | ||
# set firewall zone <zone> interface vrf <vrf> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
# set firewall zone <zone> interface vrf <vrf> | |
# set firewall zone <zone> member vrf <vrf> |
for zone in config.list_nodes(base): | ||
if config.exists(base + [zone, 'interface']): | ||
for iface in config.return_values(base + [zone, 'interface']): | ||
config.set(base + [zone, 'interface', 'name'], value=iface, replace=False) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
config.set(base + [zone, 'interface', 'name'], value=iface, replace=False) | |
config.set(base + [zone, 'member', 'interface'], value=iface, replace=False) |
# Nothing to do | ||
return | ||
|
||
for zone in config.list_nodes(base): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This logic looks incomplete.
- It doesn't seem to delete values from under the old
interface
node, only duplicates them under the new one. - VRF support was introduced in 1.4.0 already, but the script doesn't handle the case when the value is a VRF name rather than an interface name.
Improve config parsing for ZBF when using VRFs and interfaces attached to VRFs
T6841: firewall: Fixed issues in ZBF when using VRFs
CI integration ❌ failed! Details
|
</properties> | ||
</leafNode> | ||
<children> | ||
<leafNode name="interface"> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please reference the generic interface include https://github.com/vyos/vyos-1x/blob/current/interface-definitions/include/generic-interface-multi.xml.i
Change Summary
Improve config parsing for ZBF when using VRFs and interfaces attached to VRFs
Types of changes
Related Task(s)
Related PR(s)
Component(s) name
firewall
Proposed changes
For zone based firewall, everything is related to matching inbound and outbound interface. The problem is that in Linux, if an interface is attached to a non-default VRF, then:
Before this PR, what was written under
set firewall zone <zone> interface <iface>
was exactly written for inbound|outbound interface in nftables.Now we have provide more options so we can specify
interface name
andinterfave vrf
while defining interfaces in a zone.interface name <iface>
--> it still writes exactly that interfaces for inbound|outbound interface in nftablesinterface vrf <vrf_name>
--> in nftables it writes:How to test
Smoketest result
Checklist: