Sonos - firewall rules

Hi guys,

I’m trying to improve my pi’s security by adding a firewall (I’ve chosen UFW, although that shouldn’t matter for this question). I have configured it to allow all outgoing traffic, to block all incoming traffic, and then added some rules to allow specific ports to allow incoming traffic for HASS, Mosquitto, SSH, Pi-Hole etc.
However, ever since I turned the firewall on the Sonos media_player component has stopped working. Adding a rule to allow all incoming traffic from the Sonos’ IP address solves the issue, so the firewall is the reason that it has stopped working.

Things I have tried so far:

  • Adding rules to allow all incoming traffic on ports used by Sonos as defined on their website:

https://sonos.custhelp.com/app/answers/detail/a_id/692/kw/sonos%20software%20linux

  • Looking at the UFW logs to see which ports are blocked when trying to connect to Sonos after a HASS restart and adding rules to allow incoming traffic on these ports

But nothing helps!

For now I have simply added a rule to allow all incoming traffic from the Sonos IP address on all ports, which works, but I want to understand why it isn’t working!

So my big question is: which ports are used to allow a connection between HASS and Sonos?

Thanks in advance for the help, much appreciated!

Necro’ing an old thread, but I thought I’d share an excellent serverfault page for how to enable UPNP service discovery via UFW, without whitelisting the 192.168.0.0/16 IP range. This worked for me running HA via docker, with host networking, on raspbian.

sudo apt-get install ipset
ipset create upnp hash:ip,port timeout 3

#add the following to your /etc/ufw/before.rules, before the commit statement
-A ufw-before-input -p udp -m set --match-set upnp dst,dst -j ACCEPT
-A ufw-before-output -d 239.255.255.250/32 -p udp -m udp --dport 1900 -j SET --add-set upnp src,src --exist

What these rules do, which is explained in serverfault, is insert, temporarily, the source port when sending to the multicast ssdp address. Then, when evaluating the rules for incoming, if the dest port of a packet exists in that set (which has a 3 second timeout), it allows it.

As an example, this was what was happening before this rule was added:

Sep  4 18:50:17 raspberry kernel: [243707.951172] [UFW ALLOW] IN= OUT=eth0 SRC=192.168.94.43 DST=239.255.255.250 LEN=147 TOS=0x00 PREC=0x00 TTL=4 ID=33201 DF PROTO=UDP SPT=50338 DPT=1900 LEN=127
Sep  4 18:50:17 raspberry kernel: [243707.951599] [UFW ALLOW] IN= OUT=eth0 SRC=192.168.94.43 DST=255.255.255.255 LEN=147 TOS=0x00 PREC=0x00 TTL=64 ID=22400 DF PROTO=UDP SPT=50338 DPT=1900 LEN=127
Sep  4 18:50:17 raspberry kernel: [243707.952644] [UFW BLOCK] IN=eth0 OUT= SRC=192.168.94.13 DST=192.168.94.43 LEN=242 TOS=0x00 PREC=0x00 TTL=64 ID=50188 DF PROTO=UDP SPT=1900 DPT=50338 LEN=222

We can see the multicast go out from port 50338, but then the reply got blocked. Firewalls usually allow response to whatever port was just used, but that only works when the DEST for outgoing, matching the SRC for incoming, which isn’t true with broadcast packets.

This work great, except if you reboot your Raspberry Pi will lose the ability to reach the network because the ipset command doesn’t run on startup and ufw chokes on the iptables rules and leaves your firewall in a hosed state. I have been using this guide to persist the ipset rules and it works across reboots now:

Thanks for sharing your solution @jhenkens!