Bridging two vlans of DSA bridge to filter traffic between them with nft causes lock-up after 30s

Hello!

i am using an Asus TUF AX6000 with Openwrt 24.10.4, trying to bridge untagged lan (on vid 83) with tagged lan (vid 6) together with nft rules for traffic filtering*. Excerpt from my network config:

config interface 'loopback'
        option device 'lo'
        option proto 'static'
        option ipaddr '127.0.0.1'
        option netmask '255.0.0.0'

config globals 'globals'
        option ula_prefix '<redacted>::/48'
        option packet_steering '1'

config device 'brlan_dev'
        option name 'br-lan'
        option type 'bridge'
        option vlan_filtering '1'
        list ports 'lan1'
        list ports 'lan2'
        list ports 'lan3'
        list ports 'lan4'
        list ports 'lan5'

config interface 'lan'
        option device 'br-lan.83'
        option proto 'static'
        option ipaddr '192.168.1.1'
        option netmask '255.255.255.0'

config bridge-vlan                       
        option device 'br-lan'
        option vlan '83'
        list ports 'lan1:u*'
        list ports 'lan2:u*'
        list ports 'lan3:u*'
        list ports 'lan4:u*'
        list ports 'lan5:u*'

config bridge-vlan
        option device 'br-lan'
        option vlan '6'
        list ports 'lan5:t'
        list ports 'lan2:t'

config interface 'filtered_lan'
        option device 'br-lan.6'
        option proto 'none'

According to https://openwrt.org/docs/guide-user/network/vlan/switch_configuration one should see something like lan5.6 or lan2.6 (ports were intended for uplink and debugging) in brctl show, but i only get

$ brctl show
bridge name     bridge id               STP enabled     interfaces
br-lan          7fff.107c61dd0688       no              lan4
                                                        lan2
                                                        lan5
                                                        lan3
                                                        lan1

Indeed there is now no bridging happening between br-lan.83 and br-lan.6, so nft rules don't apply.
But if i add a second bridge with

$ brctl addbr br-vlan
$ brctl addif br-vlan br-lan.6

and then temporarily add br-lan.83 to it via

$ brctl addif br-vlan br-lan.83; sleep 60; brctl delif br-vlan br-lan.83

the bridging and the nft filtering works as i can see the drops in the system log - but just for 30 seconds. After that, all connectivity to the device is lost (no ssh or ping). And after another 30s, it is restored as br-vlan.83 is removed from the bridge, but just due to the timed command, otherwise i would have to reboot.
Am i doing something wrong?

*Reason for me wanting this is that this was easily possible up to Openwrt 19.07 using ebtables.

PS: Bonus question: Is it normal that connectivity breaks if one does

$ uci set network.brlan_dev.vlan_filtering='0' && service network restart

? If yes, vlan_filtering option is not really an option.

I'm trying to understand the end goal here...

  • Are you trying to actually bridge the two VLANs together?
  • What is the rest of the network topology? (a diagram could be really helpful)?
  • Is this the main router?
  • If not, what is the address of the upstream router?
  • What port on this router connects to the upstream network?
  • Does VLAN 6 exist anywhere else on the network?
  • Where is the router that services this VLAN?

Some quick things:

  • Normally, you can simply have config device on its own -- no name following because the name is explicitly within the bridge definition. I'd remove brlan_dev because it is unnecessary and may even be causing a conflict.
  • The vlan_filtering line isn't actually necessary from what I have seen across many hundreds of configs. It shouldn't have any negative effect either way, but it is enabled automatically (without needing to specify it) when you create bridge-vlan statements.

Show bridge vlan (package ip-bridge)

I'm missing something here. What nft rules have you configured? I don't see any mention of what rules you have.

The nftables equivalent of ebtables requires the kmod-nft-bridge package that gives support for the bridge address family.

So, to be clear, are you trying to filter traffic between two interfaces in a bridge?

For this you will have to create a bridge table, a chain of the hook type you need and the rules you want.
This is not supported by fw4 as far as I know, so you will have to do it via nft commands.

  • Are you trying to actually bridge the two VLANs together?

Yes. 83 is main lan, and 6 shall be lan for iot devices that shall not connect to the internet, but be serviceable by certain ips from main lan.

  • What is the rest of the network topology? (a diagram could be really helpful)?

Not much currently:

*------*   *-------*  *------*
|router| --|       |--|lan(u)|   <-- main lan
*------*   |managed|  *------*
           |switch |
           |       |  *------*
           |       |--|lan(6)|  <-- iot lan (over wifi aps)
           *-------*  *------*

There will be more, but first i have to get the vlan bridging working.

  • Is this the main router?

Shall be, yes.

  • What port on this router connects to the upstream network?

The wan port, but that is not involved here. Thanks to DSA, this router shall replace my wrt1900acs because the asus has its wan port on a separate interface.

  • Does VLAN 6 exist anywhere else on the network?

There shall be a managed switch on lan port 5 which also connects openwrt access points that bridge certain wifis (where iot devices connect to) to this vlan. Currently i do testing over lan port 2 using a laptop with its ethernet interface configured for vlan 6.

  • Where is the router that services this VLAN?

This should be this one, but it will only do dhcp for 6 and allow communication with certain devices on lan.

  • The vlan_filtering line isn't actually necessary from what I have seen across many hundreds of configs. It shouldn't have any negative effect either way, but it is enabled automatically (without needing to specify it) when you create bridge-vlan statements.

Well, it crashes the router if there is vlan configured for the bridge and one sets it to zero. I would call this a negative effect.

Show bridge vlan (package ip-bridge)

Not installed.

You do not want to bridge the networks. That is not the right approach and will not work properly.

You want to route the networks. Doing this is a different operation entirely.

So you plan to make this router into the main router (replacing your existing main router)? Please confirm.

To be clear, your current approach will not work and will only cause problems when you try to implement it (as you're already experiencing). You need to setup a routed network with VLANs.

You can use nft to filter on the bridge, but in this case you totally do not need to frankenstein 3 bridges together.

kmod-nft-bridgeis installed (else i would not see the drops happening in the 30s window).
Rules are (here for only one managing ip, will be more):

# nft list table bridge gfw
table bridge gfw {
        chain forward {
                type filter hook forward priority 0; policy accept;
                iifname "br-lan.6" jump local_br-lan.6_FIN
                oifname "br-lan.6" jump local_br-lan.6_FOUT
        }

        chain input {
                type filter hook input priority 0; policy accept;
                iifname "br-lan.6" jump local_br-lan.6_IN
        }

        chain output {
                type filter hook output priority 0; policy accept;
                oifname "br-lan.6" jump local_br-lan.6_OUT
        }

        chain logAndDrop {
                log prefix "gfw-drop" flags all
                drop
        }

        chain local_br-lan.6_IN {
                arp daddr ip 192.168.1.2 accept
                ip daddr 192.168.1.2 accept
                arp daddr ip 192.168.1.1 accept
                meta protocol ip udp dport 67 accept
                ether type 0x888e accept
                jump logAndDrop
        }

        chain local_br-lan.6_FIN {
                arp daddr ip 192.168.1.2 accept
                ip daddr 192.168.1.2 accept
                meta protocol ip udp dport 67 accept
                jump logAndDrop
        }

        chain local_br-lan.6_OUT {
                arp saddr ip 192.168.1.2 accept
                ip saddr 192.168.1.2 accept
                arp saddr ip 192.168.1.1 accept
                meta protocol ip udp sport 67 accept
                jump logAndDrop
        }

        chain local_br-lan.6_FOUT {
                arp saddr ip 192.168.1.2 accept
                ip saddr 192.168.1.2 accept
                meta protocol ip udp sport 67 accept
                jump logAndDrop
        }
}

As said, i see nft working in the first 30s time window before the router goes offline. Test is just pinging from lan2.6.

This is the wrong approach for your goals.

Indeed, it is the wrong approach if he wants to layer 3 route, but from what he has said, he wants to filter layer 2 between bridge ports.

He did say it used to work using ebtables on 19.07, so the implication is that he actually does want a layer 2 filter.... Now he has posted his bridge table details... So.... I'll take a look.

Well, kind of...

The problem is that there is no upstream network definition currently associated with VLAN 6. That is to say that there isn't a router that expects to handle said traffic, and there is no DHCP or DNS service associated, so that network is basically just a headless L2 construct.

Bridging VLAN 6 with VLAN 83 would really just make it part of the same VLAN 83... but I don't think that the filtering that is desired would ever work as expected.

The goal appears to be this:

The most effective approach to achieve this is to use 2 VLANs and route between them. The lan > iot network can be allowed (or filtered with whatever granularity is required) and the iot network can simply not have forwarding to the wan. Simple, effective, and functional.

1 Like

Might be, although layer 2 "filtering" is generally much faster than layer 3+.

You know much more about vlans than I do, but if each vlan appears in the output of ip link then there is no issue with bridge filtering.
What would you expect to see in ip link with his vlans?

Add some rate limit here and goto as it has no further processing intended.

I suspect log storm from arp who-has broadcasts (this is not arptables, but you have to re-implement one if limiting)

Now i understand the 3 bridges design. What you could do instead is just make a set if iif-s (not 5x slower -names) and use those ipo branched vlans.

Usually, the attempts to do L2 filtering:
a) don't work properly these days (although I'm not an expert here)
b) are done on the same subnet/VLAN.

It is not normal to bridge VLANs together, as it defeats the entire purpose of VLANs in the first place.

This is wrong. You are overriding the forward priority (default -200 for filter).
All the fw4 chains are priority 0, so it is undefined which chains/rules take priority, your table's or fw4's. Either leave out the priority part or make it -300 or so.

Your whole ruleset looks more complicated than it needs to be, but then it might just be me not fully understanding what you are trying to achieve.

If your IoT devices don't care if they are on a different ipv4 subnet, then @psherman 's indicated solution may well be better for you.

1 Like

Proxmox does "keep in order" filtering on the bridges, like nobody spoofs traffic etc.

Install it, it "sees" more than brctl

Yes, there is no support whatsoever in fw4 and bridge family is omitted by default (no kmod-nft-bridge installed) to save space.

Not really. Layer 2 neither knows nor cares about vlans or subnets, because, well, that is layer 2.

A "trunk" is basically a set of vlans bridged together is it not?

I thought vlan packets were nothing more than "ethernet type" packets with extra fields of bits set (tags) to specify the "owning vlan" network.