Fixing IPv6 on UniFi guest wireless network

Problem statement

My UniFi home network (some APs, some switches, whole lotta devices) is split between the trusted and guest WLANs.

Since I don’t want my corp devices on the trusted WLAN1, they sit on the guest WLAN. And up until recently, the IPv6 support wasn’t working on the guest network due to the way UniFi Cloud Key configures it.

This is a quick note explaining how to fix it, expanding on the IPv6 on UniFi guest wireless network gist by Mic Szillat2.

Root cause

The root cause for the issue is that the Ethernet bridge tables configured on the APs completely block IPv6 from reaching the guest network3:

$ ebtables -t nat -L
# [...]
Bridge chain: GUESTIN, entries: 17, policy: ACCEPT
# [...]
-p IPv6 -j DROP 
# [...]

Bridge chain: GUESTOUT, entries: 6, policy: ACCEPT
# [...]
-p IPv6 -j DROP 
# [...]


The solution is – to add a bunch of stanzas allowing IPv6 and stateless IPv6 autoconfig to work. By prepending the necessary ebtables entries, that punch the appropriately sized hole, to the Eth bridge config.

In order for it to sustain device restarts and reconfigs, it is advisable not to fight the UniFi ecosystem.

Therefore, two things are needed:

Add router’s MAC to “Excepted devices” under broadcast/multicast filtering

On 7.2.94 UniFi controller this is done in Settings (wheel) → Wireless Networks$guest_network:

excepted devices

In the picture above I’ve added aa:bb:cc:dd:ee:ff and ff:ee:dd:cc:bb:aa MAC addresses to the excepted devices. Only the MAC of your router suffices here.

In the background what happens is that UniFi AP will then attempt to call:

iwpriv athX bcfiltenable 0
iwpriv athX add_bcfiltmac aa:bb:cc:dd:ee:ff
iwpriv athX add_bcfiltmac ff:ee:dd:cc:bb:aa
iwpriv athX bcfiltenable 1            

during interface initialization4. Presumably to exempt these macs from the broadcast filter.

Modify Ethernet bridge tables to allow IPv6

For this second part, GUI has no power here™. And ssh-ing into the Cloud Key is necessary.

What is needed – in particular – is this mysterious per-site file5. This file, I manually created under /srv/unifi/data/sites/default6 on my system contains the following:

# don't call home (unrelated to this post, but good to have)
# to enable IPv6 on the guest network
config.system_cfg.2=ebtables.101.cmd=-t nat -I GUESTOUT 1 -p IPv6 -s aa:bb:cc:00:00:00/ff:ff:ff:00:00:00 -j ACCEPT
config.system_cfg.3=ebtables.102.cmd=-t nat -I GUESTOUT 2 -p IPv6 --ip6-proto ipv6-icmp --ip6-icmp-type neighbour-advertisement -j ACCEPT
config.system_cfg.4=ebtables.103.cmd=-t nat -I GUESTIN  1 -p IPv6 -d aa:bb:cc:00:00:00/ff:ff:ff:00:00:00 -j ACCEPT
config.system_cfg.5=ebtables.104.cmd=-t nat -I GUESTIN  2 -p IPv6 --ip6-proto ipv6-icmp --ip6-icmp-type router-solicitation -j ACCEPT
config.system_cfg.6=ebtables.105.cmd=-t nat -I GUESTIN  3 -p IPv6 --ip6-proto ipv6-icmp --ip6-icmp-type neighbour-advertisement -j ACCEPT
config.system_cfg.7=ebtables.106.cmd=-t nat -I GUESTIN  4 -p IPv6 --ip6-proto ipv6-icmp --ip6-icmp-type neighbour-solicitation -j ACCEPT

(Assuming aa:bb:cc:dd:ee:ff is the router7, I – just like Mic – used just a prefix of the entire MAC address, as I don’t think it hurts anything)

This will cause the provisioning system to first execute these rules (and then add the default ones, including the infamous -p IPv6 -j DROP). But given that the rules above allow communication with the router (to and from) and then a few selected ICMP messages to make the stateless autoconfig, it punches just the right hole for the IPv6 to start working.


Obviously after this is all saved, you need to re-provision all the APs.

After that, you can use ebtables -t nat -L to verify the changes took place. That, plus the fact IPv6 should be working now.

Closing words

Wow, from a few lines in a gist to a novel. In under an hour and half. Not bad.

In all seriousness, why isn’t IPv6 working on the guest network on UniFi out of the box? I don’t know. Fortunately, there is a workaround.

  1. I’m not particularly keen on the plethora of corp-operated spyware that is force-installed (and unavoidable) on all corp machines.

  2. Not that there’s anything wrong with the gist; it’s just that it lacks a bunch of context. So either you know what file is and where it should be located, or you’d be lost.

  3. I mean, yes, that’s one possible way of dealing with IPv6 configuration. Thank you, UniFi.

  4. The curiosity that it seems to be failing on the current firmware version with Interface doesn't accept private ioctl...<CR>add_bcfiltmac (8BFD): Bad address is a cherry I shall leave for some other time.

  5. Mysterious… because try finding official documentation for it. C’mon, I’ll wait.

  6. Because my UniFi “Site” is creatively named default, the location has default as the last directory name. YMMV. If you can’t find it, find / -type d -name sites or even find / -name might help locate the unifi data root.

  7. You might want to add similar entries for your local DNS server, if it happens to be different from your router.