I have a properly segmented home network. Eight VLANs, zone-based firewall, IoT devices isolated from the rest. It works exactly as designed. Except for two Bose SoundTouch speakers that refuse to play music from my phone.
This isn’t a firewall misconfiguration. It isn’t a missing mDNS rule. It’s a limitation in the SoundTouch network stack that took me an evening of systematic debugging to pin down, and one line of iptables to fix.
The setup #
My home network runs on a UniFi Dream Machine SE with a fairly standard VLAN layout:
| Network | Subnet | VLAN | Purpose |
|---|---|---|---|
| Home | 10.0.3.0/24 | 30 | Phones, laptops, tablets |
| IoT | 10.0.100.0/24 | 100 | Smart home devices |
The Home network is in the Internal firewall zone. IoT has its own dedicated zone with default-deny toward Internal, plus specific allow rules for things like Home Assistant. Traffic from Internal to IoT is allowed.
Two Bose SoundTouch speakers live in the IoT VLAN:
- SoundTouch SA-5 (wired) -bathroom
- SoundTouch Lifestyle (WiFi) -living room
Both running firmware 27.0.6. Each network has its own SSID -Home on 5 GHz only, IoT on 2.4 + 5 GHz. mDNS reflection is enabled on both networks.
AirPlay from my iPhone or Mac to the SoundTouch speakers doesn’t work. Move the speakers to the Home network -works instantly.
Why not just move them to Home? #
The obvious answer is: put the speakers on the same VLAN as your phone and be done with it. That’s what most forum posts suggest. That’s what Bose support will tell you. And yes -it works.
But I’m not going to do that.
I spend my days designing security architectures for financial institutions. I build detection-as-code frameworks, threat hunting apps, and data observability tools that catch when a single endpoint goes silent out of a thousand. The entire point of my professional work is that security boundaries exist for a reason, and convenience is not a valid justification for weakening them.
A Bose speaker runs firmware that hasn’t been updated since August 2022. It has a web server, an open API on port 8090, and no security patches in sight. It belongs in the IoT VLAN -behind a firewall that blocks it from reaching my laptops, my phones, my home NAS, my work environment. Every device in my IoT network is there because I don’t fully trust it, and a speaker with abandoned firmware is a textbook example of why.
Moving it to the Home network means every device on that VLAN -the speaker included -can freely communicate with my Mac where I have SSH keys, VPN credentials, and access to production systems. That’s not a theoretical risk. It’s the kind of lateral movement path I’d flag in a security review at work. I’m not going to create one at home because AirPlay is inconvenient.
The right solution is to keep the security boundary intact and find a way to make AirPlay work across it. That’s what the rest of this post is about.
The obvious suspects (all innocent) #
Firewall rules #
First thing I checked. The zone-based firewall has a rule allowing traffic from the Home network to the IoT network. I verified it was active, matching correctly, and in the right position (before the default block).
To be thorough, I temporarily set both source and destination to ANY. Still nothing.
But here’s the thing -other IoT devices responded just fine from the Home network:
$ ping 10.0.100.5 # Home Assistant → OK (4ms)
$ ping 10.0.100.150 # Front door controller → OK (5ms)
$ ping 10.0.100.6 # Doorbird → OK (4ms)
$ ping 10.0.100.103 # Zigbee gateway → OK (22ms)
$ ping 10.0.100.172 # SoundTouch Living Room → timeout
$ ping 10.0.100.234 # SoundTouch Bathroom Speaker → timeout
Same firewall rules, same VLAN, same direction. Four devices respond, two don’t. Not a firewall problem.
mDNS / Bonjour discovery #
mDNS reflection was already enabled on both networks. I verified with dns-sd:
$ dns-sd -B _airplay._tcp
Browsing for _airplay._tcp
20:35:15.450 Add local. _airplay._tcp. Living Room
20:35:15.450 Add local. _airplay._tcp. Bathroom
My Mac sees both speakers. Discovery works perfectly. The speakers show up in the AirPlay menu. They just refuse to connect when you select them.
WiFi multicast #
I enabled Multicast Enhancement (IGMPv3) on both SSIDs to ensure multicast-to-unicast conversion was working properly on the APs. No change.
The actual test #
To rule out any network-layer issue, I connected my MacBook directly to the IoT SSID:
$ ifconfig en0 | grep inet
inet 10.0.100.102
$ ping 10.0.100.172 # SoundTouch Living Room
64 bytes from 10.0.100.172: icmp_seq=0 ttl=64 time=166ms
$ nc -z 10.0.100.172 7000 # AirPlay port
Connection succeeded!
$ nc -z 10.0.100.172 8090 # SoundTouch API
Connection succeeded!
Everything works from the same subnet. Ping, AirPlay port (7000), SoundTouch API (8090) -all open and responding.
Switched back to Home network:
$ ifconfig en0 | grep inet
inet 10.0.3.209
$ ping 10.0.100.172
Request timeout
$ nc -z 10.0.100.172 7000
timeout
$ nc -z 10.0.100.172 8090
timeout
Same speaker, same Mac, same AP. The only difference is that traffic now routes through the gateway instead of staying on the same L2 segment. The traceroute confirmed packets reach the UDM gateway (10.0.3.1) but never make it to the speaker -or rather, the speaker gets them but never responds.
Root cause #
Bose SoundTouch has a simplified network stack. It accepts a default gateway via DHCP (I confirmed this through the SoundTouch API on port 8090), but it appears to silently drop traffic that arrives from a different subnet.
The speaker works fine for outbound connections -it reaches Bose’s streaming servers, gets firmware updates, communicates with the SoundTouch app when you’re on the same network. But when an incoming packet arrives with a source IP outside its local /24, the speaker ignores it.
This isn’t documented anywhere by Bose. The SoundTouch web UI has no routing configuration. The API exposes IP and MAC but nothing about gateway settings. There’s no way to configure this behavior.
The firmware (27.0.6 from August 2022) is the latest available -Bose has effectively ended updates for the SoundTouch line.
The fix: NAT masquerade #
If the speaker only responds to traffic from its local subnet, we make the traffic look local.
On the UniFi Dream Machine SE (via SSH):
|
|
This tells the UDM to rewrite the source IP of any packet from Home (10.0.3.x) heading to IoT (10.0.100.x). The speaker sees the packet coming from 10.0.100.1 (the gateway’s IoT interface) instead of 10.0.3.209 (my Mac). It responds to the gateway, which translates the response back to the original source.
After adding this rule:
$ ping 10.0.100.172
64 bytes from 10.0.100.172: icmp_seq=0 ttl=63 time=50ms
$ ping 10.0.100.234
64 bytes from 10.0.100.234: icmp_seq=0 ttl=63 time=3ms
AirPlay connects instantly. Music plays. Both speakers.
Making it persistent #
The iptables rule doesn’t survive a UDM reboot. On UniFi OS (Debian-based), the cleanest approach I found is a @reboot cron job:
|
|
The sleep 30 gives the network stack time to come up. The -C check before -A prevents duplicate rules if cron fires twice.
One caveat: UniFi firmware updates may reset the crontab. Worth checking after each upgrade.
Going deeper: what if you could fix the firmware? #
The masquerade rule works. But it’s a workaround -the actual problem is inside the speaker. I wanted to understand why.
The SoundTouch runs Linux #
The SA-5 (internal codename: “burns”) runs Linux 3.x on an ARM SoC. Port 17000 exposes a TAP (Test Access Point) console with a limited command set. On firmware 27.0.6, you get:
$ echo "network status" | nc 203.0.113.1 17000
<Status primaryIsUp="true" primaryIPAddress="10.0.100.234">
<interfaceInfo name="eth0" type="wired" state="up">
<ipInfo IPAddress="10.0.100.234" SubnetMask="255.255.255.0" />
</interfaceInfo>
<interfaceInfo name="usb0" type="wired" state="up">
<ipInfo IPAddress="203.0.113.1" SubnetMask="255.255.255.252" />
</interfaceInfo>
</Status>
Notice what’s missing: no gateway, no routing table, no DNS. The TAP console exposes IP and subnet mask but nothing about L3 routing. The speaker gets a default gateway via DHCP -I confirmed this -but there’s no way to inspect or modify routing behavior through any available interface.
The locked door #
Older SoundTouch firmware (pre-v16) had two commands that opened full root shell access:
local_services on-started telnetd, accessible via CTRL-C escape sequence on the serial ETAP interfaceremote_services on-started SSH/telnet on network interfaces
Firmware 27.0.6 removed both. Type either command and you get Command not found. Bose patched the debug access but left the broken network stack untouched. The last firmware update was August 2022. No more are coming -Bose is shutting down SoundTouch services entirely.
The firmware downgrade path #
I had a spare SA-5 in a closet. Unused, expendable, perfect for experiments.
The micro-USB “SETUP” port on the back exposes a USB gadget interface at 203.0.113.1/30. Your computer gets 203.0.113.2 automatically. Over this interface, port 17008 serves a firmware update page that the normal WiFi/ethernet interfaces don’t expose:
$ curl http://203.0.113.1:17008/update.html
<title>Bose SoundTouch Wi-Fi Update</title>
<div class="center">From: 27.0.6</div>
An archive on Archive.org has every SA-5 firmware version from 9.0 to 27.0.6. I downloaded 15.0.20 -old enough to have local_services, new enough to be Bluetooth-capable.
The first upload attempt returned HTTP 409 -the device rejected the downgrade. After a sys factorydefault through the TAP console, the same upload returned HTTP 200 and the speaker rebooted into firmware 15.0.20:
$ echo "sys ver" | nc 203.0.113.1 17000
BoseApp version: 15.0.20.37272.2363762
$ echo "local_services on" | nc 203.0.113.1 17000
local services on
local_services on works again. The command is accepted. Telnetd should be running.
The last wall #
Except it isn’t -not on the USB interface. The local_services command starts the daemon, but the root shell escape sequence (CTRL-C → e → login as root) only works through the physical ETAP serial interface. That’s the 3.5mm AUX IN jack on the back, speaking RS232 at 115200 baud through a TTL converter.
I don’t have the cable. A USB-TTL converter (CH340 or FTDI) costs about $5 and would get me a root shell in minutes. From there: ip route show, iptables -L, maybe even patching the routing table or adding a startup script that fixes the cross-subnet response behavior permanently.
The security irony #
Here’s what makes this interesting from a security perspective.
I put these speakers in an isolated IoT VLAN specifically because I don’t trust their firmware. And I was right not to -the firmware has known CVEs, an unauthenticated API on port 8090, a TAP console with no authentication on port 17000, and a firmware update interface that accepts downgrades after a factory reset. From the same VLAN, anyone can:
- Read device configuration and WiFi credentials via the API
- Reboot the device or change its settings via TAP
- Downgrade the firmware to a version with root shell access
- Flash arbitrary firmware through the USB update page
The IoT VLAN isolation isn’t paranoia. It’s the minimum responsible configuration for a device like this.
But the same simplified network stack that creates the cross-VLAN problem is also, in a twisted way, a form of accidental security. The speaker ignores routed traffic from other subnets. An attacker on a different VLAN can’t reach port 17000 or 8090 even if the firewall allows it -the speaker simply won’t respond. The masquerade rule I added is the thing that actually opens the attack surface from the Home VLAN.
I added it anyway, scoped to just the Home-to-IoT direction, because the alternative -putting the speaker on the Home VLAN -would be worse. With masquerade, the speaker sees traffic from the gateway IP. With VLAN bridging, it sees traffic from every device on the network, and every device sees it.
Trade-offs. That’s what network security always comes down to.
The takeaway #
If you’re running a segmented network with IoT devices on a separate VLAN and AirPlay won’t connect to your Bose speakers despite correct firewall rules and working mDNS:
- Test from the same subnet first -confirm the speaker actually works
- Test from across the VLAN -if other IoT devices respond but Bose doesn’t, it’s the speaker, not the network
- Add a NAT masquerade rule for traffic from your client VLAN to the IoT VLAN
The speaker isn’t broken. Your firewall isn’t misconfigured. Bose just shipped a network stack that doesn’t handle routed traffic. A single iptables rule fixes it.
And keep in mind -this is Bose. Not some no-name brand with a rushed-to-market IoT device. This is a premium, established company charging premium prices, shipping firmware with unauthenticated debug consoles, known CVEs, and a network stack that silently drops valid routed traffic. If this is the state of security and network engineering from a brand people trust by default, imagine what’s running on the $15 smart plug you bought without thinking twice.
And if you’re the type who can’t leave it at that -there’s a firmware archive, a USB update port, and a 3.5mm serial console waiting for someone with a $5 cable and a free afternoon.
Speakers: Bose SoundTouch SA-5 and Lifestyle, firmware 27.0.6. Gateway: UniFi Dream Machine SE.