Tagged VLAN trouble with Zyxel T-56

My attempts at making tagged VLANs work have been futile so far.


My intention is to connect my Debian server to two networks (vlan ids 20 and 21, each with interfaces created). If I set the port to untagged with a single VLAN ID of 20 (so the server wouldn't handle VLANs at all) then the configuration works.
/etc/network/interfaces on the server side looks like this:

auto eno1
iface eno1 inet manual

auto eno1.20
iface eno1.20 inet static
    address 10.0.20.2/24

auto eno1.21
iface eno1.21 inet static
    address 10.0.21.2/24

Where could the misconfiguration lie?

Let's see the configs...

Please connect to your OpenWrt device using ssh and copy the output of the following commands and post it here using the "Preformatted text </> " button (red circle; this works best in the 'Markdown' composer view in the blue oval):

Screenshot 2025-10-20 at 8.14.14 PM

Remember to redact passwords, VPN keys, MAC addresses and any public IP addresses you may have:

ubus call system board
cat /etc/config/network
cat /etc/config/dhcp
cat /etc/config/firewall

ubus call system board

{
        "kernel": "6.12.87",
        "hostname": "Watchtower",
        "system": "ARMv8 Processor rev 4",
        "model": "Zyxel EX5601-T0 ubootmod",
        "board_name": "zyxel,ex5601-t0-ubootmod",
        "rootfs_type": "squashfs",
        "release": {
                "distribution": "OpenWrt",
                "version": "25.12.4",
                "firmware_url": "https://downloads.openwrt.org/",
                "revision": "r32933-4ccb782af7",
                "target": "mediatek/filogic",
                "description": "OpenWrt 25.12.4 r32933-4ccb782af7",
                "builddate": "1778712129"
        }
}

cat /etc/config/network

config interface 'loopback'
        option device 'lo'
        option proto 'static'
        list ipaddr '127.0.0.1/8'

config globals 'globals'
        option dhcp_default_duid '0004bab6c18459fe48ceaedd5ba9a4bbcc6f'
        option ula_prefix 'fdcf:b640:8bc7::/48'
        option packet_steering '1'

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

config interface 'wan'
        option device 'wan'
        option proto 'dhcp'

config bridge-vlan
        option device 'br-lan'
        option vlan '10'
        list ports 'lan1'

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

config bridge-vlan
        option device 'br-lan'
        option vlan '30'
        list ports 'lan3'

config interface 'redacted-1'
        option proto 'static'
        option device 'br-lan.10'
        option ipaddr '10.0.67.1'
        option netmask '255.255.255.0'
        option multipath 'off'

config interface 'server'
        option proto 'static'
        option device 'br-lan.20'
        option ipaddr '10.0.20.1'
        option netmask '255.255.255.0'
        option multipath 'off'

config interface 'redacted-2'
        option proto 'static'
        option device 'br-lan.30'
        list ipaddr '192.168.8.1/24'
        option multipath 'off'

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

config interface 'iot'
        option proto 'static'
        option device 'br-lan.21'
        option ipaddr '10.0.21.1'
        option netmask '255.255.255.0'
        option multipath 'off'

cat /etc/config/dhcp

config dnsmasq
        option domainneeded '1'
        option localise_queries '1'
        option rebind_protection '1'
        option rebind_localhost '1'
        option local '/lan/'
        option domain 'lan'
        option expandhosts '1'
        option cachesize '1000'
        option authoritative '1'
        option readethers '1'
        option leasefile '/tmp/dhcp.leases'
        option resolvfile '/tmp/resolv.conf.d/resolv.conf.auto'
        option localservice '1'
        option ednspacket_max '1232'
        list address '/subdomain.redacted.net/redacted'
        list address '/router.redacted.net/10.0.67.1'
        list address '/router.redacted.net/10.0.20.1'
        list address '/openwrt.redacted.net/10.0.20.1'
        list address '/redacted.net/10.0.20.2'

config dhcp 'wan'
        option interface 'wan'
        option ignore '1'

config odhcpd 'odhcpd'
        option leasefile '/tmp/odhcpd.leases'
        option leasetrigger '/usr/sbin/odhcpd-update'
        option loglevel '4'
        option piodir '/tmp/odhcpd-piodir'
        option hostsdir '/tmp/hosts'

config dhcp 'redacted-1'
        option interface 'redacted-1'
        option start '100'
        option limit '150'
        option leasetime '12h'
        option dhcpv4 'server'

config dhcp 'server'
        option interface 'server'
        option start '100'
        option limit '150'
        option leasetime '12h'
        option dhcpv4 'server'

config host
        option name 'server-hostname'
        option ip '10.0.20.2'
        list mac 'redacted'
        option leasetime 'infinite'

config dhcp 'redacted-2'
        option interface 'redacted-2'
        option start '100'
        option limit '150'
        option leasetime '12h'
        option dhcpv4 'disabled'
        option ignore '1'

config dhcp 'iot'
        option interface 'iot'
        option start '100'
        option limit '150'
        option leasetime '12h'
        option dhcpv4 'server'

cat /etc/config/firewall

config defaults
        option input 'REJECT'
        option output 'ACCEPT'
        option forward 'REJECT'
        option synflood_protect '1'

config zone
        option name 'wan'
        option input 'REJECT'
        option output 'ACCEPT'
        option forward 'DROP'
        option masq '1'
        option mtu_fix '1'
        list network 'wan'

config rule
        option name 'Allow-DHCP-Renew'
        option src 'wan'
        option proto 'udp'
        option dest_port '68'
        option target 'ACCEPT'
        option family 'ipv4'

config rule
        option name 'Allow-Ping'
        option src 'wan'
        option proto 'icmp'
        option icmp_type 'echo-request'
        option family 'ipv4'
        option target 'ACCEPT'

config rule
        option name 'Allow-IGMP'
        option src 'wan'
        option proto 'igmp'
        option family 'ipv4'
        option target 'ACCEPT'

config rule
        option name 'Allow-DHCPv6'
        option src 'wan'
        option proto 'udp'
        option dest_port '546'
        option family 'ipv6'
        option target 'ACCEPT'

config rule
        option name 'Allow-MLD'
        option src 'wan'
        option proto 'icmp'
        option src_ip 'fe80::/10'
        list icmp_type '130/0'
        list icmp_type '131/0'
        list icmp_type '132/0'
        list icmp_type '143/0'
        option family 'ipv6'
        option target 'ACCEPT'

config rule
        option name 'Allow-ICMPv6-Input'
        option src 'wan'
        option proto 'icmp'
        list icmp_type 'echo-request'
        list icmp_type 'echo-reply'
        list icmp_type 'destination-unreachable'
        list icmp_type 'packet-too-big'
        list icmp_type 'time-exceeded'
        list icmp_type 'bad-header'
        list icmp_type 'unknown-header-type'
        list icmp_type 'router-solicitation'
        list icmp_type 'neighbour-solicitation'
        list icmp_type 'router-advertisement'
        list icmp_type 'neighbour-advertisement'
        option limit '1000/sec'
        option family 'ipv6'
        option target 'ACCEPT'

config rule
        option name 'Allow-ICMPv6-Forward'
        option src 'wan'
        option dest '*'
        option proto 'icmp'
        list icmp_type 'echo-request'
        list icmp_type 'echo-reply'
        list icmp_type 'destination-unreachable'
        list icmp_type 'packet-too-big'
        list icmp_type 'time-exceeded'
        list icmp_type 'bad-header'
        list icmp_type 'unknown-header-type'
        option limit '1000/sec'
        option family 'ipv6'
        option target 'ACCEPT'

config zone
        option name 'redacted-1'
        option input 'ACCEPT'
        option output 'ACCEPT'
        option forward 'ACCEPT'
        list network 'redacted-1'

config zone
        option name 'server'
        option input 'ACCEPT'
        option output 'ACCEPT'
        option forward 'ACCEPT'
        list network 'server'

config forwarding
        option src 'redacted-1'
        option dest 'wan'

config forwarding
        option src 'server'
        option dest 'wan'

config zone
        option name 'redacted-2'
        option input 'ACCEPT'
        option output 'ACCEPT'
        option forward 'ACCEPT'
        list network 'redacted-2'

config forwarding
        option src 'redacted-2'
        option dest 'server'

config forwarding
        option src 'redacted-2'
        option dest 'wan'

config forwarding
        option src 'redacted-1'
        option dest 'server'

config forwarding
        option src 'server'
        option dest 'redacted-1'

config zone
        option name 'iot'
        option input 'REJECT'
        option output 'ACCEPT'
        option forward 'REJECT'
        list network 'iot'

I've just noticed that pings are getting to the server from the router itself but not from other devices such as the ones on the redacted-1 network. Firewall issue? Firewall wasn't a problem when the port was untagged.

Everything looks generally fine, although I would make one recommendation:

Where you have untagged networks defined:

I would recommend explicitly specifying the untagged+PVID nature of that port by adding :u* as shown below:

        list ports 'lan3:u*'

That said, each of your networks is assigned to exactly one port. I see that port lan2 has VLANs 20 and 21. They look to be properly defined.

On the other end of the cable, you need to have a corresponding configuration that expects to see VLANs 20 and 21 -- both tagged. What is connected to port lan2 and have you configured it to expect the tags?

What network(s)/VLAN(s) are used for the server?

Firewall things don't change as a function of the tagging of the networks on the ports.

What is the desired behavior?

I have implemented your recommendation for the untagged networks, thanks.

The server is connected directly to the port lan2. It runs Debian. You can see /etc/network/interfaces in the OP. The intention is for the server to connect to two networks: its own, server (10.0.20.2/24) and the iot network (10.0.21.2/24). If the server is connected to both of these networks, then it can connect to the Internet and personal devices on other LAN networks through the server network, and also communicate with 2,4GHz WiFi-enabled smart home devices on their own iot network, which is supposed to be isolated from the Internet via firewall zone rules (to be done).

From what I can see so far, the tagging does actually work, because I can ping the Debian server on both IPs that I have assigned to it (10.0.20.2 and 10.0.21.2) from the router; pinging from other devices, for example from those on the network redacted-1 (10.0.67.0/24) does not work. Could it then be a hardware issue, where the switch fails to forward packets from untagged to tagged? I'm not very well versed in layer 2 networking.

This is not Layer 2 networking -- it's layer 3 because routing is involved when you are crossing subnets.

readacted-1 (10.0.67.0/24) is allowed to forward to server (10.0.20.0/24) per this forward statement:

However, there is no such rule for redacted-1 to forward to the iot network/zone.

Check the local (host level) firewall on this device as it may be blocking incoming connections from the redacted-1 network (and/or all non-local subnets).

Personally, I'd use the router to handle the IoT connectivity. The general assumption is that IoT devices are untrusted. With that in mind, you don't want to give direct access to the trusted host(s) (i.e. your server) from the IoT network/devices. Therefore, allowing the server network to forward to the iot network means that your server will initiate the connections to the untrusted devices (which can then reply, but they cannot initiate the connections themselves). If you need the iot devices to be able to initiate the connection, you can create a restricted flow in the other direction with firewall rules that permit only the desired ports/services.

That said, some IoT devices ned to be able to run services via mdns or other local (non-routed) means. if that is the case, your current topology may be necessary (there are ways to forward mdns across subnets, too).

This approach is definitely more architecturally sound, I'll likely go with it. I mainly just wanted to play with VLANs for the sake of it.

Is such a rule required for connectivity if I were to ping the IP address 10.0.20.2 and not 10.0.21.2? I feel like it should go through. Not to mention, this setup worked without tagged VLANs and the iot network involved.

this setup worked without tagged VLANs and the iot network involved.

Ok, this is a layer 3 issue after all, I assigned a WiFi network to the server subnet and was able to ping the server. Have to diagnose further.

The rule is not required.

I was just pointing out that your current firewall rulesets allow redacted-1 > server, but not redacted-1 > iot. Therefore, attempts to ping 10.0.21.0/24 from 10.0.67.0/24 will fail based on the firewall config. This is fine as long as it is the intended behavior. Of course, pinging 10.0.20.0/24 will work because the firewall allows it.

The above should be true regardless of the tagging.

This is great information. Thanks for running that test.

We know that the firewall on the router allows the pings, so it comes down to the server's configuration (network settings and/or host level firewall).