[VyOS 1.5 - Stream] -- Generic Zone Base Firewall Inquiry

Hi Again everyone!

So this is a very basic question. Before anyone has asks, I’ve gone through the documentation provided on the VyOS website but there is still one thing I’m a touch confused on, and that’s related to the local-zone.

Here is the most minimal configuration I am able to provide.

VyOS Router #1:

set firewall zone LOCAL local-zone
set interfaces ethernet eth0 address 'dhcp'
set interfaces ethernet eth1 address '172.16.91.2/24'
set interfaces ethernet eth2 address '10.91.91.2/24'
set interfaces ethernet eth9 address '10.1.1.1/24'
set interfaces loopback lo
set nat source rule 1 outbound-interface name 'eth0'
set nat source rule 1 source address '0.0.0.0/0'
set nat source rule 1 translation address 'masquerade'
set service config-sync mode 'load'
set service config-sync secondary address '10.1.1.2'
set service config-sync secondary key '123123123123123'
set service config-sync section firewall
set service config-sync section nat
set service config-sync section system time-zone
set system host-name 'vyos'
set system time-zone 'America/Toronto'

VyOS Router #2:

set interfaces ethernet eth1 address '172.16.91.3/24'
set interfaces ethernet eth2 address '10.91.91.3/24'
set interfaces ethernet eth9 address '10.1.1.2/24'
set interfaces loopback lo
set nat source rule 1 outbound-interface name 'eth0'
set nat source rule 1 source address '0.0.0.0/0'
set nat source rule 1 translation address 'masquerade'
set service https api keys id 1 key '123123123123123'
set service https listen-address '10.1.1.2'
set system host-name 'vyos'
set system time-zone 'America/Toronto'

When I enable just a basic zone called “LOCAL” as a local-zone, i can’t figure out a way to allow local traffic, for example config-sync to function correctly or even a basic ICMP packet between the eth9 interface.

I am using eth9 as an interconnect interface between VyOS routers for config-sync purposes, and VRRP as well – i will have VRRP running on interface eth2 and eth1 – i would assume putting those interfaces into their own Zones, if a packet enters that zone for vrrp it should be accepted.

I’ve tried to incorporate the zone based firewall local-zone with the set firewall ipv4 input filter and set firewall ipv4 output filter for locally generated traffic, but doesn’t seem to function as expected.

Any insight on this would be helpful and greatly appreciated!

One thing that will help you understand what the config is doing is to learn to understand nftables (or pipe it into ChatGPT). Right now, you’re just configuring a zone, but not configuring any traffic being allowed to/from it. We can see this using sudo nft list table vyos_filter (for IPv4 traffic). I removed some of the other chains for simplicity.

chain VYOS_ZONE_FORWARD {
        type filter hook forward priority filter + 1; policy accept;
}

chain VYOS_ZONE_LOCAL {
        type filter hook input priority filter + 1; policy accept;
        counter packets 72 bytes 5328 jump VZONE_LOCAL_IN
}

chain VYOS_ZONE_OUTPUT {
        type filter hook output priority filter + 1; policy accept;
        counter packets 72 bytes 5328 jump VZONE_LOCAL_OUT
}

chain VZONE_LOCAL_IN {
        iifname "lo" counter packets 72 bytes 5328 return
        counter packets 0 bytes 0 drop comment "zone_LOCAL default-action drop"
}

chain VZONE_LOCAL_OUT {
        oifname "lo" counter packets 72 bytes 5328 return
        counter packets 0 bytes 0 drop comment "zone_LOCAL default-action drop"
}

Traffic to your router will use this chain (notice the hook of input):

chain VYOS_ZONE_LOCAL {
        type filter hook input priority filter + 1; policy accept;
        counter packets 72 bytes 5328 jump VZONE_LOCAL_IN
}

Traffic hits the chain and then jumps to the named chain of:

chain VZONE_LOCAL_IN {
        iifname "lo" counter packets 72 bytes 5328 return
        counter packets 0 bytes 0 drop comment "zone_LOCAL default-action drop"
}

So you can see that traffic to ‘lo’ is returned to the parent chain (VYOS_ZONE_LOCAL ). Everything else is dropped. You’ll see a similar behavior with VYOS_ZONE_OUTPUT . Since you’re trying to do config-sync on eth9, traffic will hit that default drop (since it’s not lo).

You’ll need to configure other zones to actually make traffic work. So if eth9 is only used for config-sync, you can make that it’s own zone, and then configure policies you can apply to make that traffic work. This is just a simple example:

set firewall zone LOCAL local-zone
set firewall zone CFGSYNC member interface 'eth2'

set firewall ipv4 name CFGSYNC_TO_LOCAL rule 10 action 'accept'
set firewall ipv4 name CFGSYNC_TO_LOCAL rule 10 source address '10.1.1.2'

set firewall ipv4 name LOCAL_TO_CFGSYNC rule 10 action 'accept'
set firewall ipv4 name LOCAL_TO_CFGSYNC rule 10 destination address '10.1.1.2'

set firewall zone CFGSYNC from LOCAL firewall name 'LOCAL_TO_CFGSYNC'
set firewall zone LOCAL from CFG_SYNC firewall name 'CFGSYNC_TO_LOCAL'

Now if we look at nftables, we can see it is more complete:

        chain NAME_CFGSYNC_TO_LOCAL {
                ip saddr 10.1.1.2 counter packets 0 bytes 0 accept comment "ipv4-NAM-CFGSYNC_TO_LOCAL-10"
                counter packets 0 bytes 0 drop comment "NAM-CFGSYNC_TO_LOCAL default-action drop"
        }

        chain VYOS_ZONE_LOCAL {
                type filter hook input priority filter + 1; policy accept;
                counter packets 0 bytes 0 jump VZONE_LOCAL_IN
        }

        chain VZONE_CFG_SYNC {
                iifname "eth2" counter packets 0 bytes 0 return
                counter packets 0 bytes 0 drop comment "zone_CFG_SYNC default-action drop"
        }

        chain VZONE_LOCAL_IN {
                iifname "lo" counter packets 0 bytes 0 return
                iifname "eth2" counter packets 0 bytes 0 jump NAME_CFGSYNC_TO_LOCAL
                iifname "eth2" counter packets 0 bytes 0 return
                counter packets 0 bytes 0 drop comment "zone_LOCAL default-action drop"
        }
}

You can see that now, when traffic hits an inbound interface of ‘eth2’ (eth9 in your config), then it is sent to your new named chain we created of CFGSYNC_TO_LOCAL, which allows traffic with a source of 10.1.1.2, allowing the config-sync traffic.

This is how you’ll want to do it if using “zone based firewall”, but if you don’t actually want to define zones for everything, you can just use the input and output chains with similar syntax as our named chains.

# Drops all traffic not explicitly allowed
set firewall ipv4 input filter default-action 'drop'

# Allows stateful return traffic
set firewall ipv4 input filter rule 10 action 'accept'
set firewall ipv4 input filter rule 10 state 'established'
set firewall ipv4 input filter rule 10 state 'related'

# Drops invalid state (traffic seen without a conntrack entry)
set firewall ipv4 input filter rule 15 action 'drop'
set firewall ipv4 input filter rule 15 state 'invalid'

# Explicitly allows traffic from 10.1.1.2 on eth9
set firewall ipv4 input filter rule 20 action 'accept'
set firewall ipv4 input filter rule 20 source address '10.1.1.2'
set firewall ipv4 input filter rule 20 inbound-interface name eth9

# Allows all traffic from the router out (you can lock this down more if desired)
set firewall ipv4 output filter default-action 'accept'

@L0crian thanks for the details provided.
That’s all I needed to know, newbie with nftables, but reading up on it a bit more it makes much more sense to me.

No issue with defining a separate zone for it for myself as that’s the only interface that is not accounted for.

Thanks again! I’ll mark your response as the solution as all I was looking for was to see if I was missing something. Now i know the Zone Based Firewall is based off of nftables so that already is good information for me to know!

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.