Using multicast-relay to do SSDP relaying for Roku, Sonos, Tivo discovery

Comments

18 comments

  • Avatar
    Michael Bierman

    @alak I haven't tried it, but you could look at running github.com/scyto/multicast-relay in docker on FWG It says it supports Sonos specifically at least. 

    0
    Comment actions Permalink
  • Avatar
    David Rothenberger

    The docker container would need access to the interfaces on the Firewalla over which you wanted to relay SSDP messages. I don't know if that's possible right now (or ever) on the Firewalla.

    There's a feature request for more flexible docker networking options.

    https://help.firewalla.com/hc/en-us/community/posts/7552270924051-Docker-network-flexibility-support-coming-to-beta-

    0
    Comment actions Permalink
  • Avatar
    Alak

    @Michael Thanks for the pointer!  I'll take a look at it.  Even github.com/alsmith/multicast-relay already provides a Docker file but I'm very new to using Dockers so I will need time to study it.

    @David Thanks for pointing out the interface permissions issue!  Maybe someone with more advanced FWG Docker experience can try to get this working.

    In the meantime, this utility might be simple enough to run directly on FWG without a Docker container.  Once you download it somewhere, it runs as a single Python process to do the relaying.  It would just need to be added to the startup cronjobs.

    0
    Comment actions Permalink
  • Avatar
    Alak

    Ok I got it working with https://github.com/scyto/multicast-relay !

    This is my first time using Docker containers so I'm pretty happy about having success with this!

    # Create the ssdp-relay container the first time
    sudo docker run --detach --restart=always --name ssdp-relay --network=host -e OPTS="--noMDNS" -e INTERFACES="br0 br1" scyto/multicast-relay

    # Stop the SSDP relaying
    sudo docker stop ssdp-relay

    # Restart the SSDP relaying
    sudo docker start ssdp-relay

    # Remove the ssdp-relay container (if you want to reconfigure it)
    sudo docker container rm -f ssdp-relay

     

    1
    Comment actions Permalink
  • Avatar
    Michael Bierman

    Very cool, @Alak! 

    0
    Comment actions Permalink
  • Avatar
    Alak

    Thanks Michael!

    I found that it also works for a Guest network if you create an allow rule between the Guest network and the specific device like a Roku.  You do need to reserve static IP addresses for those AV devices for the rule.

    Hopefully this helps out some folks who were putting all their AV devices on the same subnet as their casting devices because of this limitation.

    1
    Comment actions Permalink
  • Avatar
    Michael Bierman

    @alak and others in the future, this will tell you the available interfaces on your firewalla

    ip -4 -j address | jq -r '.[] | "index: \(.ifindex), interface: \(.ifname), local: \(.addr_info[].local)"'

    Not quite sure what you mean by the Guest network. That seems like it will depend if the Guest network is part of an AP like eero or just another VLAN. What kind of set up did you test it on?

    3
    Comment actions Permalink
  • Avatar
    Alak

    In my case, the guest network is a VLAN with Firewalla guest network template rules (block traffic to all local networks, block traffic from internet) on a WAP connected to one of the listed interfaces (br1) given to multi-cast relay.  The actual interface of the VLAN is different from br1 but that doesn't seem to matter.  Relaying it to br1 covers all VLANS connected to this interface.  This is not an issue though because guest networks can't discover devices on other subnets without a rule overriding the block rule that prevents traffic to local networks.

    If the WAP has a guest network feature preventing all local traffic, it needs to be turned off to allow device discovery and media casting.  You also need an allow override rule allowing guest network to reach your specific AV device on a non-guest subnet.

    0
    Comment actions Permalink
  • Avatar
    Michael Bierman

    Thanks, @Alak. That still appears as an interface so I would have assumed it would be no different. For example ,here are before and after when I added a Guest network to my Purple.  

    pi@Firewalla:~ (Purple) $ ip -4 -j address | jq -r '.[] |"index: \(.ifindex), interface: \(.ifname), local: \(.addr_info[].local)"'
    index: 1, interface: lo, local: 127.0.0.1
    index: 2, interface: eth0, local: 192.168.177.2
    index: 9, interface: br-83eef645874c, local: 172.16.0.1
    index: 10, interface: docker0, local: 172.17.0.1
    index: 11, interface: br-08065b5411e2, local: 172.16.1.1
    index: 17, interface: wg0, local: 10.189.10.1
    index: 20, interface: br0, local: 10.11.227.1
    pi@Firewalla:~ (Purple) $ ip -4 -j address | jq -r '.[] | "index: \(.ifindex), interface: \(.ifname), local: \(.addr_info[].local)"'
    index: 1, interface: lo, local: 127.0.0.1
    index: 2, interface: eth0, local: 192.168.177.2
    index: 9, interface: br-83eef645874c, local: 172.16.0.1
    index: 10, interface: docker0, local: 172.17.0.1
    index: 11, interface: br-08065b5411e2, local: 172.16.1.1
    index: 17, interface: wg0, local: 10.189.10.1
    index: 20, interface: br0, local: 10.11.227.1
    index: 21, interface: br1, local: 192.168.118.1
    0
    Comment actions Permalink
  • Avatar
    Alak

    @Michael - I have something like the following on my network 

    interface: eth2.40, local: 192.168.40.1 (guest VLAN 40 on WAP on FWG LAN port 2)
    interface: br1, local: 192.168.2.1 (FWG LAN port 2)
    interface: br0, local: 192.168.1.1 (FWG LAN port 1)

    WAP is on br1 but also creates a guest VLAN 40 which is eth2.40.  When I relay SSDP between br0 and br1, it also works for the guest VLAN 40 on interface eth2.40 without the need to explicitly add it.

    Consequently FWG users should simply be able to set the relay interfaces to "br0 br1 br2" in order to relay everything across all LAN subnets since everything ultimately connects through those interfaces.  That is my humble observation anyway.

    0
    Comment actions Permalink
  • Avatar
    David Rothenberger

    Consequently FWG users should simply be able to set the relay interfaces to "br0 br1 br2" in order to relay everything across all LAN subnets since everything ultimately connects through those interfaces.  That is my humble observation anyway.

    This will depend on your configuration. For example, on my FWG, I only have a "docker0" bridge. I do not have br0, br1, or br2.

    For reference, I have three of the FWG's ports combined into a LAG that is connected to my switch. So for me, the interface names are things like "bond0.20" and "bond0.70".

    0
    Comment actions Permalink
  • Avatar
    Michael Bierman

    @alak, @David, 

    Agreed, I'm sure there are people who know what the bare minimum requirements are for what interfaces need to be included with the many possible interface configurations LAG, Bridges, VLANs, etc. I am unfortunately not knowledgable enough right now to be certain. If I did, I would probably write another "installer" like I did for pi-hole and homebridge  to make this trivial and walk people through answering a few questions and, "BOOM!" they would be in business. 

    The command I posted earlier should be enough to allow some painless experimentation though and get people going. I think that's the best I can do at the moment. Most people probably don't have that many interfaces and can figure it out by trial and error. 

    Also, I can't test any of this because I don't currently have any Sonos equipment. Always open to donations so I can test things though. ;) 

    0
    Comment actions Permalink
  • Avatar
    David Rothenberger

    I don't have Sonos equipment, but this did solve the problems I was having discovering Rokus. It also solved a problem discovering a Yamaha receiver.

    So, thanks very much, @alak!

    The only AV device I can't get to work in a subnet is a Libratone Zipp Mini speaker. I really wish I could move that device, too, since it communicates with China a lot, but oh, well.

     

    0
    Comment actions Permalink
  • Avatar
    Alak

    @Michael, @David

    Thanks for setting me straight on the variety of configurations and interface definitions out there!

    @Michael, your utility should help people discover their interface names.  I can add it to my original post text if you're ok with it.

    @David You're my first Beta tester!  Glad it works!  It does seem to have the ability to relay for other multicast ports as well if you can find out what Zipp Mini speaker is using for discovery.  It might work if it is simple multicast.  Unfortunately there are devices like Samsung TVs that only allow communication on the same subnet.  That's a device limitation and some people have worked around it by running a proxy server to relay the communication with those devices.  I've got that problem as well but I won't dive into that rat hole for now.

    0
    Comment actions Permalink
  • Avatar
    Michael Bierman

    Yes, feel free, @Alak.

    0
    Comment actions Permalink
  • Avatar
    Alak

    Thanks @Michael!  I added it to my original post which I have updated to make it a self-standing guide for any other users who need this info.

    0
    Comment actions Permalink
  • Avatar
    Matt Niswonger

    @Alak, this is excellent work.  Thank you for this!

    @Firewalla - this needs to be a native feature just like mDNS reflection using the Avahi daemon!  

    1
    Comment actions Permalink
  • Avatar
    Erker B.

    @Alak, thank you very much for the wonderful guide. I also wanted to do a quick follow up for those who likes/prefers docker-compose for containers. IMO, it makes it easy to start/stop containers, and make config changes easier.

    Create a docker-compose.yaml (i created it under /data/docker-manifest directory) file with the following:

    ---
    version: "3.9"

    services:
      ssdp-relay:
        image: scyto/multicast-relay:latest
        container_name: ssdp-relay
        environment:
        - INTERFACES=eth1.11 eth1.13 <----- Left here for example, use your network interfaces discovered from earlier step
          - OPTS=--noMDNS
        - TZ=America/New_York <---- Change this for your time zone
      network_mode: host
        deploy:
          restart_policy:
            condition: any
          resources:
            limits:
            cpus: '0.15'
              memory: 16M
        logging:
          options:
          max-size: "250k"

    Couple things to note here:

    • When you are running containers, always set a CPU and Memory resource limits. I ran the application for a few hours and profiled based on how much it used. You may need more depending on how many interfaces you have configured. Use sudo docker stats command to discover current usage.
    • This specific container does not generate logs, but it's a good idea to limit how much space it can consume.

    If you would like to automatically update the container image(s), you can use watchtower container. Here is a blurb you can add to the same docker-compose.yaml file:

      watchtower:
        container_name: watchtower
        image: containrrr/watchtower
        read_only: true
        environment:
          WATCHTOWER_DEBUG: 'true'
          TZ: 'America/New_York'
          WATCHTOWER_CLEANUP: 'true'
          WATCHTOWER_INCLUDE_RESTARTING: 'true'
          WATCHTOWER_SCHEDULE: '0 0 0 * * *'
          WATCHTOWER_ROLLING_RESTART: 'true'
          WATCHTOWER_TIMEOUT: '60s'
      volumes:
          - /var/run/docker.sock:/var/run/docker.sock
        networks:
        - fwg <--- Extra steps needed
        deploy:
          restart_policy:
            condition: any
          resources:
            limits:
              cpus: '0.25'
              memory: 64M
        logging:
          options:
            max-size: "250k"

    watchtower container will need to be able to access internet (so that it can check container images from image repositories). In my container above, I've created a docker network called fwg with the following:

    sudo docker network create --driver=bridge --subnet=172.30.0.0/26 --gateway=172.30.0.1 --attachable fwg

    Then created a route, so containers attached to that network can access internet:

    $ sudo docker network ls | grep fwg
    grab the ID

    $ sudo ip route add 172.30.0.0/26 dev br-(ID FROM EARLIER) table wan_routable

    Only attach containers that need to access internet to fwg docker network (or whatever you decide to name).

    Once you have the file created, use sudo docker-compose up -d command to start your containers listed in docker-compose.yaml file.  You can use sudo docker-compose down stop containers.

    1
    Comment actions Permalink

Please sign in to leave a comment.