After troubleshooting this issue for weeks I finally found a working solution which I wanted to share here.
Scenario:
My phone is in VLAN 100
(10.1.100.0/24
, br-lan100
) and I wanted to cast (Netflix/Youtube) to my LG TV in VLAN 103 (10.1.103.0/24, br-iot)
.
The TV uses ssdp (simple service discovery protocol), which means I needed
- smcroute
- A way to increase the TTL of ssdp-packages
- Allow packages from the relevant firewall zones to 239.255.255.250, port 1900
- Open the necessary ports (they change with every use)
- A masquerading rule
smcroute:
Just install it via opkg install smcroute
, then change the config to your liking (/etc/smcroute.conf
). Here is mine:
phyint br-lan100 enable
phyint br-iot enable
mgroup from br-iot group 239.255.255.250
mroute from br-iot group 239.255.255.250 to br-lan100
mgroup from br-lan100 group 239.255.255.250
mroute from br-lan100 group 239.255.255.250 to br-iot br-nonet
When you are done restart smcroute: service smcroute restart
.
Now smcroute will route packages arriving at 239.255.255.250, port 1900
from br-iot
to br-lan100
and vice versa.
TTL:
Sometimes ssdp packages have a TTL of 1 which means the firewall will discard them. To increase the TTL I added the following in my /etc/firewall.user
:
nft add rule inet fw4 mangle_prerouting iifname {"br-iot", "br-lan100"} ip daddr 239.255.255.250 ip ttl 1 ip ttl set 2
Which translates to: "If a ssdp package arrives at one of those interfaces with a ttl of 1 then change it's ttl to 2".
Allow packages from the relevant firewall zones to 239.255.255.250, port 1900
If your firewall rules disallow the free flow of packages between VLANs you might need to add an exception so that packages for 239.255.255.250, port 1900
may arrive at the router (which I did in LuCI):
Open the necessary ports:
Now, if a ssdp-package arrives we route it. The TV will then try to answer the phone, but since br-iot
is in a firewall zone that isn't allowed to forward to the zone the phone is in (in my case) we need to open the necessary ports (/etc/firewall.user
):
nft add set inet fw4 ssdp_out {type inet_service \; timeout 5s \;}
nft insert rule inet fw4 forward iifname {"br-iot"} oifname {"br-lan100"} udp dport @ssdp_out counter accept
nft insert rule inet fw4 forward iifname {"br-iot"} oifname {"br-lan"} tcp dport @ssdp_out counter accept
A bit of background: The phone is notified via ssdp what services the TV offers at which IP and at which port(s). The phone then opens a random port (phone-side) and sends packages to the TV. The TV will then reply, trying to reach the TV on that random port.
If your zones/VLANs are allowed to talk to each other freely then there is nothing to do here for you. If not then you need the rules above.
The first line creates an nftset called ssdp_out
. This nftset will open ports for 5 seconds.
The second and third line (udp/tcp) say that every time a device in br-lan100
connects to a device in br-iot
then the port the device connects from will be added to the nftset which will open the firewall on that port so that the device in br-iot
may answer the requesting device.
This was all pretty simple to google, but I wasn't able to find the last ingredient anywhere. My phone was able to see the TV, but when I tried to cast to it it told me that there was an error in the connection.
Masquerading:
Firing up wireshark I found that the phone tries the following http request
1761 26.351383 192.168.178.193 10.1.100.101 HTTP 306 63 GET /apps/Netflix HTTP/1.1
When the devices are in the same subnet the TV answers with
11151 27.089581 192.168.178.241 192.168.178.193 HTTP/XML 1293 HTTP/1.1 200 OK
But when they were in differen subnets/VLANs it'd answer with
1763 26.353354 10.1.100.101 192.168.178.193 HTTP 209 64 HTTP/1.1 403 Forbidden
It seems the TV is programmed to only accept connections from the same subnet.
To circumvent this I masqueraded all traffic from br-lan100
going to the TV:
In Firewall->Nat Rules
With all this in place casting works exactly as it should.
Notes:
There are some infos here on how to use an nftset to masquerade the traffic in case you don't want to masquerade the whole subnet.
Efahl beautifully rewrote the nftables rules for ssdp in this thread. For this How To I decided to use my initial rules because I think they are easier to understand for beginners (like me).
The rules that open the random ports are also helpful when using mDNS because the necessary ports might not be open when mDNS is used to announce services to the network either.
A BIG thanks to all the members in this community who helped me over the last few weeks!!
I am definitely not a pro and I am sure I didn't use the right lingo in some places. Please let me know where so that I can enhance the guide so as many people as possible can understand it.