Forwarding UPnP announcements between VLANs

I want UPnP devices to be discoverable across VLANs (example: a TV in IoT network wants to stream from NAS in home network, hence the TV needs to “see” the media server on NAS). The actual connection is not a problem, I can record traffic and create rules based on that, but I am stuck with forwarding announcements on 239.255.255.250 between two networks. As I understand, in Linux, there is mcproxy package that should do the trick, but in OpenWrt it is not available, and I don’t know alternatives specifically for multicast traffic. Eventually I was able to simulate that with something like

socat -v UDP4-RECVFROM:1900,ip-add-membership=239.255.255.250:192.168.10.1,fork UDP4-DATAGRAM:239.255.255.250:1900,interface=br-lan.20

but it does not seem like a graceful solution to route traffic with socat on a ROUTER?

Am I missing something?

P.S.: my use case is purely to make UPnP/DLNA devices discoverable across local networks. I don’t need to stream IPTV from the provider or anything like that, so my understanding that this or this articles don’t apply to me, and igmpproxy will not help me since it does not proxy unsolicited NOTIFYs.

Research smcroute to discover and route SSDP/DLNA traffic between subnets

1 Like

Have a look at this also….

https://forum.openwrt.org/t/accept-ssdp-dlna-responses-through-routed-networks/151628

1 Like

This is some good info as well

I was able to achieve routing of the multicast traffic with smcroute as recommended in the given articles, however I am facing a different problem: it seems like my Samsung Smart TV is smarter than required. Specifically, it seems like it filters the multicast traffic if it originates from another network. ChatGPT says it’s actually quite common behaviour, but you know ChatGPT… So please validate my findings.

So I have two networks based on VLANs:
lan: on br-lan.10, 192.168.10.0/24
iot: on br-lan.20, 192.168.20.0/24

The TV is pinned to 192.168.20.20. I run tcpdump on lan network to watch for multicast traffic. I temporarily assigned 192.168.20.20 to a laptop so that I could positively confirm that traffic can actually reach the destination (since I cannot run tcpdump on TV) and is not subject to any firewall blocks. I run tcpdump on the said laptop and I can see the same multicast traffic as I can see in lan network, with TTL decreased by 1, which confirms that smcroute works. Also, I confirmed that the LOCATION from the message is reachable from TV IP and responds meaningfully. However, when the real TV is connected, it seems like it ignores NOTIFY messages and DLNA server remains undetected.

To confirm my assumption about filtering by source IP, I created a post-routing iptables rule to mange the source IP to 192.168.20.1, and TV started seeing the server.

I have no other explanation than filtering at TV, though this was not a direct evidence and there might be other implicit factors. Have anyone seen this behavior?

Regardless of the reason, I am thinking what will be involved in proper routing:

  • smcroute daemon,
  • smcroute configuration,
  • post-routing source IP mangling rule,
  • firewall configuration for multicast traffic,

If I want to add routing for M-SEARCH messages from iot to lan (optional), I need additionally:

  • pre-routing TTL mangling rule (in this direction I have TTL=1, while on opposite direction I have greater TTL);
  • smcroute configuration.

At this point I seriously think if the problem deserves this complexity, and consider reverting to my original solution with socat. Let’s see what’s required:

  • socat pipe (needs to be automated to launch on start, but that’s it).
  • socat pipe for another direction (optional, to respond to M-SEARCH).

Socat is free from the TTL problem as it re-originates the traffic instead of routing. Also, for the same reason, the source IP will be in the destination network, removing the need for both mangling rules.

Are there any downsides if I continue using socat? Are there any reasons why smcroute path would be more preferable?

In the end, I decided to cheat and use socat instead of proper routing (like smcroute) due to the complexities described above. For anyone who is a lazy bones like me, here is my solution:

  1. Install socat package.
  2. Put into /etc/config/socat:
# Forward SSDP from LAN (br-lan.10) to IoT (br-lan.20)

# NAS DLNA server
config socat 'ssdp_ds2iot'
    option enable '1'
    list SocatOptions '-d0'
    list SocatOptions 'UDP4-RECVFROM:1900,ip-add-membership=239.255.255.250:192.168.10.1,reuseaddr,fork,range=192.168.10.10/32'
    list SocatOptions 'UDP4-DATAGRAM:239.255.255.250:1900,interface=br-lan.20'

# Laptop DLNA server
config socat 'ssdp_laptop2iot'
    option enable '1'
    list SocatOptions '-d0'
    list SocatOptions 'UDP4-RECVFROM:1900,ip-add-membership=239.255.255.250:192.168.10.1,reuseaddr,fork,range=192.168.10.30/32'
    list SocatOptions 'UDP4-DATAGRAM:239.255.255.250:1900,interface=br-lan.20'

# Forward SSDP from IoT (br-lan.20) to LAN (br-lan.10)
# TV
config socat 'ssdp_iot2lan'
    option enable '1'
    list SocatOptions '-d0'
    list SocatOptions 'UDP4-RECVFROM:1900,ip-add-membership=239.255.255.250:192.168.20.1,reuseaddr,fork,range=192.168.20.20/32'
    list SocatOptions 'UDP4-DATAGRAM:239.255.255.250:1900,interface=br-lan.10'

I am not enabling blanket relay of everything, the solution only covers the devices of interest (range option), and only SSDP multicast address/port. It also limits exposure of devices cross-networks (I have other devices I don’t want to be visible on the other side).

Note that the reverse path (from iot to lan) is optional, it is only required to immediately respond to M-SEARCH messages from the client and make discovery faster. Otherwise servers will send NOTIFY message every defined interval and the client will know anyway.

Not very universal, since I hardcode IPs of my equipment, but they are pinned anyway, so it will never break.

Also, the firewall rules are required for socat to see the traffic:

config rule
	option src 'lan'
	option name 'Allow-SSDP-from-lan'
	list proto 'udp'
	option target 'ACCEPT'
	option dest_port '1900'
	list dest_ip '239.255.255.250'

config rule
	option src 'iot'
	option name 'Allow-SSDP-from-iot'
	list proto 'udp'
	option target 'ACCEPT'
	option dest_port '1900'
	list dest_ip '239.255.255.250'

Of course, another set of rules (one per client-server pair) is required to enable actual connection from DLNA client to server. It seems like there is no standard ports for that, and you’d have to discover them if you want to punch port-specific holes only. To find that out, look into LOCATION field in NOTIFY announcements from the server through tcpdump or socat verbose log. After that, it will be trivial to create rules.

Forgot to mention – one trap that you can easily get into with setting up relays in both directions is the risk of creating circular traffic (and crashing socat/procd/system – whichever you get luck), because each socat instance sends into the same multicast address/port it listens. In my case, the range filter option saves from that, but in case you want to relay the SSDP traffic from/to the whole network, you need to filter it in some way or (better) use true routing with smcroute.

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.