Isolating all SSIDs from each other

Hello!

I have been experimenting with guest wifi isolation, and am wondering what the best way to properly separate all SSIDs on a single router would be. My XR500 running 22.03.0-rc6 is currently set up as follows: one 5 ghz SSID (wlan0, no client isolation), and two 2.4 ghz SSIDs on the same radio. The first of the 2.4 ghz ones (wlan1) is for general access and does not use client isolation. The second 2.4 ghz SSID (wlan1-1) is used as a guest network, set up with client isolation using this guide.

Devices in this guest SSID cannot ping each other, which is what I want. But if a device on wlan0 pings wlan1, they are able to communicate, and vice versa. I'd like to completely isolate SSIDs (including isolating the two 2.4 ghz SSIDs from each other) so that devices in wlan0 cannot interact or monitor devices in wlan1, wlan1-1, or any new SSIDs that I may make. What would be the best way of going about this?

I imagine this problem would involve a fairly simple firewall zone/rule, but I am still new to OpenWRT and am not certain of what it would be.

My firewall zone settings are here:

Assign each SSID in different interface, then each interface to its own firewall zone, and control the allowed flows with firewall.

3 Likes

Thank you for the reply.

I understand how to make different interfaces and firewall zones, but I'm not sure about controlling flows with the the firewall. Would it be possible for you to point me to an example of these sorts of rules that would be applicable to this situation?

By default all forwardings from one zone to another are blocked. So you'll need to create forwardings, like the lan to wan.

Thank you again, I think I'm understanding it better now.

I have taken the following steps:

  1. Create two new identical firewall zones (one for 2.4g, one for 5g) and set them up with forwarding to wan like below:


    And the final product:

  2. Create two new identical interfaces (one for 2.4g, one for 5g) in the same way as in the guest network guide (DHCP server enabled, static address, etc). I've named them 2g_iso_interfce and 5g_iso_interfce.


    Assign each to its respective firewall zone, like below for the 2.4g SSID:

  3. In the network->wireless tab->edit wireless, change only the network for both wlan0 and wlan1 from lan to their respective interfaces. The image below is wlan1 (2.4g network):

This seems to work. When I try to ping from wlan1 to wlan0 now, I get this message:

Request timeout for icmp_seq 0
92 bytes from openwrt.lan (192.168.9.1): Destination Port Unreachable

Does my configuration look correct, and would this mean that isolation between the SSIDs is working correctly?

Yes it looks quite alright!

Please let me know if I should make a new thread for this, but I'm experiencing some incredibly strange behavior.

After I run through the steps from above, the interface separation works correctly until the router is restarted. The settings were saved through Luci at each point. After the restart, all zones start to be able to ping each other. The firewall zone rule that stops the original guest network (wlan1-1) from interacting with the router also ceases to work, and I can access Luci and SSH. To experiment, I reset everything from above back to when I only had the original guest network. I found that even adding one new zone and restarting the router made the input: reject zone rule for 'Guestzone' stop working.

This is the firewall config, with the last two entries about '5gIso' being the ones that make the reject rule stop working. If they are not present, the reject functionality works as expected:

config defaults
	option input 'ACCEPT'
	option output 'ACCEPT'
	option forward 'REJECT'
	option synflood_protect '1'
	option flow_offloading '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 masq '1'
	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 output 'ACCEPT'
	option forward 'REJECT'
	option input 'REJECT'
	option name 'Guestzone'
	list network 'GUEST'

config forwarding
	option src 'Guestzone'
	option dest 'wan'

config rule
	option enabled '0'

config rule
	option name 'Guest DHCP and DNS'
	option src 'Guestzone'
	option dest_port '53 67 68'
	option target 'ACCEPT'

config rule
	option name 'Guest DHCP'
	list proto 'udp'
	option src 'Guestzone'
	option dest_port '67 68'
	option target 'ACCEPT'
	option enabled '0'

config rule
	option name 'Guest DNS'
	option src 'Guestzone'
	option dest_port '53'
	option target 'ACCEPT'
	option enabled '0'

config rule
	option name 'Guest-Block-All'
	option src 'Guestzone'
	option target 'REJECT'

config zone
	option name '5gIso'
	option input 'REJECT'
	option output 'ACCEPT'
	option forward 'REJECT'

config forwarding
	option src '5gIso'
	option dest 'wan'

Could this new '5gIso' zone be overwriting 'Guestzone' somehow?

I hope that you bind the uci interface with the SSID and not the uci interface with a physical interface.

This is never used as it is not bound to any interface.
Post the fowllowing: uci export network; uci export wireless

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 'fd99:ff86:6f06::/48'

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

config interface 'lan'
	option device 'br-lan'
	option proto 'static'
	option ipaddr '192.168.1.1'
	option netmask '255.255.255.0'
	option ip6assign '60'

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

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

config switch
	option name 'switch0'
	option reset '1'
	option enable_vlan '1'

config switch_vlan
	option device 'switch0'
	option vlan '1'
	option ports '1 2 3 4 6t'

config switch_vlan
	option device 'switch0'
	option vlan '2'
	option ports '5 0t'

config interface 'GUEST'
	option proto 'static'
	option ipaddr '192.168.8.1'
	option netmask '255.255.255.0'

And the wireless, with keys and SSIDs replaced with placeholders:

config wifi-device 'radio0'
	option type 'mac80211'
	option path 'soc/1b500000.pci/pci0000:00/0000:00:00.0/0000:01:00.0'
	option band '5g'
	option cell_density '0'
	option country 'US'
	option channel '161'
	option htmode 'VHT80'

config wifi-iface 'default_radio0'
	option device 'radio0'
	option network 'lan'
	option mode 'ap'
	option ssid 'FirstSSID'
	option encryption 'psk2'
	option key '123'

config wifi-device 'radio1'
	option type 'mac80211'
	option path 'soc/1b700000.pci/pci0001:00/0001:00:00.0/0001:01:00.0'
	option band '2g'
	option country 'US'
	option cell_density '0'
	option channel 'auto'
	option htmode 'HT20'

config wifi-iface 'default_radio1'
	option device 'radio1'
	option network 'lan'
	option mode 'ap'
	option ssid 'SecondSSID'
	option encryption 'psk2'
	option key '456'

config wifi-iface 'wifinet2'
	option device 'radio1'
	option mode 'ap'
	option ssid 'ThirdSSID'
	option encryption 'psk2'
	option isolate '1'
	option key '789'
	option network 'GUEST'

What does nft list ruleset say?

table inet fw4 {
	flowtable ft {
		hook ingress priority filter
		devices = { eth0, eth1, wlan0, wlan1, wlan1-1 }
	}

	chain input {
		type filter hook input priority filter; policy accept;
		iifname "lo" accept comment "!fw4: Accept traffic from loopback"
		ct state established,related accept comment "!fw4: Allow inbound established and related flows"
		tcp flags syn / fin,syn,rst,ack jump syn_flood comment "!fw4: Rate limit TCP syn packets"
		iifname "br-lan" jump input_lan comment "!fw4: Handle lan IPv4/IPv6 input traffic"
		iifname "wlan1-1" jump input_Guestzone comment "!fw4: Handle Guestzone IPv4/IPv6 input traffic"
	}

	chain forward {
		type filter hook forward priority filter; policy drop;
		meta l4proto { tcp, udp } flow add @ft
		ct state established,related accept comment "!fw4: Allow forwarded established and related flows"
		iifname "br-lan" jump forward_lan comment "!fw4: Handle lan IPv4/IPv6 forward traffic"
		iifname "wlan1-1" jump forward_Guestzone comment "!fw4: Handle Guestzone IPv4/IPv6 forward traffic"
		jump handle_reject
	}

	chain output {
		type filter hook output priority filter; policy accept;
		oifname "lo" accept comment "!fw4: Accept traffic towards loopback"
		ct state established,related accept comment "!fw4: Allow outbound established and related flows"
		oifname "br-lan" jump output_lan comment "!fw4: Handle lan IPv4/IPv6 output traffic"
		oifname "wlan1-1" jump output_Guestzone comment "!fw4: Handle Guestzone IPv4/IPv6 output traffic"
	}

	chain prerouting {
		type filter hook prerouting priority filter; policy accept;
		iifname "br-lan" jump helper_lan comment "!fw4: Handle lan IPv4/IPv6 helper assignment"
		iifname "wlan1-1" jump helper_Guestzone comment "!fw4: Handle Guestzone IPv4/IPv6 helper assignment"
	}

	chain handle_reject {
		meta l4proto tcp reject with tcp reset comment "!fw4: Reject TCP traffic"
		reject comment "!fw4: Reject any other traffic"
	}

	chain syn_flood {
		limit rate 25/second burst 50 packets return comment "!fw4: Accept SYN packets below rate-limit"
		drop comment "!fw4: Drop excess packets"
	}

	chain input_lan {
		jump accept_from_lan
	}

	chain output_lan {
		jump accept_to_lan
	}

	chain forward_lan {
		jump accept_to_wan comment "!fw4: Accept lan to wan forwarding"
		jump accept_to_lan
	}

	chain helper_lan {
	}

	chain accept_from_lan {
		iifname "br-lan" counter packets 1 bytes 61 accept comment "!fw4: accept lan IPv4/IPv6 traffic"
	}

	chain accept_to_lan {
		oifname "br-lan" counter packets 0 bytes 0 accept comment "!fw4: accept lan IPv4/IPv6 traffic"
	}

	chain input_wan {
		meta nfproto ipv4 udp dport 68 counter packets 0 bytes 0 accept comment "!fw4: Allow-DHCP-Renew"
		icmp type echo-request counter packets 0 bytes 0 accept comment "!fw4: Allow-Ping"
		meta nfproto ipv4 meta l4proto igmp counter packets 0 bytes 0 accept comment "!fw4: Allow-IGMP"
		meta nfproto ipv6 udp dport 546 counter packets 0 bytes 0 accept comment "!fw4: Allow-DHCPv6"
		ip6 saddr fe80::/10 icmpv6 type . icmpv6 code { mld-listener-query . no-route, mld-listener-report . no-route, mld-listener-done . no-route, mld2-listener-report . no-route } counter packets 0 bytes 0 accept comment "!fw4: Allow-MLD"
		icmpv6 type { destination-unreachable, time-exceeded, echo-request, echo-reply, nd-router-solicit, nd-router-advert } limit rate 1000/second counter packets 0 bytes 0 accept comment "!fw4: Allow-ICMPv6-Input"
		icmpv6 type . icmpv6 code { packet-too-big . no-route, parameter-problem . no-route, nd-neighbor-solicit . no-route, nd-neighbor-advert . no-route, parameter-problem . admin-prohibited } limit rate 1000/second counter packets 0 bytes 0 accept comment "!fw4: Allow-ICMPv6-Input"
		jump reject_from_wan
	}

	chain output_wan {
		jump accept_to_wan
	}

	chain forward_wan {
		icmpv6 type { destination-unreachable, time-exceeded, echo-request, echo-reply } limit rate 1000/second counter packets 0 bytes 0 accept comment "!fw4: Allow-ICMPv6-Forward"
		icmpv6 type . icmpv6 code { packet-too-big . no-route, parameter-problem . no-route, parameter-problem . admin-prohibited } limit rate 1000/second counter packets 0 bytes 0 accept comment "!fw4: Allow-ICMPv6-Forward"
		meta l4proto esp counter packets 0 bytes 0 jump accept_to_lan comment "!fw4: Allow-IPSec-ESP"
		udp dport 500 counter packets 0 bytes 0 jump accept_to_lan comment "!fw4: Allow-ISAKMP"
		jump reject_to_wan
	}

	chain accept_to_wan {
	}

	chain reject_from_wan {
	}

	chain reject_to_wan {
	}

	chain input_Guestzone {
		tcp dport { 53, 67, 68 } counter packets 0 bytes 0 accept comment "!fw4: Guest DHCP and DNS"
		udp dport { 53, 67, 68 } counter packets 0 bytes 0 accept comment "!fw4: Guest DHCP and DNS"
		meta l4proto tcp counter packets 0 bytes 0 jump handle_reject comment "!fw4: Guest-Block-All"
		meta l4proto udp counter packets 0 bytes 0 jump handle_reject comment "!fw4: Guest-Block-All"
		jump reject_from_Guestzone
	}

	chain output_Guestzone {
		jump accept_to_Guestzone
	}

	chain forward_Guestzone {
		jump accept_to_wan comment "!fw4: Accept Guestzone to wan forwarding"
		jump reject_to_Guestzone
	}

	chain helper_Guestzone {
	}

	chain accept_to_Guestzone {
		oifname "wlan1-1" counter packets 0 bytes 0 accept comment "!fw4: accept Guestzone IPv4/IPv6 traffic"
	}

	chain reject_from_Guestzone {
		iifname "wlan1-1" counter packets 0 bytes 0 jump handle_reject comment "!fw4: reject Guestzone IPv4/IPv6 traffic"
	}

	chain reject_to_Guestzone {
		oifname "wlan1-1" counter packets 0 bytes 0 jump handle_reject comment "!fw4: reject Guestzone IPv4/IPv6 traffic"
	}

	chain dstnat {
		type nat hook prerouting priority dstnat; policy accept;
	}

	chain srcnat {
		type nat hook postrouting priority srcnat; policy accept;
	}

	chain srcnat_wan {
		meta nfproto ipv4 masquerade comment "!fw4: Masquerade IPv4 wan traffic"
	}

	chain raw_prerouting {
		type filter hook prerouting priority raw; policy accept;
	}

	chain raw_output {
		type filter hook output priority raw; policy accept;
	}

	chain mangle_prerouting {
		type filter hook prerouting priority mangle; policy accept;
	}

	chain mangle_postrouting {
		type filter hook postrouting priority mangle; policy accept;
	}

	chain mangle_input {
		type filter hook input priority mangle; policy accept;
	}

	chain mangle_output {
		type route hook output priority mangle; policy accept;
	}

	chain mangle_forward {
		type filter hook forward priority mangle; policy accept;
	}
}

The only logical explanation I can see is that packet is classified as forward from wlan1-1
iifname "wlan1-1" jump forward_Guestzone comment "!fw4: Handle Guestzone IPv4/IPv6 forward traffic"
Then this forward_Guestzone has 2 jumps

		jump accept_to_wan comment "!fw4: Accept Guestzone to wan forwarding"
		jump reject_to_Guestzone

since the packet is not going to wan it goes to reject_to_Guestzone

		oifname "wlan1-1" counter packets 0 bytes 0 jump handle_reject comment "!fw4: reject Guestzone IPv4/IPv6 traffic"

which only blocks the packets going out of wlan1-1, not br-lan
So from chain forward it will jump handle_reject
which basically blocks only tcp
meta l4proto tcp reject with tcp reset comment "!fw4: Reject TCP traffic"
can you verify that only tcp doesn't work, but icmp or udp does work?