Warning: count(): Parameter must be an array or an object that implements Countable in /usr/local/www/wordpress/wp-includes/post-template.php on line 284

A tale of two AirPorts

The concept of a “guest” WiFi network, open to anyone but isolated from the rest of my home LAN has always been appealing… The feature has existed in the AirPort Extreme routers since the third generation (circa 2009).

Originally the feature would disappear the moment you turn off router functionality and place the AirPort in bridge mode. This combined with my insistence on letting my FreeBSD box serve as the Internet gateway for my household negated my ability to use the feature.

In a firmware update some time ago, this feature re-appeared, even while the router was in bridge mode… I tried it once, discovered I could get no traffic to flow through it, shrugged it off and disabled it…

Until…

Fast forward at least a few years, lacklustre performance from my nearly five-year old 802.11n AP and the presence of an 802.11ac chip in my shiny new iPhone 6 lead me to the Apple Store to acquire a more modern variant, the 802.11ac Time Capsule (no inventory on straight up router at the time).

Yesterday morning in a sudden fit of curiosity, I re-enabled the Guest Network feature from the iOS AirPort Utility. As before, I could see the new ESSID but could not actually get an IPv4 or IPv6 address… No traffic would pass through.

Feeling in a playful mood, I took it one step further and did a quick Google on the issue. Turns out all guest network traffic is tagged with 802.1Q VLAN 1003. Why didn’t you just say so?!

Let’s try this out, should be just a few quick changes to /etc/rc.conf:

cloned_interfaces="vlan1003"
ifconfig_vlan1003="inet 172.31.1.1/24 vlan 1003 vlandev em1"
ifconfig_vlan1003_ipv6="inet6 2610:1e8:800:101::1/64"

dhcpd_ifaces="em1 vlan1003"
rtadvd_interfaces="em1 vlan1003"

It works! I can now connect to the guest network and receive an IP from the IPv4 and IPv6 subnet assigned for that purpose… All I need to do now is add some sane firewall rules to isolate the traffic and restrict the throughput.

Wait… Why am I limited to ~ 0.5 Mbps downloads on the guest network while my uploads can saturate the full 5 Mbps upstream of my Shaw connection? What’s happening here? I haven’t shoved this traffic through DUMMYNET, not yet!?

I assumed the issue was on my side, maybe an MTU issue caused by the extra 4 byte 802.1Q VLAN tag? Maybe one of the two D-Link switches between my FreeBSD gateway and the AirPort just couldn’t tolerate it?

I swapped things around, let the new AirPort get cuddly with the FreeBSD box in the basement… Nothing between its gigabit Intel NIC and the AirPort. No difference.

Maybe one of these VLAN specific options on the Intel NIC was giving me grief, much like “TCP Segmentation Offload” issues have caused me much confusion in the past? Nope… Disabling all of these made no difference.

Alright… Let’s take advantage of OS X’s FreeBSD based userland… I disabled IPv4 on the Mac Mini’s NIC and used a couple quick ifconfig commands to create a VLAN 1003 interface. No speed issues. The VLAN tagging clearly is not the issue.

Then I did some more Googling… There are plenty of threads where people are experiencing the same issue. Some dating back to late 2013. Some have experienced the issue with a Junos based router and another with a pfSense box… Is FreeBSD the common ground here? There’s another thread where someone was attempting this with Tomato but they were having issues setting up the VLAN in general, rather than the speed issue.

One more thing to try this morning… Let’s see how the old AirPort behaves in this exact scenario… I plug it in, hide the primary network and enable guest networking… and… It works flawlessly. No speed issues!

Alright, I’ll cause some speed issues and finish what I started.

In /etc/sysctl.conf:

net.inet.ip.fw.one_pass=0

In /boot/loader.conf:

dummynet_load="YES"
kern.hz="1000"

In /etc/rc.firewall

${fwcmd} pipe 1 config bw 5M
${fwcmd} pipe 2 config bw 512Kbits/s
${fwcmd} add 60 pipe 1 ip from any to any xmit vlan1003
${fwcmd} add 70 pipe 2 ip from any to any recv vlan1003

The above rules go right after my NAT rule. The one_pass sysctl causes the traffic to re-enter the IPFW ruleset after the pipe.

Then to isolate my guest network:

${fwcmd} add pass ip from any to any out recv vlan1003 xmit em0
${fwcmd} add pass ip from any to me 53 recv vlan1003
${fwcmd} add deny ip from any to me recv vlan1003
${fwcmd} add deny ip from any to any out recv vlan1003 xmit em1

So this all works… but why does the old AirPort succeed where the new one fails? The traffic from the new AirPort even has to traverse through the ethernet ports of the new Airport based on my current topology.

I could just keep the old AirPort around for the purpose of the guest network but this should be do-able with just the one AP.

This smells like a firmware bug. The old AirPort is on firmware 7.6.4. The new AirPort is on firmware 7.7.3. I assume this could be fixed in the future. I’ve opened a support case with Apple and scheduled a call for Tuesday evening… Although I fear this setup treads pretty far into “unsupported” territory.

I have until October 5th to return the new AirPort if it doesn’t want to play nice. That said, I window shopped the web and could not find a sub $300 access point that is 802.11ac, dual band and capable of ESSID to VLAN mapping.

Am I asking for too much?

Leave a Reply