Network topology
OPNsense
10.33.1.1
|
LAN 10.33.1.0/24
|
+------------+-------------+
| |
Unraid / MiniDLNA GL-MT6000 Flint 2
10.33.1.10 eth1: 10.33.1.2
|
br-lan: 10.33.2.1
|
Wi-Fi 10.33.2.0/24
|
HEOS / Marantz
br-guest: 10.81.1.1
|
Guest Wi-Fi
NOT INCLUDED
Important addresses:
OPNsense LAN: 10.33.1.1
Flint upstream: 10.33.1.2 / eth1
Flint trusted Wi-Fi: 10.33.2.1 / br-lan
Flint guest Wi-Fi: 10.81.1.1 / br-guest
Unraid / MiniDLNA: 10.33.1.10
MiniDLNA HTTP port: 8200
SSDP multicast: 239.255.255.250:1900/UDP
Guest Wi-Fi is deliberately excluded from SSDP forwarding.
Why it failed
UPnP/DLNA discovery uses SSDP multicast:
239.255.255.250:1900/UDP
Routers do not normally forward this multicast between subnets.
This meant:
HEOS 10.33.2.x
|
| SSDP discovery
X
|
MiniDLNA 10.33.1.10
However, bookmarked tracks continued to work because playback itself uses normal routed HTTP traffic:
HEOS 10.33.2.x
|
| HTTP
v
10.33.1.10:8200
MiniDLNA configuration
MiniDLNA runs as the binhex-minidlna Docker container on Unraid using Host networking.
Relevant configuration:
port=8200
media_dir=/media
friendly_name=MiniDLNA
db_dir=/config
log_dir=/config
inotify=yes
notify_interval=900
network_interface does not need to be explicitly set, although the Unraid LAN interface is:
eth0 = 10.33.1.10/24
To confirm MiniDLNA itself is healthy:
http://10.33.1.10:8200/rootDesc.xml
It should return XML containing something similar to:
<deviceType>urn:schemas-upnp-org:device:MediaServer:1</deviceType>
<friendlyName>MiniDLNA</friendlyName>
On Unraid:
ss -lunp | grep ':1900'
Expected:
239.255.255.250:1900 ... minidlnad
Flint 2: SMCRoute
The GL-MT6000 runs GL.iNet firmware 4.9.1, based on OpenWrt 21.02.
The package installed through:
Applications → Plug-ins → smcroute
is:
smcroute
/etc/smcroute.conf
phyint br-lan enable
phyint eth1 enable
mgroup from br-lan group 239.255.255.250
mgroup from eth1 group 239.255.255.250
mroute from br-lan group 239.255.255.250 to eth1
mroute from eth1 group 239.255.255.250 to br-lan
br-guest is intentionally absent.
Enable and start SMCRoute:
/etc/init.d/smcroute enable
/etc/init.d/smcroute restart
Verify:
smcroutectl show groups
Expected:
GROUP (S,G) IIF
(*, 239.255.255.250) br-lan
(*, 239.255.255.250) eth1
And:
smcroutectl show routes
Expected template routes:
(*, 239.255.255.250) br-lan eth1
(*, 239.255.255.250) eth1 br-lan
Once traffic exists, the kernel table will also contain concrete source addresses.
Flint 2: firewall configuration
The Flint's upstream eth1 belongs to the OpenWrt firewall zone called:
wan
The trusted Wi-Fi br-lan belongs to:
lan
Allow MiniDLNA SSDP replies
MiniDLNA answers an active M-SEARCH using UDP source port 1900, but sends it back to the client's temporary source port.
Current rule:
Name: Allow-MiniDLNA-SSDP-Reply
Family: IPv4
Source zone: wan
Source IP: 10.33.1.10
Source port: 1900
Destination zone: lan
Destination IP: 10.33.2.0/24
Protocol: UDP
Target: ACCEPT
UCI equivalent:
uci add firewall rule
uci set firewall.@rule[-1].name='Allow-MiniDLNA-SSDP-Reply'
uci set firewall.@rule[-1].family='ipv4'
uci set firewall.@rule[-1].src='wan'
uci set firewall.@rule[-1].src_ip='10.33.1.10'
uci set firewall.@rule[-1].src_port='1900'
uci set firewall.@rule[-1].dest='lan'
uci set firewall.@rule[-1].dest_ip='10.33.2.0/24'
uci set firewall.@rule[-1].proto='udp'
uci set firewall.@rule[-1].target='ACCEPT'
Allow MiniDLNA SSDP advertisements
MiniDLNA periodically sends NOTIFY messages to the multicast group.
The source port is not necessarily 1900. In packet captures MiniDLNA used ports such as 33852 and 59968.
Therefore only the destination port should be restricted.
Name: Allow-MiniDLNA-SSDP-Notify
Family: IPv4
Source zone: wan
Source IP: 10.33.1.10
Destination zone: lan
Destination IP: 239.255.255.250
Destination port: 1900
Protocol: UDP
Target: ACCEPT
UCI equivalent:
uci add firewall rule
uci set firewall.@rule[-1].name='Allow-MiniDLNA-SSDP-Notify'
uci set firewall.@rule[-1].family='ipv4'
uci set firewall.@rule[-1].src='wan'
uci set firewall.@rule[-1].src_ip='10.33.1.10'
uci set firewall.@rule[-1].dest='lan'
uci set firewall.@rule[-1].dest_ip='239.255.255.250'
uci set firewall.@rule[-1].dest_port='1900'
uci set firewall.@rule[-1].proto='udp'
uci set firewall.@rule[-1].target='ACCEPT'
Commit changes:
uci commit firewall
/etc/init.d/firewall restart
GL.iNet may print a number of warnings during a full firewall restart relating to inactive interfaces, VPN zones and GL.iNet-specific firewall extensions. These did not prevent the SSDP rules from working.
Critical NAT exception
This was the key part of the fix.
The Flint normally masquerades all traffic leaving the trusted Wi-Fi toward its upstream interface.
Without an exception, an SSDP search changed from:
10.33.2.x:37462 → 239.255.255.250:1900
to:
10.33.1.2:37462 → 239.255.255.250:1900
MiniDLNA then replied to the Flint itself instead of the original HEOS client.
The WAN firewall zone is:
firewall.@zone[1]
and contains:
name='wan'
masq='1'
The following exclusion was added:
uci add_list firewall.@zone[1].masq_dest='!239.255.255.250/32'
uci commit firewall
/etc/init.d/firewall restart
Verify:
uci show firewall.@zone[1]
Expected:
firewall.cfgXXXXXX.name='wan'
firewall.cfgXXXXXX.masq='1'
firewall.cfgXXXXXX.masq_dest='!239.255.255.250/32'
This means:
Normal Wi-Fi → upstream traffic:
NAT normally
Traffic to 239.255.255.250:
DO NOT NAT
The actual anonymous UCI zone index could change in the future, so before recreating the rule always identify the WAN zone first:
uci show firewall | grep -E "=zone|\.name='wan'|\.masq"
OPNsense return route
Once NAT is removed from SSDP, MiniDLNA sees the real client address:
10.33.2.x
MiniDLNA sends its SSDP response directly to that address.
Unraid's normal gateway is OPNsense at 10.33.1.1, so OPNsense must know that 10.33.2.0/24 lives behind the Flint.
Gateway
Create:
Name: GLINET_WIFI
Interface: LAN
Address Family: IPv4
IP Address: 10.33.1.2
Upstream Gateway: No
Far Gateway: No
Gateway Monitoring: Disabled
Description: Flint 2 WiFi router
Static route
Create:
Network: 10.33.2.0/24
Gateway: GLINET_WIFI
Description: WiFi via Flint 2
Result:
10.33.2.0/24 via 10.33.1.2
If the OPNsense LAN firewall policy is restrictive, it must also permit traffic from the LAN toward 10.33.2.0/24.
With a normal LAN net → any allow policy, no additional rule should be necessary.
Expected working SSDP flow
A HEOS client searches for a media server:
10.33.2.x:ephemeral
|
| M-SEARCH
v
239.255.255.250:1900
|
| SMCRoute
v
Flint eth1
|
| source still 10.33.2.x
v
MiniDLNA 10.33.1.10
MiniDLNA responds:
10.33.1.10:1900
|
| HTTP/1.1 200 OK over UDP
v
10.33.2.x:ephemeral
The response contains:
ST: urn:schemas-upnp-org:device:MediaServer:1
SERVER: ... MiniDLNA/1.3.3
LOCATION: http://10.33.1.10:8200/rootDesc.xml
After receiving this, HEOS can retrieve rootDesc.xml via ordinary routed HTTP and display MiniDLNA under Music Servers.
Troubleshooting
1. Check MiniDLNA itself
From another client:
http://10.33.1.10:8200/rootDesc.xml
If this does not work, troubleshoot MiniDLNA or normal IP routing first.
On Unraid:
ss -lunp | grep ':1900'
Expected:
239.255.255.250:1900 ... minidlnad
Restart MiniDLNA if necessary:
docker restart binhex-minidlna
2. Check Flint interfaces
ip -br addr
Important entries should still resemble:
eth1 UP 10.33.1.2/24
br-lan UP 10.33.2.1/24
br-guest UP 10.81.1.1/24
Check routes:
ip route
Expected:
default via 10.33.1.1 dev eth1
10.33.1.0/24 dev eth1
10.33.2.0/24 dev br-lan
10.81.1.0/24 dev br-guest
3. Check SMCRoute
/etc/init.d/smcroute status
Then:
smcroutectl show groups
smcroutectl show routes
Expected interfaces:
br-lan
eth1
Expected group:
239.255.255.250
There should be no br-guest route.
If SMCRoute is not running:
/etc/init.d/smcroute enable
/etc/init.d/smcroute restart
4. Check firewall rules
uci show firewall | grep -E 'MiniDLNA|masq_dest'
Expected to find:
Allow-MiniDLNA-SSDP-Reply
Allow-MiniDLNA-SSDP-Notify
masq_dest='!239.255.255.250/32'
If there are duplicate MiniDLNA rules, inspect them with:
uci show firewall
and delete only the unwanted duplicate, for example:
uci delete firewall.@rule[24]
uci commit firewall
/etc/init.d/firewall restart
Do not blindly reuse a rule number from this document; anonymous UCI indexes can change.
5. Check the critical NAT behavior
Run on the Flint:
tcpdump -ni eth1 -vv -A 'udp port 1900'
Then refresh:
HEOS → Music Servers
A working MediaServer search on eth1 should retain the Wi-Fi client source:
10.33.2.x.37462 > 239.255.255.250.1900
M-SEARCH * HTTP/1.1
ST: urn:schemas-upnp-org:device:MediaServer:1
Bad
If instead you see:
10.33.1.2.37462 > 239.255.255.250.1900
the Flint is still NATing SSDP.
Check:
uci show firewall.@zone[1]
and confirm:
masq_dest='!239.255.255.250/32'
6. Check MiniDLNA response
After an M-SEARCH, a working capture should show:
10.33.1.10.1900 > 10.33.2.x.37462
HTTP/1.1 200 OK
...
LOCATION: http://10.33.1.10:8200/rootDesc.xml
If MiniDLNA replies but the packet never appears on br-lan, investigate:
- OPNsense static route
- OPNsense LAN firewall policy
- Flint
Allow-MiniDLNA-SSDP-Replyrule
Capture the trusted Wi-Fi side:
tcpdump -ni br-lan -vv -A 'udp port 1900 and host 10.33.1.10'
7. Check OPNsense route
OPNsense must have:
10.33.2.0/24 → 10.33.1.2
If this route is missing, MiniDLNA's direct reply to 10.33.2.x will not return through the Flint.
Useful packet signatures
HEOS / Marantz advertisement
Typical:
NOTIFY * HTTP/1.1
HOST: 239.255.255.250:1900
SERVER: LINUX UPnP/1.0 Denon-Heos/...
HEOS searching for a media server
M-SEARCH * HTTP/1.1
HOST: 239.255.255.250:1900
MAN: "ssdp:discover"
ST: urn:schemas-upnp-org:device:MediaServer:1
MiniDLNA advertisement
NOTIFY * HTTP/1.1
HOST:239.255.255.250:1900
LOCATION:http://10.33.1.10:8200/rootDesc.xml
SERVER: ... MiniDLNA/1.3.3
NT:urn:schemas-upnp-org:device:MediaServer:1
NTS:ssdp:alive
MiniDLNA discovery response
HTTP/1.1 200 OK
ST: urn:schemas-upnp-org:device:MediaServer:1
SERVER: ... MiniDLNA/1.3.3
LOCATION: http://10.33.1.10:8200/rootDesc.xml
Firmware upgrades and persistence
The setup survives normal router reboots.
The following are stored persistently:
- OpenWrt UCI firewall configuration
- OPNsense gateway/static route
/etc/smcroute.conf- SMCRoute init enablement
However, a GL.iNet firmware upgrade may remove user-installed packages even when Keep Settings is selected.
The smcroute package may therefore need to be reinstalled after a firmware upgrade.
Recommended additional persistence setting:
grep -qxF '/etc/smcroute.conf' /etc/sysupgrade.conf || \
echo '/etc/smcroute.conf' >> /etc/sysupgrade.conf
Verify:
cat /etc/sysupgrade.conf
After a GL.iNet firmware upgrade:
smcroutectl show routes
If the command does not exist, reinstall smcroute through:
Applications → Plug-ins
Then:
/etc/init.d/smcroute enable
/etc/init.d/smcroute restart
Finally verify:
uci show firewall | grep -E 'MiniDLNA|masq_dest'
cat /etc/smcroute.conf
smcroutectl show groups
smcroutectl show routes
Quick health check
When HEOS discovery stops working, run these in order on the Flint:
ip -br addr
smcroutectl show groups
smcroutectl show routes
uci show firewall | grep -E 'MiniDLNA|masq_dest'
tcpdump -ni eth1 -vv -A 'udp port 1900'
Then refresh HEOS → Music Servers.
The most important check is:
M-SEARCH leaving eth1 MUST have source 10.33.2.x
and not:
10.33.1.2
If the source is 10.33.1.2, the SSDP NAT exclusion is missing or no longer active.
Final configuration summary
MiniDLNA:
10.33.1.10:8200
SSDP 239.255.255.250:1900
Flint:
eth1 = 10.33.1.2
br-lan = 10.33.2.1
br-guest excluded
SMCRoute:
br-lan <-> eth1
multicast group 239.255.255.250
Flint firewall:
Allow MiniDLNA SSDP response wan -> lan
Allow MiniDLNA SSDP NOTIFY wan -> lan
Flint NAT:
Normal masquerading enabled
Exception:
!239.255.255.250/32
OPNsense:
Gateway GLINET_WIFI = 10.33.1.2
Static route:
10.33.2.0/24 via 10.33.1.2
Guest:
10.81.1.0/24
no SSDP forwarding