I have 3 cAP AXes connected to a CRS328 bridge. One of the cAP AXes is a CAPsMAN server. I have configured 2 SSIDs on different VLANs: one for trusted devices (VLAN 10) and one for untrusted/guest devices (VLAN 20). The goal is to isolate the wireless stations on the guest network so that they have Internet breakout but cannot see any traffic from other devices on the same network.
The CAPsMAN server has set datapath.client-isolation=yes
on the guest network. In my experiments, this works pretty well for clients connected to the same BSSID, but not when the 2 wireless stations are connected to different BSSIDs (either on the same AP or a different AP). datapath.traffic-processing=on-capsman
is not currently not supported on devices with a Qualcomm driver (wifi-qcom
package).
So I figured I need bridge firewall rules to isolate that traffic.
My Proposed Solution
To be able to break out to the Internet, the clients would need to use DHCPv4 to obtain network information and ARP to resolve the MAC address of the default gateway. Both these protocols use Ethernet/IPv4 broadcasts. I do not want these broadcasts to reach other nodes, so I decided to use bridge destination NAT to change the MAC address to the address of the gateway. This works great.
On IPv6, the clients would use SLAAC to obtain network information. This requires the clients to be able to send IPv6 NDP Router Solicitations to MAC 33:33:00:00:00:02
and IPv6 ff02::2
. After that, they would use IPv6 NDP Neighbor Solicitation by sending a solicited-node multicast to the gateway at 33:33:FF:AA:AA:AA
and ff02::1:ffaa:aaaa
. I again use a destination NAT rule to make sure all solicited-node multicasts are directed to the gateway.
Finally, I use the bridge filter to:
- allow traffic from and to the gateway MAC address
- allow all IPv6 NDP multicast frames
- drop all traffic between WiFi interfaces (on the same AP)
- drop everything else
Bridge NAT
/interface bridge nat
add action=dst-nat chain=dstnat comment="From GUEST WLAN: redirect all IPv4 \
broadcasts to GW" in-interface-list=GUEST_WLANS packet-type=broadcast \
to-dst-mac-address=AA:AA:AA:AA:AA:AA
add action=dst-nat chain=dstnat comment="From GUEST WLAN: solicited-node \
multicast only to GW" dst-mac-address=33:33:FF:00:00:00/FF:FF:FF:00:00:00 \
in-interface-list=GUEST_WLANS to-dst-mac-address=33:33:FF:AA:AA:AA
- This translates Ethernet broadcasts to the all-As MAC address of the gateway to take care of DHCPv4 and ARP broadcasts.
- It redirects all IPv6 solicited-node multicasts to the gateway.
Bridge Filter
The bridge filter would then allow all traffic from and to the gateway, as well as IPv6 NDP router + neighbor solicitations and advertisements and drop everything else:
/interface bridge filter
add action=accept chain=forward comment="Allow all from GW" src-mac-address=\
AA:AA:AA:AA:AA:AA/FF:FF:FF:FF:FF:FF
add action=accept chain=forward comment="Allow all to GW" dst-mac-address=\
AA:AA:AA:AA:AA:AA/FF:FF:FF:FF:FF:FF
add action=drop chain=forward comment="Drop GUEST radio to GUEST radio"
in-interface-list=GUEST_WLANS out-interface-list=GUEST_WLANS
add action=accept chain=forward comment="Allow solicited-node multicast to GW" \
dst-mac-address=33:33:FF:AA:AA:AA/FF:FF:FF:FF:FF:FF
add action=accept chain=forward comment=\
"Allow GUEST WLANS to send IPv6 multicasts (RA&RS + NS&NA) on ether1" \
dst-mac-address=33:33:00:00:00:00/FF:FF:FF:FF:FF:00 \
in-interface-list=GUEST_WLANS out-interface=ether1
add action=drop chain=forward log=yes log-prefix=br-drop-forward-policy
The gateway itself has no filter rules because, being a relatively slow single-core CRS328, I did not want to disturb its bridge fast path.
Caveats
Information leakage. Isolated clients will always see:
- DHCPv4 broadcasts from the gateway. Clients thus learn MAC and IP address of other hosts in the network from the Offer and ACK DHCPv4 messages. But I noticed this happens for clients connected to the same BSSID even with
datapath.client-isolation=yes
set, so even MikroTik themselves are not able to filter this. - ARP broadcasts sent by the gateway. This happens when the gateway does its duplicate address detection (DAD) before offering a DHCPv4 address and periodically later.
Note that flooded unknown unicasts nor multicasts are a problem, because the bridge filter will drop any frames that do not originate from the gateway MAC address.
Feedback?
Any feedback on this approach? Could this setup be better/tighter?
One problem I can see is that bridge filters disable bridge FastPath and would be a bottleneck once you have more than ~10 devices on an AP (based on ~10% CPU usage when a single client runs a speedtest).