[Solved] Separate Switch/Routing/AP mode for different VLANs

I have currently a selfhosted setup on a thin client. I want to isolate any IoT traffic from my normal network without giving them internet access, while keeping access to the home assistant instance.

I thought it might be possible to use VLANs for this.
My normal network would be VLAN 1, the IoT network 2.
My HA instance would get two virtual network interfaces for each vlan. Port will be tagged.
On my openwrt router I'd like to implement this in such a way that VLAN 1 is just switched without routing, I would just follow the Dumb AP tutorial for that, just omit the wireless.

For VLAN 2 I need a bit help.
I want the wireless interface to connect to VLAN2 and the IoT traffic to be routed to my HA instance. I know this can be done with createing a new interface and device from br-lan.2.
But thats as far as I came, I don't know how to set the rest, I tried and either it became completely unreachable or the devices could communicate across networks.

Currently I am starting from a fresh reset of the settings.
Thanks!

Your fritzbox is the main router, so this needs to be aware of both networks.

Is the fritzbox running OpenWrt or the FritzOS? If the latter, does it have the option for setting static routes?

Its running FritzOS, but it does have the option yes.

Great. What you need to do is:

  • create a static route in the main router: 192.168.1.0/24 via 192.168.178.x where x is the IP address your OpenWrt router has on the main network.
  • On the OpenWrt router, disable masquerading on the upstream firewall zone (likely lan based on what you've shown, but would need to see the config to be sure)
  • Again, on the OpenWrt router, create a forwarding rule from lan > iot.
  • And, also on the OpenWrt router, you'll probably want to add (if not already done) a rule to block the iot devices from reaching the rest of the lan (except maybe your HA server).

I tried to follow your instructions, however the openwrt became unreachable after applying.

Fritzbox:
image

Changes in the Openwrt GUI:

# /etc/config/dhcp
uci set dhcp.iso=dhcp
uci set dhcp.iso.interface='iso'
uci set dhcp.iso.start='100'
uci set dhcp.iso.limit='150'
uci set dhcp.iso.leasetime='12h'
# /etc/config/firewall
uci add firewall zone # =cfg0edc81
uci set firewall.@zone[-1].name='iso'
uci set firewall.@zone[-1].input='REJECT'
uci set firewall.@zone[-1].output='ACCEPT'
uci set firewall.@zone[-1].forward='REJECT'
uci add_list firewall.@zone[-1].network='iso'
uci add firewall forwarding # =cfg0fad58
uci set firewall.@forwarding[-1].src='lan'
uci set firewall.@forwarding[-1].dest='iso'
uci del firewall.cfg01e63d.syn_flood
uci del firewall.cfg03dc81.masq
uci set firewall.cfg01e63d.synflood_protect='1'
# /etc/config/network
uci add network bridge-vlan # =cfg07a1b0
uci set network.@bridge-vlan[-1].device='br-lan'
uci set network.@bridge-vlan[-1].vlan='1'
uci add_list network.@bridge-vlan[-1].ports='lan1:u*'
uci add_list network.@bridge-vlan[-1].ports='lan2:u*'
uci add_list network.@bridge-vlan[-1].ports='lan3:t*'
uci add_list network.@bridge-vlan[-1].ports='lan4:u*'
uci add network bridge-vlan # =cfg08a1b0
uci set network.@bridge-vlan[-1].device='br-lan'
uci set network.@bridge-vlan[-1].vlan='2'
uci add_list network.@bridge-vlan[-1].ports='lan3:t'
uci add network device # =cfg090f15
uci set network.@device[-1].type='bridge'
uci set network.@device[-1].name='br-iso'
uci add_list network.@device[-1].ports='br-lan.2'
uci set network.@device[-1].bridge_empty='1'
uci add network device # =cfg0a0f15
uci set network.@device[-1].type='bridge'
uci set network.@device[-1].name='br-com'
uci add_list network.@device[-1].ports='br-lan.1'
uci set network.@device[-1].bridge_empty='1'
uci set network.lan.device='br-com'
uci set network.iso=interface
uci set network.iso.proto='static'
uci set network.iso.device='br-iso'
uci set network.iso.ipaddr='192.168.1.1'
uci set network.iso.netmask='255.255.255.0'

Please post your complete config:

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:
grafik
Remember to redact passwords, MAC addresses and any public IP addresses you may have:

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

Now it stayed reachable, maybe I had a typo before . But now the devices on the wireless dont get an IP. (I did activate the static route in the fritz box)

root@OpenWrt:~# ubus call system board
{
        "kernel": "6.6.86",
        "hostname": "OpenWrt",
        "system": "MediaTek MT7621 ver:1 eco:3",
        "model": "TP-Link Archer AX23 v1",
        "board_name": "tplink,archer-ax23-v1",
        "rootfs_type": "squashfs",
        "release": {
                "distribution": "OpenWrt",
                "version": "24.10.1",
                "revision": "r28597-0425664679",
                "target": "ramips/mt7621",
                "description": "OpenWrt 24.10.1 r28597-0425664679",
                "builddate": "1744562312"
        }
}
root@OpenWrt:~# cat /etc/config/network

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 'fd41:1728:c73a::/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 'lan'
        option device 'br-com'
        option proto 'static'
        option ipaddr '192.168.178.8'
        option netmask '255.255.255.0'
        option ip6assign '60'
        option gateway '192.168.178.1'

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

config interface 'wan6'
        option device 'wan'
        option proto 'dhcpv6'

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

config bridge-vlan
        option device 'br-lan'
        option vlan '2'
        list ports 'lan3:t'

config device
        option type 'bridge'
        option name 'br-iso'
        list ports 'br-lan.2'
        option bridge_empty '1'

config device
        option type 'bridge'
        option name 'br-com'
        list ports 'br-lan.1'
        option bridge_empty '1'

config interface 'iso'
        option proto 'static'
        option device 'br-iso'
        option ipaddr '192.168.1.1'
        option netmask '255.255.255.0'

root@OpenWrt:~# cat /etc/config/wireless

config wifi-device 'radio0'
        option type 'mac80211'
        option path '1e140000.pcie/pci0000:00/0000:00:01.0/0000:02:00.0'
        option band '2g'
        option channel '1'
        option htmode 'HE20'
        option cell_density '0'

config wifi-iface 'default_radio0'
        option device 'radio0'
        option network 'iso'
        option mode 'ap'
        option ssid 'redacted'
        option encryption 'sae-mixed'
        option hidden '1'
        option key 'redacted'
        option ocv '0'

config wifi-device 'radio1'
        option type 'mac80211'
        option path '1e140000.pcie/pci0000:00/0000:00:01.0/0000:02:00.0+1'
        option band '5g'
        option channel '36'
        option htmode 'HE80'
        option disabled '1'

config wifi-iface 'default_radio1'
        option device 'radio1'
        option network 'lan'
        option mode 'ap'
        option ssid 'OpenWrt'
        option encryption 'none'

root@OpenWrt:~# cat /etc/config/dhcp

config dnsmasq
        option domainneeded '1'
        option boguspriv '1'
        option filterwin2k '0'
        option localise_queries '1'
        option rebind_protection '1'
        option rebind_localhost '1'
        option local '/lan/'
        option domain 'lan'
        option expandhosts '1'
        option nonegcache '0'
        option cachesize '1000'
        option authoritative '1'
        option readethers '1'
        option leasefile '/tmp/dhcp.leases'
        option resolvfile '/tmp/resolv.conf.d/resolv.conf.auto'
        option nonwildcard '1'
        option localservice '1'
        option ednspacket_max '1232'
        option filter_aaaa '0'
        option filter_a '0'

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

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

config odhcpd 'odhcpd'
        option maindhcp '0'
        option leasefile '/tmp/hosts/odhcpd'
        option leasetrigger '/usr/sbin/odhcpd-update'
        option loglevel '4'

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

root@OpenWrt:~# cat /etc/config/firewall

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

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

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

config forwarding
        option src 'lan'
        option dest '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 rule
        option name 'Allow-IPSec-ESP'
        option src 'wan'
        option dest 'lan'
        option proto 'esp'
        option target 'ACCEPT'

config rule
        option name 'Allow-ISAKMP'
        option src 'wan'
        option dest 'lan'
        option dest_port '500'
        option proto 'udp'
        option target 'ACCEPT'

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

config forwarding
        option src 'lan'
        option dest 'iso'

Delete:

Edit the lan to use br-lan.1:

config interface 'lan'
        option device 'br-lan.1'
        option proto 'static'
        option ipaddr '192.168.178.8'
        option netmask '255.255.255.0'
        option ip6assign '60'
        option gateway '192.168.178.1'

And iso to use br-lan.2

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

Reboot and test again.

I thought this was necessary bc the wireless cant use the interface if its directly based on the vlan

No, WiFi is connected to the network name.

Weird, I could swear the GUI wouldn't let me choose iso as wireless network when its device was the vlan bridge. But anyways.

That didnt work either sadly, they still get disconnected.

Sun Apr 13 22:08:05 2025 daemon.info hostapd: phy0-ap0: STA 10:52:1c:07:98:56 IEEE 802.11: authenticated
Sun Apr 13 22:08:05 2025 daemon.info hostapd: phy0-ap0: STA 10:52:1c:07:98:56 IEEE 802.11: associated (aid 4)
Sun Apr 13 22:08:05 2025 daemon.notice hostapd: phy0-ap0: AP-STA-CONNECTED 10:52:1c:07:98:56 auth_alg=open
Sun Apr 13 22:08:05 2025 daemon.info hostapd: phy0-ap0: STA 10:52:1c:07:98:56 WPA: pairwise key handshake completed (RSN)
Sun Apr 13 22:08:05 2025 daemon.notice hostapd: phy0-ap0: EAPOL-4WAY-HS-COMPLETED 10:52:1c:07:98:56
Sun Apr 13 22:08:05 2025 daemon.info hostapd: phy0-ap0: STA 10:52:1c:06:ef:9e IEEE 802.11: disassociated

Let’s see the updated complete configs.

root@OpenWrt:~# ubus call system board
at /etc/config/wireless
cat /etc/config/dhcp
cat /etc/config/fir{
        "kernel": "6.6.86",
        "hostname": "OpenWrt",
        "system": "MediaTek MT7621 ver:1 eco:3",
        "model": "TP-Link Archer AX23 v1",
        "board_name": "tplink,archer-ax23-v1",
        "rootfs_type": "squashfs",
        "release": {
                "distribution": "OpenWrt",
                "version": "24.10.1",
                "revision": "r28597-0425664679",
                "target": "ramips/mt7621",
                "description": "OpenWrt 24.10.1 r28597-0425664679",
                "builddate": "1744562312"
        }
}
root@OpenWrt:~# cat /etc/config/network

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 'fd41:1728:c73a::/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 'lan'
        option device 'br-lan.1'
        option proto 'static'
        option ipaddr '192.168.178.8'
        option netmask '255.255.255.0'
        option ip6assign '60'
        option gateway '192.168.178.1'

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

config interface 'wan6'
        option device 'wan'
        option proto 'dhcpv6'

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

config bridge-vlan
        option device 'br-lan'
        option vlan '2'
        list ports 'lan4:t'

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

root@OpenWrt:~# cat /etc/config/wireless

config wifi-device 'radio0'
        option type 'mac80211'
        option path '1e140000.pcie/pci0000:00/0000:00:01.0/0000:02:00.0'
        option band '2g'
        option channel '1'
        option htmode 'HE20'
        option cell_density '0'

config wifi-iface 'default_radio0'
        option device 'radio0'
        option network 'iso'
        option mode 'ap'
        option ssid ''
        option encryption 'sae-mixed'
        option hidden '1'
        option key ''
        option ocv '0'

config wifi-device 'radio1'
        option type 'mac80211'
        option path '1e140000.pcie/pci0000:00/0000:00:01.0/0000:02:00.0+1'
        option band '5g'
        option channel '36'
        option htmode 'HE80'
        option disabled '1'

config wifi-iface 'default_radio1'
        option device 'radio1'
        option network 'lan'
        option mode 'ap'
        option ssid 'OpenWrt'
        option encryption 'none'

root@OpenWrt:~# cat /etc/config/dhcp

config dnsmasq
        option domainneeded '1'
        option boguspriv '1'
        option filterwin2k '0'
        option localise_queries '1'
        option rebind_protection '1'
        option rebind_localhost '1'
        option local '/lan/'
        option domain 'lan'
        option expandhosts '1'
        option nonegcache '0'
        option cachesize '1000'
        option authoritative '1'
        option readethers '1'
        option leasefile '/tmp/dhcp.leases'
        option resolvfile '/tmp/resolv.conf.d/resolv.conf.auto'
        option nonwildcard '1'
        option localservice '1'
        option ednspacket_max '1232'
        option filter_aaaa '0'
        option filter_a '0'

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

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

config odhcpd 'odhcpd'
        option maindhcp '0'
        option leasefile '/tmp/hosts/odhcpd'
        option leasetrigger '/usr/sbin/odhcpd-update'
        option loglevel '4'

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

root@OpenWrt:~# cat /etc/config/firewall

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

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

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

config forwarding
        option src 'lan'
        option dest '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 rule
        option name 'Allow-IPSec-ESP'
        option src 'wan'
        option dest 'lan'
        option proto 'esp'
        option target 'ACCEPT'

config rule
        option name 'Allow-ISAKMP'
        option src 'wan'
        option dest 'lan'
        option dest_port '500'
        option proto 'udp'
        option target 'ACCEPT'

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

config forwarding
        option src 'lan'
        option dest 'iso'

You have input set to reject but you haven’t allowed dhcp and dns. For now, set this to accept for testing.

Also, you don’t have the upstream dns server defined.

The firewall rule worked

Great. You can set input back to reject and add a rule to accept dns (udp+tcp port 53) and dhcp (udp port 67)

Hm, not sure I did that right. Could you doublecheck

config rule
        option src 'iso'
        option name 'Iso_dns'
        option src_port '53'
        option dest_port '53'
        option target 'ACCEPT'

config rule
        option src 'iso'
        option name 'Iso_dhcp'
        list proto 'udp'
        option target 'ACCEPT'
        option src_port '67'
        option dest_port '67'

Remove the source ports.

Ok that works and the devices are showing. Thank you so much!

My proxmox now shows me martian package errors from the other net. Do you know by chance hoe to fix that as well? (The IPs are proxmox itself and the fritzbox)

May 18 00:23:31 pve kernel: IPv4: martian source 255.255.255.255 from 192.168.178.11, on dev eth0
May 18 00:23:31 pve kernel: ll header: 00000000: ff ff ff ff ff ff 02 c4 dc 2b 20 a4 08 00
May 18 00:23:49 pve kernel: IPv4: martian source 255.255.255.255 from 192.168.178.1, on dev eth0
May 18 00:23:49 pve kernel: ll header: 00000000: ff ff ff ff ff ff 2c 3a fd e5 8f a8 08 00