Miniupnpd in trunk & STUN setup

I'm trying to leverage the new feature in miniupnpd that dynamically discovers the public IP of a cascaded (i.e behind another NAT router) OpenWRT box using the STUN protocol.

My upstream ISP-Supplied modem/router is configured to forward all inbound traffic with a DMZ configuration. I've tested, and traffic arrives at the OpenWRT and goes through manually configured port forwards to their destinations.

This is good news for PPPoE and cascaded users who have struggled with the public IP not being shown in miniupnpd, and therefore clients not working, as they see a private IP vs public.

So two things, there does not seem to be support (yet) in the OpenWRT /etc/config file parsing that will output the newly defined miniupnpd runtime input config (in /var/etc/miniupnpd.conf ), is anyone working on that, or do we need a bug report?

Secondly, even if I manually poke the run var file as follows, it still claims the test did not pass:

root@OpenWrt:/etc/config# cat /var/etc/miniupnpd.conf
ext_ifname=eth0.2
listening_ip=br-lan
port=5000
enable_natpmp=yes
enable_upnp=yes
secure_mode=yes
ext_perform_stun=yes
ext_stun_host=stun.onesuite.com
pcp_allow_thirdparty=no
system_uptime=yes
force_igd_desc_v1=yes
lease_file=/var/run/miniupnpd.leases
bitrate_down=8388608
bitrate_up=4194304
uuid=34d83956-276a-466c-beaf-d2af9d9e7bec
allow 1024-65535 0.0.0.0/0 1024-65535 #Allow high ports
deny 0-65535 0.0.0.0/0 0-65535 #Default deny

When I then launch miniupnpd in full debug mode, we see the STUN process successfully retrieve the public IP, but grades the inbound state as 'Restrictive NAT' and clients can't add effective forwards (if they even bother, given the other status).

root@OpenWrt:/etc/config# /usr/sbin/miniupnpd -d -f /var/etc/miniupnpd.conf
miniupnpd[1950]: system uptime is 3517 seconds
miniupnpd[1950]: Reloading rules from lease file
miniupnpd[1950]: could not open lease file: /var/run/miniupnpd.leases
miniupnpd[1950]: version 2.1 starting NAT-PMP/PCP UPnP-IGD ext if eth0.2 BOOTID=1533835654
miniupnpd[1950]: STUN: Performing with host=stun.onesuite.com and port=0 ...
miniupnpd[1950]: STUN: ext interface eth0.2 with IP address 192.168.254.13 is now behind restrictive NAT with public IP address 40.134.86.218: Port forwarding is now impossible
miniupnpd[1950]: HTTP listening on port 5000
miniupnpd[1950]: HTTP IPv6 address given to control points : [fd6b:c2c9:3cb7::1]
miniupnpd[1950]: Listening for NAT-PMP/PCP traffic on port 5351

Even though I know traffic is being forwarded from the upstream router.

So anyone else having luck with miniupnpd and STUN discovery?

Code is today's build on a C7v2.

Made some progress today, and it looks like there is problem with the OpenWRT implementation of miniupnpd, related to how it handles the firewall during the Stun test.

Suspecting this, I ran a quick test, and I think I proved the DMZ stuff upstream is working and the core issue is how the upnpstun function is testing for access. They open 4 ports to receive inbound replies from the stun server, I just don’t think the rules are quite right on the OpenWRT build.

First, I opened up the inbound udp in the firewall, any inbound udp connection can reach the device (dangerous)
StunTestFirewall

Re-pushed my customized miniupnpd.conf file back in to /var/etc/miniupnpd.conf

Kill existing instance and re-launch with the debug flag, and voila:

root@OpenWrt:~# /usr/sbin/miniupnpd -d -f /var/etc/miniupnpd.conf
miniupnpd[4668]: system uptime is 27647 seconds
miniupnpd[4668]: Reloading rules from lease file
miniupnpd[4668]: could not open lease file: /var/run/miniupnpd.leases
miniupnpd[4668]: version 2.1 starting NAT-PMP/PCP UPnP-IGD ext if eth0.2 BOOTID=1533931318
miniupnpd[4668]: STUN: Performing with host=stun.onesuite.com and port=0 ...
miniupnpd[4668]: STUN: ext interface eth0.2 with IP address 192.168.254.13 is now behind unrestricted NAT 1:1 with public IP address 40.134.86.218: Port forwarding is now enabled
miniupnpd[4668]: HTTP listening on port 5000
miniupnpd[4668]: HTTP IPv6 address given to control points : [redacted]
miniupnpd[4668]: Listening for NAT-PMP/PCP traffic on port 5351

And the test tool reports all good, I can now add new port maps, and even my Back To My Mac reports all good.

So it's in how they craft and / or apply the temporary firewall rules for these tests that is likely the problem.

Should I open a bug on the OpenWRT flyspray or back on the miniupnpd project?

Finding the same problem here, so adding my input.

Many folks (including me) have to run behind the ISP router and only get local IP's not the public IP, so this is a common issue.

Looks like there is a bug report on this, but no activity (that I could see): https://github.com/openwrt/packages/issues/6771

If anyone else agrees and wants to see this in the next point release, please chime in.

1 Like

Ok i had this issue with bridge mode on my Zytel VMG1312-B10a,

The issue is not with the router but the modem you set to bridge not being configured correctly.

In my case i forgot to make a Interface Group for LAN1 and the PTM ppp WAN interface.

This setting stops LAN1 from being a LAN port and makes it a port for WAN connections.

So if you have a Zytel VMG1312-B10/VMG8324 simply head to

Network Settings > Interface Group

Then click add new interface group and call it Bridge
Then assign the PTM Type to ptm0.1 then add LAN1 to the grouped interface list and checkbox it.

Once done click apply and bingo upnp will work.

As for others check your modem to something simular and then do the same thing as above, this should solve your NAT-PMP and UPNP issues without having to use STUN firewall rules and adding STUN to the config.

this issue related to this commit https://github.com/openwrt/packages/commit/c61614a849d1c7fc0cb6d0dafd79440a35bb5fc6#diff-a22cd36220a763d4ebb8ad9c5f128589

should fix with this patch

diff --git a/net/miniupnpd/files/miniupnpd.hotplug b/net/miniupnpd/files/miniupnpd.hotplug
index 29f9cdbd1..78bd2924a 100644
--- a/net/miniupnpd/files/miniupnpd.hotplug
+++ b/net/miniupnpd/files/miniupnpd.hotplug
@@ -1,6 +1,6 @@
 #!/bin/sh /etc/rc.common
 
-enabled miniupnpd || exit 0
+/etc/init.d/miniupnpd enabled || exit 0
 
 # If miniupnpd is not running:
 # - check on _any_ event (even updates may contribute to network_find_wan*)


Is anyone aware that UPnP doesn't work very well in v19.07? I have been compiling my own v19.07 firmware but I have been packaging the miniupnpd from v18.06 and it works very well. My current miniupnpd version is 2.1-1.

I'm currently writing up a bug report to see if someone can fix it.

Does this fix the issue with opening the on the firewall the UDP ports used by miniupnpd for STUN testing?

Miniupnpd version from 18.06 does not have stun support.

Since miniupnpd is "smart" and can detect the NAT type and if the WAN interface IP is public or private, it is not working in double NAT configurations (openwrt behind the ISP router with DMZ). Miniupnod detects if the IP of the wan interface is private or public, and does not enable port forwarding if its private. One solution is to use a stun server to detect the public IP, but for it to work you have to allow incoming UDP traffic (thus it detects that it is a NAT 1:1 and determines that it is possible to redirect ports). It's not recommended for security allow all incoming UDP traffic on an interface connected to the internet. Otherwise miniupnpd warns that NAT is strict and port forwarding is not working. The other solution is to add external_ip to the configuration file and manually specify public IP (only useful if you have static ip) or edit the /etc/init.d/miniupnpd file so that it detects the public IP every time it is started (for example from a DDNS host) .

You can also use version 18.06 when it was not yet "smart" and it will work regardless of whether the wan interface IP is private or public. The negative side is that the devices that ask for upnp for the public IP, will get a private one and it may not work correctly.

I actually have a public IP address on my WAN interface and none of the miniupnpd packages after 18.06 (miniupnpd v 2.1-1) work with my games consoles.The external_ip parameter won't work me as my IP address is randomly refreshed.

IIRC, they switched the default config for miniupnpd to be 'igdv2', which is current and more secure. However, most consoles can't deal with that, and require the upnp process support igvd1 standards.

The fix is easy, add this to your /etc/config/upnpd settings in the config upnpd section:

option igdv1 '1'

Given the security patches to the process, I recommend you recompile with a current version, and use the setting to revert the igdv support level.
My Xbox One S reports an Open NAT with nothing extra done to achieve that other than having that option set in upnpd.

Is that file definitely at /etc/upnpd or should it be /etc/config/upnpd?

Sorry, it is in /etc/config/upnpd. I've edited the text above.

Cheers. I will recompile without touching miniupnpd and post back. However, I do have strong feeling that setting option igdv1 '1' was one of the first things I enabled in the LuCI-app and it made no difference.

I compiled a large firmware for my Linksys WRT1900ACSv2 last night including miniupnpd and everything opens up fine.

The miniupnpd version is now 2.1.20191006-4 rather than 2.1-1

The only problem now is I'm getting major issues when two games consoles trying to initially connect to the same 3074 port. I have made a post here UPnP Clash WIth Duplicate Initial Port

The problem was a missing chain rule in the iptable filter, it should be fixed once my code is merged https://github.com/openwrt/packages/pull/13951

You can also fix it by ssh to the router and adding the rule yourselves by:
1-Call iptables -L to list all the rules
2-Check your Chain zone_CON_input where CON in my case is wan
3-Count the existing rules below target prot opt source destination
4-Last one should say zone_CON_src_REJECTED
5-Call iptables -I zone_CON_input NUMBER -c 0 0 -j MINIUPNPD to add the needed rule, where NUMBER is the count you've made before, this will add the rule in penultimate, also replace CON.
6-Should be good now. If you also use IPv6, ip6tables should be similar I think.

2 Likes

working now!!!!!

1 Like

how you reproduce your settings in the screen

i have started like this

iptables -t mangle -A PREROUTING -p all -i wan  -j DSCP  --set-dscp-class CS0 
iptables -t mangle -A PREROUTING -p icmp -j DSCP  --set-dscp-class CS6 
#!/bin/ash -x
IPT="iptables"
iptmark="iptables"
##ipset for streming sites.they are bening filled by dnsmasq
ipset create streaming hash:ip
ipset create usrcdn hash:ip
ipset create bulk hash:ip
ipset create latsens hash:ip
## flush mangle table ##
$IPT -t mangle -F PREROUTING
#Clear interface dscp marks, we don't trust ISP marks(also to use our own marks).
$IPT -t mangle -A PREROUTING -i wan -j DSCP --set-dscp 0
########################################
# Latency Sensitive (gaming/voip)
########################################
##Latency Sensitive
$IPT -t mangle -A PREROUTING -p icmp -j DSCP --set-dscp-class CS6 ##dscp tag for ping packets
$IPT -t mangle -A PREROUTING -m set --match-set latsens src -j DSCP --set-dscp-class CS6 ## set dscp tag for our Latency Sensitive (latsens) ipset
$IPT -t mangle -A PREROUTING -p tcp -m conntrack --ctorigsrc 192.168.1.186 -m multiport ! --ports 80,443,8080 -j DSCP --set-dscp-class CS6 -m comment --comment "PS4" #i don't have PS4, change the ip according to your ip setting.
####Latency Sensitive Ports####
sport00="3074"
sport4="9305:9308"
sport16="3478:3479"
dport00="3074:3075,3478:3479,3658:3659,9305:9308"
$IPT -t mangle -A PREROUTING -p udp -m multiport --sport $sport00 -j DSCP --set-dscp-class CS6
$IPT -t mangle -A PREROUTING -p udp -m multiport --sport $sport4 -j DSCP --set-dscp-class AF41
$IPT -t mangle -A PREROUTING -p udp -m multiport --sport $sport16 -j DSCP --set-dscp-class AF41
$IPT -t mangle -A PREROUTING -p udp -m multiport --dport $dport00 -j DSCP --set-dscp-class CS6
$IPT -t mangle -N dscp_mark > /dev/null 2>&1
$IPT -t mangle -F dscp_mark
## check if POSTROUTING already exits then jumps to our tables if not, add them
$IPT -t mangle -L POSTROUTING -n | grep dscp_mark || $IPT -t mangle -A POSTROUTING -o br-lan -j dscp_mark
iptmark() {
    $IPT -t mangle -A dscp_mark "$@"
}
#A robust 2 rules to detect realtime traffic
iptmark -p udp -m hashlimit --hashlimit-name udp_high_prio --hashlimit-above 100/sec --hashlimit-burst 50 --hashlimit-mode srcip,srcport,dstip,dstport -j CONNMARK --set-mark 0x55 -m comment --comment "connmark for udp"
# unmarked UDP streams with small packets get CS6
iptmark -p udp -m connmark ! --mark 0x55 -m multiport ! --ports 22,25,53,67,68,123,143,161,162,514,80,443,8080 -m connbytes --connbytes 0:940 --connbytes-dir both --connbytes-mode avgpkt -j DSCP --set-dscp-class CS6 -m comment --comment "small udp connection gets CS6"
iptmark -p udp -m connmark ! --mark 0x55 -m multiport ! --ports 137,442,444,445,446,447 -m connbytes --connbytes 0:940 --connbytes-dir both --connbytes-mode avgpkt -j DSCP --set-dscp-class CS6 -m comment --comment "small udp connection gets CS6"
#large udp streams like video call get AF41
iptmark -p udp -m connmark ! --mark 0x55 -m multiport ! --ports 22,25,53,67,68,123,143,161,162,514,80,443,8080 -m connbytes --connbytes 940:1500 --connbytes-dir both --connbytes-mode avgpkt -j DSCP --set-dscp-class AF21 -m comment --comment "large udp connection gets AF21"
iptmark -p udp -m connmark ! --mark 0x55 -m multiport ! --ports 137,442,444,445,446,447 -m connbytes --connbytes 940:1500 --connbytes-dir both --connbytes-mode avgpkt -j DSCP --set-dscp-class CS6 -m comment --comment "small udp connection gets CS6"
#DNS traffic both udp and tcp
iptmark -p udp -m multiport --port 53 -j DSCP --set-dscp-class CS6 -m comment --comment "DNS udp"
#NTP
iptmark -p udp -m multiport --port 123 -j DSCP --set-dscp-class CS6 -m comment --comment "NTP udp"
#High priority ipset, i use for pubgM
iptmark ! -p udp -m set --match-set latsens src,dst -j DSCP --set-dscp-class CS6 -m comment --comment "latency sensitive ipset" ## set dscp tag for Latency Sensitive (latsens) ipset,udp
iptmark -p tcp -m set --match-set latsens src,dst -j DSCP --set-dscp-class CS6 -m comment --comment "latency sensitive ipset" ## set dscp tag for Latency Sensitive (latsens) ipset
###########
##Browsing
###########
## medium priority for browsing
iptmark -p tcp -m multiport --ports 80,443 -j DSCP --set-dscp-class CS3 -m comment --comment "Browsing at CS3"
##################
#TCP SYN,ACK flows
##################
#Make sure ACK,SYN packets get priority (to avoid upload speed limiting our download speed)
iptmark -p tcp --tcp-flags ALL ACK -m length --length :128 -j DSCP --set-dscp-class CS3
iptmark -p tcp --tcp-flags ALL SYN -m length --length :666 -j DSCP --set-dscp-class CS3
#Small packet is probably interactive or flow control
iptmark -m dscp ! --dscp  24 -m dscp ! --dscp  18 -m dscp ! --dscp  34 -m dscp ! --dscp  40 -m dscp ! --dscp  48 -m length --length 0:500 -j DSCP --set-dscp-class CS3
#Small packet connections: multi purpose (don't harm since not maxed out)
iptmark -m dscp ! --dscp  24 -m dscp ! --dscp  18 -m dscp ! --dscp  34 -m dscp ! --dscp  40 -m dscp ! --dscp  48 -m connbytes --connbytes 0:250 --connbytes-dir both --connbytes-mode avgpkt -j DSCP --set-dscp-class CS3
########################################
# Streaming Media (videos/audios)
########################################
#Known video streams sites like netflix
iptmark -m set --match-set streaming src,dst -j DSCP --set-dscp-class AF41 -m comment --comment "video audio stream ipset"
#known usrcdn like google or akamai
iptmark -m set --match-set usrcdn src,dst -j DSCP --set-dscp-class AF21 -m comment --comment "usrcdn ipset"
#########################################
# Background Traffic (Bulk/file transfer)
#########################################
#bulk traffic ipset, like windows udates and steam updates/downloads
iptmark -p tcp -m set --match-set bulk src,dst -j DSCP --set-dscp-class CS1 -m comment --comment "bulk traffic ipset"
iptmark -p udp -m set --match-set bulk src,dst -j DSCP --set-dscp-class CS1 -m comment --comment "bulk traffic ipset"
iptmark -p tcp -m connbytes --connbytes 350000: --connbytes-dir both --connbytes-mode bytes -m dscp --dscp-class CS3 -j DSCP --set-dscp-class CS1 -m comment --comment "Downgrade CS3 to CS1 for bulk tcp traffic"

This is what i use for dscp marks in conjunction with upnp and stun server.... Here is my dnsmasq file which needs some updating now that im looking at it...