Struggling with VLANs due to some gaps in my knowledge - looking for help on an e2e solution

I understand the concept of VLANs and why I need to utilize them to segregate my guest, IoT, and primary/management networks. I also understand the concept of tagged and untagged VLANs. But there are clearly some concepts in the end-to-end solution that I am missing as I gave up after frantically trying various methods of configuration to make this all work as expected.

Let me start with my current network setup, and then i'll detail my goal.

Currently I have 3 Netgear R7800 "dumb" APs that I flashed the latest OpenWRT. They each have 1 SSID (my management/primary network). The SSIDs are the same (name and encryption/auth) for each AP to support devices throughout the house & roaming (with different channels of course). Each AP is connected via one ethernet cable to an unmanaged switch. The unmanaged switch is connected to the LAN port of my 2-port Protectli FW2 router, which is also running the latest OpenWrt. The WAN port of the router is connected to a cable modem. Relatively simple setup I think, and this is all working fine.

What I want to do is add 2 more SSIDs to each AP: 1 for IoT devices and another for guest devices. I realize that VLANs are needed to support this, so I purchased a Zyxel GS1900-8 managed switch, which I also flashed to the latest OpenWrt.

So my final network configuration will have 3 dumb APs, each with 3 SSIDs: "primary", "IoT", and "guest". The "primary" SSID/network has access to everything (it can reach out to clients on all 3 networks + the internet). The "guest" and "IoT" networks/SSIDs can only hit the internet and cannot initiate communications with any other clients on the local network (not even clients on their respective networks). Each AP will be hardwired to the managed switch on a separate port. So port 1 on the managed switch will be connected to the router's LAN port, and port 2 on the managed switch will be connected to one of the 3 APs, with port 3 on the switch connected to another one of the 3 APs, etc.

I'm having trouble understanding how I need to configure OpenWrt on my APs, managed switch, and router to make all of this work. I assume each SSID will have it's own VLAN. Say the "primary" network/SSID will be VLAN 10, and the "IoT" network will be VLAN 20, and the "guest" network will be VLAN 30. How exactly do I configure interfaces, devices, wireless, firewall zones, etc on the APs, switch, and router to make all of this fit together?

I'm a little anxious about this as I don't want to break my existing functional (and very important to me) network in the process.

The unmanaged switch, as it seems you already know, cannot be used with VLANs.

Have you replaced the unmanaged switch with this new managed one?

Start with the router. The additional networks will be created on the router along with the appropriate firewall rules (and typically also a DHCP server). Each network will be associated with a VLAN on the router's lan port. The new networks will be tagged.

Then, the switch will be configured with the same 3 VLANs as are present on the router's lan port -- this will apply for the port that connects to the router, as well as the 3 ports that connect to the APs. These are called trunks (a port/cable that carries multiple networks). I would also recommend that you create an access (a 'normal', one network, untagged) port for each of the networks on the switch so that you can test that is functioning properly with a wired computer.

Finally, you'll setup your APs with the same VLAN trunk configuration on the port that connects to the switch. You'll then make 2 new unmanaged network interfaces and then create two new SSIDs that you will connect to those new networks.

Start by creating just one new network and get it working end-to end. Then you can use the same recipe to create the final one.

You can use this tutorial to setup a new network on the router. Skip the wifi part, of course. When you've got everything else done, post the config here (specific instructions below) and we'll review and show you how to setup the VLAN on the lan port.

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/dhcp
cat /etc/config/firewall

I haven't replaced the unmanaged switch with the managed one yet. I'll do that now and then all network devices will be VLAN-capable.

After setting up the guest network (per the guide you linked to) on one of the APs, do I post the output of the listed commands from the AP, the switch, or the router? I'm running OpenWrt on all APs and the switch and the router.

No, do this on the main router, omitting the wifi part of the tutorial.

Make sure you set your switch with a non-conflicting IP address.

The router, please.

1 Like

Thanks for the clarifications. Here is the requested output from my router:

root@protectli-router:~# ubus call system board
{
	"kernel": "6.6.73",
	"hostname": "protectli-router",
	"system": "Intel(R) Celeron(R) CPU  J1800  @ 2.41GHz",
	"model": "Protectli FW2",
	"board_name": "protectli-fw2",
	"rootfs_type": "ext4",
	"release": {
		"distribution": "OpenWrt",
		"version": "24.10.0",
		"revision": "r28427-6df0e3d02a",
		"target": "x86/64",
		"description": "OpenWrt 24.10.0 r28427-6df0e3d02a",
		"builddate": "1738624177"
	}
}
root@protectli-router:~# 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 'fd64:333:8758::/48'
	option packet_steering '1'

config device
	option name 'br-lan'
	option type 'bridge'
	list ports 'eth1'

config interface 'lan'
	option device 'br-lan'
	option proto 'static'
	option ipaddr '192.168.88.1'
	option netmask '255.255.255.0'

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

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

config interface 'tailscale'
	option proto 'none'
	option device 'tailscale0'

config device
	option type 'bridge'
	option name 'br-guest'
	option bridge_empty '1'

config interface 'guest'
	option proto 'static'
	option device 'br-guest'
	option ipaddr '192.168.10.1'
	option netmask '255.255.255.0'
root@protectli-router:~# 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 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'
	option sequential_ip '1'
	list rebind_domain '<REDACTED>'

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

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'

<HOSTS REDACTED (DHCP clients)>

config dhcp 'guest'
	option interface 'guest'
	option start '100'
	option limit '150'
	option leasetime '12h'
root@protectli-router:~# cat /etc/config/firewall

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

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

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

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 'tailscale'
	option input 'ACCEPT'
	option output 'ACCEPT'
	option forward 'ACCEPT'
	option masq '1'
	list network 'tailscale'

config forwarding
	option src 'tailscale'
	option dest 'lan'

config forwarding
	option src 'tailscale'
	option dest 'wan'

config forwarding
	option src 'lan'
	option dest 'tailscale'

config rule
	option name 'Allow_mDNS'
	list proto 'udp'
	option src '*'
	option src_port '5353'
	list dest_ip '224.0.0.251'
	option dest_port '5353'
	option target 'ACCEPT'

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

config forwarding
	option src 'guest'
	option dest 'wan'

config rule

config rule
	option name 'Allow-DNS-Guest'
	option src 'guest'
	option dest_port '53'
	option target 'ACCEPT'

config rule
	option name 'Allow-DHCP-Guest'
	list proto 'udp'
	option src 'guest'
	option dest_port '67'
	option target 'ACCEPT'

Looks 99% good.

You have an orphaned config rule between the forwarding statement and the guest dns rule -- delete that orphaned line:

And for the guest bridge, add eth1.10 so it looks like this:

config device
	option type 'bridge'
	option name 'br-guest'
	list ports 'eth1.10'

Restart and that's it... router is done (with the guest network). You'll repeat the process (later) with the IoT network.

Next, we can work with the switch. We just need to see /etc/config/network and we need to know what ports connect to the router and each of the APs.

Thanks for that! Note that I have the router connected to the switch on port 1, and ports 2-4 contain ethernet connections for the 3 APs.

Here's the switch config:

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 'fdd1:c18d:7ff7::/48'
	option packet_steering '1'

config device 'switch'
	option name 'switch'
	option type 'bridge'
	option macaddr 'fc:22:f4:f8:f6:94'
	list ports 'lan1'
	list ports 'lan2'
	list ports 'lan3'
	list ports 'lan4'
	list ports 'lan5'
	list ports 'lan6'
	list ports 'lan7'
	list ports 'lan8'

config bridge-vlan 'lan_vlan'
	option device 'switch'
	option vlan '1'
	option ports 'lan1 lan2 lan3 lan4 lan5 lan6 lan7 lan8'

config device
	option name 'switch.1'
	option macaddr 'fc:22:f4:f8:f6:94'

config interface 'lan'
	option device 'switch.1'
	option proto 'static'
	option ipaddr '192.168.88.99'
	option netmask '255.255.255.0'
	option ip6assign '60'
	option gateway '192.168.88.1'

You didn't mention which ports are used for the router and APs. I'm going to make some assumptions. You'll see the patterns, so you can always adjust if this is wrong:

  • lan1: router
  • lan2: AP1
  • lan3: AP2
  • lan4: AP3
  • lan5: main lan
  • lan6: main lan
  • lan7: guest
  • lan8: iot

The guest and IoT ports will be for testing, you can assign them later however you want.

First thing we're going to do is to edit this:

so that it looks like this:

config bridge-vlan
	option device 'switch'
	option vlan '1'
	list ports 'lan1:u*' 
	list ports 'lan2:u*' 
	list ports 'lan3:u*' 
	list ports 'lan4:u*'
	list ports 'lan5:u*'
	list ports 'lan6:u*'

Now we'll add a bridge VLAN for the guest network:

config bridge-vlan
	option device 'switch'
	option vlan '10'
	list ports 'lan1:t' 
	list ports 'lan2:t' 
	list ports 'lan3:t' 
	list ports 'lan4:t' 
	list ports 'lan7:u*' 

And finally add an unmanaged interface for the guest network:

config interface 'guest'
	option device 'switch.10'
	option proto 'none'

Restart the switch after these changes. Connect the router to port 1, and then you can connect a computer to port 6 and it should get an address in the main lan, and then port 7 and it should get one in the guest network.

Assuming this works as expected, we'll now move on to your APs.... post the following from your APs:

ubus call system board
cat /etc/config/network

Sorry about the ports. I edited my post above w/ the port info, but too late it seems. Here it is again:

On the switch, port 1 is connected to the router. Ports 2-4 are connected to the APs. The other 4 ports are vacant.

I'll look at your instructions now for the switch and report back.

Looks like my assumptions line up nicely with your desired port allocations. Report back when you've got those done.

Hey great, that worked! Port 6 gives me a 192.168.88.0/24 address and port 7 gives me a 192.168.10.0/24 address.

Here's the output from one of my APs (let me know if you need this from the other 2, but those should be largely the same):

root@basement-sunroom-ap:~# ubus call system board
{
	"kernel": "6.6.73",
	"hostname": "basement-sunroom-ap",
	"system": "ARMv7 Processor rev 0 (v7l)",
	"model": "Netgear Nighthawk X4S R7800",
	"board_name": "netgear,r7800",
	"rootfs_type": "squashfs",
	"release": {
		"distribution": "OpenWrt",
		"version": "24.10.0",
		"revision": "r28427-6df0e3d02a",
		"target": "ipq806x/generic",
		"description": "OpenWrt 24.10.0 r28427-6df0e3d02a",
		"builddate": "1738624177"
	}
}
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 'fd2f:ef1c:810::/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'
	option proto 'dhcp'

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

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

Only need the one, assuming that the others are the same or very similar.

I'm going to assume that port lan1 is used as the uplink to the switch, and we'll set ports 3 and 4 as guest and IoT (again, for testing). Port 2 will be the normal lan.

Start by adding bridge VLANs:

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

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

Edit the lan interface to use br-lan.1:

config interface 'lan'
	option device 'br-lan.1'
	option proto 'dhcp'

And add an unmanaged interface for the guest:

config interface 'guest'
	option device 'br-lan.10'
	option proto 'none'

Now you can add a wifi SSID and associate it with network guest. Obviously restart after making these changes. You'll be able to plug a computer into port 2 and get the normal lan, and port 3 to get the guest network, and the new wifi guest network should work as expected, too.

Repeat for the other APs.

If all of that is successful, you can follow the same recipe to create your IoT network, with minor adaptations which should hopefully be apparent by the discussion we've been having and the patterns involved here.

Let me know how you get on, and if you have any questions about adding that last network.

It looks like this partially works. I can connect to the guest SSID and i get a guest IP, but I can still communicate with other clients on my management network. For example, as a guest I can still ssh to my router and access the luci web interface. How do i complete the isolation?

What tests are you running, specifically?

I don’t see any reason why you would have any inter-vlan routing.

For example:

  1. Connect to port 3 on the AP. I get a 192.168.10.0/24 address (guest network).
  2. I then attempt to visit 192.168.88.1 (the IP of my router). I can see the luci interface and even ssh to the router at this address. I can also access other clients on the .88.0 network (such as my switch and other random DHCP clients).

Are you using a computer with both Ethernet and WiFi? Is WiFi still enabled? If so, disable it and test again.

Nope, i turned off wifi on the laptop before i connected to the guest port on the AP. I also ran the same test while connected via wifi (with no other connection) to the guest ssid with the same results.

Let’s review the final router configuration.

cat /etc/config/network
cat /etc/config/firewall
root@protectli-router:~# 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 'fd64:333:8758::/48'
	option packet_steering '1'

config device
	option name 'br-lan'
	option type 'bridge'
	list ports 'eth1'

config interface 'lan'
	option device 'br-lan'
	option proto 'static'
	option ipaddr '192.168.88.1'
	option netmask '255.255.255.0'

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

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

config interface 'tailscale'
	option proto 'none'
	option device 'tailscale0'

config device
	option type 'bridge'
	option name 'br-guest'
	list ports 'eth1.10'

config interface 'guest'
	option proto 'static'
	option device 'br-guest'
	option ipaddr '192.168.10.1'
	option netmask '255.255.255.0'
root@protectli-router:~# cat /etc/config/firewall

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

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

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

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 'tailscale'
	option input 'ACCEPT'
	option output 'ACCEPT'
	option forward 'ACCEPT'
	option masq '1'
	list network 'tailscale'

config forwarding
	option src 'tailscale'
	option dest 'lan'

config forwarding
	option src 'tailscale'
	option dest 'wan'

config forwarding
	option src 'lan'
	option dest 'tailscale'

config rule
	option name 'Allow_mDNS'
	list proto 'udp'
	option src '*'
	option src_port '5353'
	list dest_ip '224.0.0.251'
	option dest_port '5353'
	option target 'ACCEPT'

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

config forwarding
	option src 'guest'
	option dest 'wan'

config rule
	option name 'Allow-DNS-Guest'
	option src 'guest'
	option dest_port '53'
	option target 'ACCEPT'

config rule
	option name 'Allow-DHCP-Guest'
	list proto 'udp'
	option src 'guest'
	option dest_port '67'
	option target 'ACCEPT'

There is no firewall allowances for lan > guest or guest > lan

The only possible path is mdns, but I don't think this is relevant (you can try removing or disabling this rule, though):

From your computer while it is connected to the guest network, let's see the output of:

traceroute 192.168.88.x

where x gets replaced by the last octet of a device that is on the lan (and not the router itself).