Sonos - Asus Router Merlin Yazfi Guest Network with One Way to Guest
Update 16/05/2024 notice: version 80.xx.xx.xx
After the mobile app update to version 80.xx.xx.xx, the method that the app use to discover speakers has completely changed. It is now required to allow destination UDP port 1900 (UPNP) traffic and source TCP port 1443 to flow to br0 instead:
iptables -I YazFiFORWARD -i wl0.1 -o br0 -s 172.27.15.3 -p udp --dport 1900 -j ACCEPT iptables -I YazFiFORWARD -i wl0.1 -o br0 -s 172.27.15.3 -p tcp --sport 1443 -j ACCEPT
Where 172.27.15.3 is the IP address of the Sonos system.
For Airplay to work it is also required to allow destination TCP ephemeral ports, source TCP 7000 (BBS), along with destination UDP 319:320 (PTP) ports to flow to br0:
iptables -I YazFiFORWARD -i wl0.1 -o br0 -s 172.27.15.3 -p tcp --dport 32768:65535 -j ACCEPT iptables -I YazFiFORWARD -i wl0.1 -o br0 -s 172.27.15.3 -p tcp --sport 7000 -j ACCEPT iptables -I YazFiFORWARD -i wl0.1 -o br0 -s 172.27.15.3 -p udp --dport 319:320 -j ACCEPT
Where 172.27.15.3 is the IP address of the Sonos system.
I've also noticed that Sonos also need source TCP 4444 (krb524) to br0 while running updates:
iptables -I YazFiFORWARD -i wl0.1 -o br0 -s 172.27.15.3 -p tcp --sport 4444 -j ACCEPT
Where 172.27.15.3 is the IP address of the Sonos system.
Relevant new tcpdumps:
# SONOS APP TESTING jarylc@RT-AX88U:/jffs/addons/YazFi.d/userscripts.d# tcpdump -i any src 172.27.15.3 and dst 172.27.14.98 08:23:59.721602 wl0.1 In IP 172.27.15.3.34242 > 172.27.14.98.upnp: UDP, length 741 08:23:59.721669 br0 Out IP 172.27.15.3.34242 > 172.27.14.98.upnp: UDP, length 741 08:23:59.721678 eth7 Out IP 172.27.15.3.34242 > 172.27.14.98.upnp: UDP, length 741 08:23:59.870068 wl0.1 In IP 172.27.15.3.1443 > 172.27.14.98.50146: Flags [S.], seq 165454314, ack 134039494, win 28960, options [mss 1460,sackOK,TS val 355714560 ecr 4169303348,nop,wscale 7], length 0 08:23:59.870090 br0 Out IP 172.27.15.3.1443 > 172.27.14.98.50146: Flags [S.], seq 165454314, ack 134039494, win 28960, options [mss 1460,sackOK,TS val 355714560 ecr 4169303348,nop,wscale 7], length 0 08:23:59.870093 eth7 Out IP 172.27.15.3.1443 > 172.27.14.98.50146: Flags [S.], seq 165454314, ack 134039494, win 28960, options [mss 1460,sackOK,TS val 355714560 ecr 4169303348,nop,wscale 7], length 0 08:23:59.926271 wl0.1 In IP 172.27.15.3.1443 > 172.27.14.98.50146: Flags [.], ack 157, win 235, options [nop,nop,TS val 355714574 ecr 4169303497], length 0 08:23:59.926303 br0 Out IP 172.27.15.3.1443 > 172.27.14.98.50146: Flags [.], ack 157, win 235, options [nop,nop,TS val 355714574 ecr 4169303497], length 0 08:23:59.926307 eth7 Out IP 172.27.15.3.1443 > 172.27.14.98.50146: Flags [.], ack 157, win 235, options [nop,nop,TS val 355714574 ecr 4169303497], length 0 08:23:59.926275 wl0.1 In IP 172.27.15.3.1443 > 172.27.14.98.50146: Flags [P.], seq 1:63, ack 157, win 235, options [nop,nop,TS val 355714574 ecr 4169303497], length 62 08:23:59.926330 br0 Out IP 172.27.15.3.1443 > 172.27.14.98.50146: Flags [P.], seq 1:63, ack 157, win 235, options [nop,nop,TS val 355714574 ecr 4169303497], length 62 08:23:59.926333 eth7 Out IP 172.27.15.3.1443 > 172.27.14.98.50146: Flags [P.], seq 1:63, ack 157, win 235, options [nop,nop,TS val 355714574 ecr 4169303497], length 62 08:23:59.926280 wl0.1 In IP 172.27.15.3.1443 > 172.27.14.98.50146: Flags [.], seq 63:1511, ack 157, win 235, options [nop,nop,TS val 355714574 ecr 4169303497], length 1448 08:23:59.926357 br0 Out IP 172.27.15.3.1443 > 172.27.14.98.50146: Flags [.], seq 63:1511, ack 157, win 235, options [nop,nop,TS val 355714574 ecr 4169303497], length 1448 08:23:59.926361 eth7 Out IP 172.27.15.3.1443 > 172.27.14.98.50146: Flags [.], seq 63:1511, ack 157, win 235, options [nop,nop,TS val 355714574 ecr 4169303497], length 1448 08:24:01.100909 wl0.1 In IP 172.27.15.3.1443 > 172.27.14.98.50146: Flags [P.], seq 2093:2124, ack 476, win 243, options [nop,nop,TS val 355714868 ecr 4169304590], length 31 08:24:01.100937 br0 Out IP 172.27.15.3.1443 > 172.27.14.98.50146: Flags [P.], seq 2093:2124, ack 476, win 243, options [nop,nop,TS val 355714868 ecr 4169304590], length 31 08:24:01.100942 eth7 Out IP 172.27.15.3.1443 > 172.27.14.98.50146: Flags [P.], seq 2093:2124, ack 476, win 243, options [nop,nop,TS val 355714868 ecr 4169304590], length 31 08:24:01.100913 wl0.1 In IP 172.27.15.3.1443 > 172.27.14.98.50146: Flags [F.], seq 2124, ack 476, win 243, options [nop,nop,TS val 355714868 ecr 4169304590], length 0 08:24:01.100960 br0 Out IP 172.27.15.3.1443 > 172.27.14.98.50146: Flags [F.], seq 2124, ack 476, win 243, options [nop,nop,TS val 355714868 ecr 4169304590], length 0 08:24:01.100963 eth7 Out IP 172.27.15.3.1443 > 172.27.14.98.50146: Flags [F.], seq 2124, ack 476, win 243, options [nop,nop,TS val 355714868 ecr 4169304590], length 0 08:24:01.190110 wl0.1 In IP 172.27.15.3.1443 > 172.27.14.98.50146: Flags [F.], seq 2124, ack 476, win 243, options [nop,nop,TS val 355714891 ecr 4169304590], length 0 08:24:01.190127 br0 Out IP 172.27.15.3.1443 > 172.27.14.98.50146: Flags [F.], seq 2124, ack 476, win 243, options [nop,nop,TS val 355714891 ecr 4169304590], length 0 08:24:01.190130 eth7 Out IP 172.27.15.3.1443 > 172.27.14.98.50146: Flags [F.], seq 2124, ack 476, win 243, options [nop,nop,TS val 355714891 ecr 4169304590], length 0 08:25:01.196936 wl0.1 In IP 172.27.15.3.33005 > 172.27.14.98.57454: UDP, length 741 08:25:03.196969 br0 Out IP 172.27.15.3.33005 > 172.27.14.98.57454: UDP, length 741 08:25:05.196976 eth7 Out IP 172.27.15.3.33005 > 172.27.14.98.57454: UDP, length 741 # AIRPLAY TESTING jarylc@RT-AX88U-0BC0:/tmp/home/root# tcpdump -i any src 172.27.15.3 and dst 172.27.14.110 tcpdump: data link type LINUX_SLL2 tcpdump: verbose output suppressed, use -v[v]... for full protocol decode listening on any, link-type LINUX_SLL2 (Linux cooked v2), snapshot length 262144 bytes 08:59:34.272732 wl0.1 In IP 172.27.15.3.bbs > 172.27.14.110.53646: Flags [S.], seq 361871852, ack 1905326041, win 28960, options [mss 1460,sackOK,TS val 356248160 ecr 2914930491,nop,wscale 7], length 0 08:59:34.272761 br0 Out IP 172.27.15.3.bbs > 172.27.14.110.53646: Flags [S.], seq 361871852, ack 1905326041, win 28960, options [mss 1460,sackOK,TS val 356248160 ecr 2914930491,nop,wscale 7], length 0 08:59:34.272769 eth7 Out IP 172.27.15.3.bbs > 172.27.14.110.53646: Flags [S.], seq 361871852, ack 1905326041, win 28960, options [mss 1460,sackOK,TS val 356248160 ecr 2914930491,nop,wscale 7], length 0 08:59:34.284023 wl0.1 In IP 172.27.15.3.bbs > 172.27.14.110.53646: Flags [.], ack 281, win 235, options [nop,nop,TS val 356248164 ecr 2914930539], length 0 08:59:34.284038 br0 Out IP 172.27.15.3.bbs > 172.27.14.110.53646: Flags [.], ack 281, win 235, options [nop,nop,TS val 356248164 ecr 2914930539], length 0 08:59:34.284041 eth7 Out IP 172.27.15.3.bbs > 172.27.14.110.53646: Flags [.], ack 281, win 235, options [nop,nop,TS val 356248164 ecr 2914930539], length 0 08:59:34.288263 wl0.1 In IP 172.27.15.3.bbs > 172.27.14.110.53646: Flags [P.], seq 1:977, ack 281, win 235, options [nop,nop,TS val 356248164 ecr 2914930539], length 976 08:59:34.288281 br0 Out IP 172.27.15.3.bbs > 172.27.14.110.53646: Flags [P.], seq 1:977, ack 281, win 235, options [nop,nop,TS val 356248164 ecr 2914930539], length 976 08:59:34.288285 eth7 Out IP 172.27.15.3.bbs > 172.27.14.110.53646: Flags [P.], seq 1:977, ack 281, win 235, options [nop,nop,TS val 356248164 ecr 2914930539], length 976 08:59:35.333401 wl0.1 In IP 172.27.15.3 > 172.27.14.110: ICMP 172.27.15.3 udp port 320 unreachable, length 112 08:59:35.333430 br0 Out IP 172.27.15.3 > 172.27.14.110: ICMP 172.27.15.3 udp port 320 unreachable, length 112 08:59:35.333435 eth7 Out IP 172.27.15.3 > 172.27.14.110: ICMP 172.27.15.3 udp port 320 unreachable, length 112 08:59:35.333405 wl0.1 In IP 172.27.15.3 > 172.27.14.110: ICMP 172.27.15.3 udp port 320 unreachable, length 142 08:59:35.333452 br0 Out IP 172.27.15.3 > 172.27.14.110: ICMP 172.27.15.3 udp port 320 unreachable, length 142 08:59:35.333455 eth7 Out IP 172.27.15.3 > 172.27.14.110: ICMP 172.27.15.3 udp port 320 unreachable, length 142 08:59:35.333408 wl0.1 In IP 172.27.15.3.46785 > 172.27.14.110.53647: Flags [S.], seq 4199358917, ack 972859376, win 28960, options [mss 1460,sackOK,TS val 356248426 ecr 2879974157,nop,wscale 7], length 0 08:59:35.333474 br0 Out IP 172.27.15.3.46785 > 172.27.14.110.53647: Flags [S.], seq 4199358917, ack 972859376, win 28960, options [mss 1460,sackOK,TS val 356248426 ecr 2879974157,nop,wscale 7], length 0 08:59:35.333477 eth7 Out IP 172.27.15.3.46785 > 172.27.14.110.53647: Flags [S.], seq 4199358917, ack 972859376, win 28960, options [mss 1460,sackOK,TS val 356248426 ecr 2879974157,nop,wscale 7], length 0 # UPDATE TESTING jarylc@RT-AX88U-0BC0:/tmp/home/root# tcpdump -i any src 172.27.15.3 or src 172.27.15.1 or src 172.27.15.3 08:22:01.901621 wl0.1 In IP 172.27.15.3.krb524 > 172.27.14.98.35390: Flags [R.], seq 0, ack 3400968069, win 0, length 0 08:22:01.901646 br0 Out IP 172.27.15.3.krb524 > 172.27.14.98.35390: Flags [R.], seq 0, ack 1, win 0, length 0 08:22:01.901653 eth7 Out IP 172.27.15.3.krb524 > 172.27.14.98.35390: Flags [R.], seq 0, ack 1, win 0, length 0
Overall, my latest script looks like this now:
HOME_ASSISTANT='172.27.14.254' MEDIA_RANGE='172.27.15.2-172.27.15.20' iptables -I YazFiFORWARD -i wl0.1 -o br0 -d ${HOME_ASSISTANT} -p tcp -m multiport --dports 1400,8123 -j ACCEPT iptables -I YazFiFORWARD -i wl0.1 -o br0 -m iprange --src-range "${MEDIA_RANGE}" -p tcp --dport 32768:65535 -j ACCEPT iptables -I YazFiFORWARD -i wl0.1 -o br0 -m iprange --src-range "${MEDIA_RANGE}" -p udp -m multiport --dports 319,320,1900 -j ACCEPT iptables -I YazFiFORWARD -i wl0.1 -o br0 -m iprange --src-range "${MEDIA_RANGE}" -p tcp -m multiport --sports 1400,1443,4444,7000 -j ACCEPT
End of update here, original post follows
Most recently I've discovered that Asuswrt-Merlin (community firmware for Asus routers) has a terminal UI interface `amtm`.
Within it there is a project called Yazfi by @jackyaz which provides a "feature expansion of guest Wi-Fi networks on AsusWRT-Merlin".
I've always wanted to move all my smart devices to another VLAN with only pinhole access to my main LAN. Thanks to Yazfi, the effort is reduced tremendously trying to configure these while leveraging on the Guest Network functionality of Asus Routers. With that, I started my project to reformat my Asus Router, rotating my Wi-Fi passwords and start moving everything over.
I did however encounter some issues with discovering Sonos devices on the mobile app even with `One way to guest` enabled, it was either totally not discovering or very slow, and decided to start digging into it.
Investigation
This section explains how I investigated how the Sonos works in my network under the hood and you can skip to the Solution section below if you only care about that!
Temporarily allowing two-way traffic between LAN and Guest Network
Since we are investigating how Sonos operates, I temporarily allowed two-way communication between the 2 networks in Yazfi configuration.
Enabling multicast routing
Since various online sources says that Sonos uses Simple Service Discovery Protocol (SSDP) and multicast DNS (mDNS) to support discoverability, for good measure, I enabled multicast routing under LAN > IPTV > Enable multicast routing
However I'm not 100% sure there is a need for this.
Installing entware and tcpdump on my router
You can follow these instructions to install entware on your router.
After installationof entware is complete, it's as simple as
jarylc@RT-AX88U:/tmp/home/root# opkg install tcpdump
Running tcpdump
After snooping around the UI and the Sonos App, the private IP addresses of the relevant devices are the following:
- My Android phone: 172.27.14.98 (172.27.14.x is my main LAN)
- One of my Sonos devices: 172.27.15.3 (172.27.15.x is my smart devices Guest network)
I limited the snooping to UDP packets only as that is what SSDP and mDNS primarily uses
jarylc@RT-AX88U:/jffs/addons/YazFi.d/userscripts.d# tcpdump -i any 'udp and (src 172.27.15.3 or src 172.27.14.98)' 09:26:30.044460 wl0.4 Out IP 172.27.14.98.37972 > 239.255.255.250.upnp: UDP, length 200 09:26:30.044469 wl0.1 Out IP 172.27.14.98.37972 > 239.255.255.250.upnp: UDP, length 200 09:26:30.044433 br0 M IP 172.27.14.98.37972 > 239.255.255.250.upnp: UDP, length 200 09:26:30.044582 wl0.4 Out IP 172.27.14.98.37972 > 255.255.255.255.upnp: UDP, length 200 09:26:30.044589 wl0.1 Out IP 172.27.14.98.37972 > 255.255.255.255.upnp: UDP, length 200 09:26:30.044443 br0 B IP 172.27.14.98.37972 > 255.255.255.255.upnp: UDP, length 200 09:26:30.045267 wl0.4 Out IP 172.27.14.98.37972 > 239.255.255.250.upnp: UDP, length 254 09:26:30.045274 wl0.1 Out IP 172.27.14.98.37972 > 239.255.255.250.upnp: UDP, length 254 09:26:30.045259 br0 M IP 172.27.14.98.37972 > 239.255.255.250.upnp: UDP, length 254 09:26:30.045539 wl0.4 Out IP 172.27.14.98.37972 > 255.255.255.255.upnp: UDP, length 254 09:26:30.045544 wl0.1 Out IP 172.27.14.98.37972 > 255.255.255.255.upnp: UDP, length 254 09:26:30.045530 br0 B IP 172.27.14.98.37972 > 255.255.255.255.upnp: UDP, length 254 09:26:30.048134 wl0.4 Out IP 172.27.14.98.5353 > mdns.mcast.net.5353: 1 PTR (QU)? _sonos._tcp.local. (35) 09:26:30.048139 wl0.1 Out IP 172.27.14.98.5353 > mdns.mcast.net.5353: 1 PTR (QU)? _sonos._tcp.local. (35) 09:26:30.048125 br0 M IP 172.27.14.98.5353 > mdns.mcast.net.5353: 1 PTR (QU)? _sonos._tcp.local. (35) 09:26:30.227307 wl0.1 M IP 172.27.15.3.5353 > mdns.mcast.net.5353: 0*- [0q] 1/0/6 PTR Sonos-XXXXXXXXXXXX@Media Room._sonos._tcp.local. (676) 09:26:30.266863 wl0.4 Out IP 172.27.14.98.37972 > 239.255.255.250.upnp: UDP, length 254 09:26:30.266871 wl0.1 Out IP 172.27.14.98.37972 > 239.255.255.250.upnp: UDP, length 254 09:26:30.266828 br0 M IP 172.27.14.98.37972 > 239.255.255.250.upnp: UDP, length 254 09:26:30.266945 wl0.4 Out IP 172.27.14.98.37972 > 255.255.255.255.upnp: UDP, length 254 09:26:30.266950 wl0.1 Out IP 172.27.14.98.37972 > 255.255.255.255.upnp: UDP, length 254 09:26:30.266840 br0 B IP 172.27.14.98.37972 > 255.255.255.255.upnp: UDP, length 254 09:26:30.580416 wl0.1 In IP 172.27.15.3.37360 > 172.27.14.98.37972: UDP, length 741 09:26:30.580456 br0 Out IP 172.27.15.3.37360 > 172.27.14.98.37972: UDP, length 741 09:26:31.072123 wl0.4 Out IP 172.27.14.98.5353 > mdns.mcast.net.5353: 2 PTR (QM)? _sonos._tcp.local. (35) 09:26:31.072128 wl0.1 Out IP 172.27.14.98.5353 > mdns.mcast.net.5353: 2 PTR (QM)? _sonos._tcp.local. (35) 09:26:31.071869 br0 M IP 172.27.14.98.5353 > mdns.mcast.net.5353: 2 PTR (QM)? _sonos._tcp.local. (35) 09:26:31.072203 wl0.4 Out IP 172.27.14.98.37972 > 239.255.255.250.upnp: UDP, length 200 09:26:31.072208 wl0.1 Out IP 172.27.14.98.37972 > 239.255.255.250.upnp: UDP, length 200 09:26:31.071885 br0 M IP 172.27.14.98.37972 > 239.255.255.250.upnp: UDP, length 200 09:26:31.072269 wl0.4 Out IP 172.27.14.98.37972 > 255.255.255.255.upnp: UDP, length 200 09:26:31.072274 wl0.1 Out IP 172.27.14.98.37972 > 255.255.255.255.upnp: UDP, length 200 09:26:31.071892 br0 B IP 172.27.14.98.37972 > 255.255.255.255.upnp: UDP, length 200 09:26:31.309102 wl0.1 In IP 172.27.15.3.38139 > 172.27.14.98.37972: UDP, length 741 09:26:31.309125 br0 Out IP 172.27.15.3.38139 > 172.27.14.98.37972: UDP, length 741 09:26:31.343765 wl0.4 Out IP 172.27.14.98.37972 > 239.255.255.250.upnp: UDP, length 254 09:26:31.343773 wl0.1 Out IP 172.27.14.98.37972 > 239.255.255.250.upnp: UDP, length 254 09:26:31.343737 br0 M IP 172.27.14.98.37972 > 239.255.255.250.upnp: UDP, length 254 09:26:31.343853 wl0.4 Out IP 172.27.14.98.37972 > 255.255.255.255.upnp: UDP, length 254 09:26:31.343858 wl0.1 Out IP 172.27.14.98.37972 > 255.255.255.255.upnp: UDP, length 254 09:26:31.343748 br0 B IP 172.27.14.98.37972 > 255.255.255.255.upnp: UDP, length 254 09:26:31.692594 wl0.1 In IP 172.27.15.3.38570 > 172.27.14.98.37972: UDP, length 741 09:26:31.692617 br0 Out IP 172.27.15.3.38570 > 172.27.14.98.37972: UDP, length 741 09:26:32.271746 wl0.4 Out IP 172.27.14.98.5353 > mdns.mcast.net.5353: 1 PTR (QU)? _sonos._tcp.local. (35) 09:26:32.271753 wl0.1 Out IP 172.27.14.98.5353 > mdns.mcast.net.5353: 1 PTR (QU)? _sonos._tcp.local. (35) 09:26:32.271598 br0 M IP 172.27.14.98.5353 > mdns.mcast.net.5353: 1 PTR (QU)? _sonos._tcp.local. (35) 09:26:32.278203 eth7 M IP 172.27.14.98.37972 > 239.255.255.250.upnp: UDP, length 254 09:26:32.278226 wl0.4 Out IP 172.27.14.98.37972 > 239.255.255.250.upnp: UDP, length 254 09:26:32.278232 wl0.1 Out IP 172.27.14.98.37972 > 239.255.255.250.upnp: UDP, length 254 09:26:32.278203 br0 M IP 172.27.14.98.37972 > 239.255.255.250.upnp: UDP, length 254 09:26:32.278296 wl0.4 Out IP 172.27.14.98.37972 > 255.255.255.255.upnp: UDP, length 254 09:26:32.278301 wl0.1 Out IP 172.27.14.98.37972 > 255.255.255.255.upnp: UDP, length 254 09:26:32.278214 br0 B IP 172.27.14.98.37972 > 255.255.255.255.upnp: UDP, length 254 09:26:32.465141 wl0.1 M IP 172.27.15.3.5353 > mdns.mcast.net.5353: 0*- [0q] 1/0/6 PTR Sonos-XXXXXXXXXXXX@Media Room._sonos._tcp.local. (676) 09:26:32.701778 wl0.1 In IP 172.27.15.3.41457 > 172.27.14.98.37972: UDP, length 741 09:26:32.701801 br0 Out IP 172.27.15.3.41457 > 172.27.14.98.37972: UDP, length 741 09:26:33.215347 wl0.4 Out IP 172.27.14.98.5353 > mdns.mcast.net.5353: 2 PTR (QM)? _sonos._tcp.local. (35) 09:26:33.215355 wl0.1 Out IP 172.27.14.98.5353 > mdns.mcast.net.5353: 2 PTR (QM)? _sonos._tcp.local. (35) 09:26:33.215331 br0 M IP 172.27.14.98.5353 > mdns.mcast.net.5353: 2 PTR (QM)? _sonos._tcp.local. (35) 09:26:33.905757 wl0.4 Out IP 172.27.14.98.37972 > 239.255.255.250.upnp: UDP, length 254 09:26:33.905763 wl0.1 Out IP 172.27.14.98.37972 > 239.255.255.250.upnp: UDP, length 254 09:26:33.905736 br0 M IP 172.27.14.98.37972 > 239.255.255.250.upnp: UDP, length 254 09:26:33.905846 wl0.4 Out IP 172.27.14.98.37972 > 255.255.255.255.upnp: UDP, length 254 09:26:33.905851 wl0.1 Out IP 172.27.14.98.37972 > 255.255.255.255.upnp: UDP, length 254 09:26:33.905744 br0 B IP 172.27.14.98.37972 > 255.255.255.255.upnp: UDP, length 254 09:26:34.034082 wl0.1 In IP 172.27.15.3.59807 > 172.27.14.98.37972: UDP, length 741 09:26:34.034122 br0 Out IP 172.27.15.3.59807 > 172.27.14.98.37972: UDP, length 741 09:26:34.220437 wl0.4 Out IP 172.27.14.98.5353 > mdns.mcast.net.5353: 3 PTR (QM)? _sonos._tcp.local. (35) 09:26:34.220444 wl0.1 Out IP 172.27.14.98.5353 > mdns.mcast.net.5353: 3 PTR (QM)? _sonos._tcp.local. (35) 09:26:34.220422 br0 M IP 172.27.14.98.5353 > mdns.mcast.net.5353: 3 PTR (QM)? _sonos._tcp.local. (35) 09:26:34.387343 wl0.1 M IP 172.27.15.3.5353 > mdns.mcast.net.5353: 0*- [0q] 1/0/6 PTR Sonos-XXXXXXXXXXXX@Media Room._sonos._tcp.local. (676)
The problem
09:26:30.580416 wl0.1 In IP 172.27.15.3.37360 > 172.27.14.98.37972: UDP, length 741 09:26:30.580456 br0 Out IP 172.27.15.3.37360 > 172.27.14.98.37972: UDP, length 741 09:26:31.309102 wl0.1 In IP 172.27.15.3.38139 > 172.27.14.98.37972: UDP, length 741 09:26:31.309125 br0 Out IP 172.27.15.3.38139 > 172.27.14.98.37972: UDP, length 741 09:26:32.701778 wl0.1 In IP 172.27.15.3.41457 > 172.27.14.98.37972: UDP, length 741 09:26:32.701801 br0 Out IP 172.27.15.3.41457 > 172.27.14.98.37972: UDP, length 741 09:26:34.034082 wl0.1 In IP 172.27.15.3.59807 > 172.27.14.98.37972: UDP, length 741 09:26:34.034122 br0 Out IP 172.27.15.3.59807 > 172.27.14.98.37972: UDP, length 741
Filtering out all the noise, I noticed that the Sonos device was trying to send a UDP packet from the ephemeral UDP ports (range 32768-65535) to my mobile device.
This is actually not surprising as that is how SSDP works as the device would switch to unicast after being discovered. Prior to this, I was not very familiar with SSDP and did not know that.
I noticed in a previous tcpdump before enabling two-way communication that this was being blocked:
00:13:65.371058 wl0.1 In IP 172.27.15.3.46814 > 172.27.14.98.49972: UDP, length 737 00:13:54.373059 wl0.1 Out IP 172.27.15.1 > 172.27.15.3: ICMP 172.27.14.98 udp port 49972 unreachable, length 556
Solution
Adding custom firewall allow rules to Yazfi to allow this UDP traffic from Sonos devices
With that I created a file called `myscript.sh` within the folder and placed this in the file to allow UDP traffic on the ephemeral ports (range 32768-65535) originating from the Sonos device to flow back to the main LAN
#!/bin/sh iptables -I YazFiFORWARD -i wl0.1 -o br0 -s 172.27.15.3 -p udp --dport 32768:65535 -j ACCEPT
- `-I YazFiForward` - adds the rule to the FORWARD chain in the YazFi table
- `-i wl0.1` - make sure to change this to your actual Guest Wi-Fi interface
- `-o br0` - packets moving to the bridge interface
- `-s 172.27.15.3` - make sure to change this to your actual Sonos device's IP address
- `-p udp` - UDP packets only
- `--dport 32768:65536` - ephemeral UDP port ranges only
- `-j ACCEPT` - allow packets filtered by this rule
You can duplicate that iptables line for as many Sonos device you have and their respective IPs, or you can also use `-srcrange` (i.e. `-m iprange --src-range 172.27.15.2-172.27.15.9`) if you have configured continuous static DHCP IPs for them.
Be reminded to `chmod +x` the file afterwards
jarylc@RT-AX88U:/jffs/addons/YazFi.d/userscripts.d# chmod +x myscript.sh
Reverting to only allowing one-way (LAN to Guest) communication
During investigation, I allowed two-way communication, so I am reverting it to one-way only in the Yazfi configuration.
Testing the Sonos app again
Sure enough, after allowing the UDP packet to flow back allows the Sonos app to be snappy again.
Bonus
HomeAssistant
I integrated my Sonos systems with HomeAssistant as well, it is also recommended by them to enable communication back via port 1400
iptables -I YazFiFORWARD -i wl0.1 -o br0 -d 172.27.14.100 -p tcp --dport 1400 -j ACCEPT
- `-I YazFiForward` - adds the rule to the FORWARD chain in the YazFi table
- `-i wl0.1` - make sure to change this to your actual Guest Wi-Fi interface
- `-o br0` - packets moving to the bridge interface
- `-s 172.27.14.100` - make sure to change this to your actual HomeAssistant's IP address
- `-p tcp` - TCP packets only
- `-dport 1400` - port 1400 only
- `-j ACCEPT` - allow packets filtered by this rule
It is also highly recommended to allow the Sonos systems to communicate with HomeAssistant directly (especially to use local media storage if you have any)
iptables -I YazFiFORWARD -i wl0.1 -o br0 -d 172.27.14.100 -p tcp --dport 8123 -j ACCEPT
- `-I YazFiForward` - adds the rule to the FORWARD chain in the YazFi table
- `-i wl0.1` - make sure to change this to your actual Guest Wi-Fi interface
- `-o br0` - packets moving to the bridge interface
- `-s 172.27.14.100` - make sure to change this to your actual HomeAssistant's IP address
- `-p tcp` - TCP packets only
- `-dport 8123` - make sure to change this to your actual HomeAssistant's port
- `-j ACCEPT` - allow packets filtered by this rule