From b2c4ed56c4104e85770001a606c15f26d6421e20 Mon Sep 17 00:00:00 2001 From: sbwml Date: Sun, 13 Oct 2024 21:11:27 +0800 Subject: [PATCH] miniupnpd: add force_forwarding support Signed-off-by: sbwml --- files/miniupnpd.init | 3 + files/upnpd.config | 1 + ...301-options-force_forwarding-support.patch | 185 ++++++++++++++++++ 3 files changed, 189 insertions(+) create mode 100644 patches/301-options-force_forwarding-support.patch diff --git a/files/miniupnpd.init b/files/miniupnpd.init index e89e4e5..8e37eab 100644 --- a/files/miniupnpd.init +++ b/files/miniupnpd.init @@ -63,6 +63,7 @@ upnpd() { local use_stun stun_host stun_port uuid notify_interval presentation_url local upnp_lease_file clean_ruleset_threshold clean_ruleset_interval local ipv6_disable + local force_forwarding local enabled config_get_bool enabled config enabled 1 @@ -90,6 +91,7 @@ upnpd() { config_get clean_ruleset_threshold config clean_ruleset_threshold config_get clean_ruleset_interval config clean_ruleset_interval config_get ipv6_disable config ipv6_disable 0 + config_get force_forwarding config force_forwarding 0 local conf ifname ifname6 @@ -142,6 +144,7 @@ upnpd() { upnpd_write_bool igdv1 0 force_igd_desc_v1 upnpd_write_bool use_stun 0 ext_perform_stun upnpd_write_bool ipv6_disable $ipv6_disable + upnpd_write_bool force_forwarding $force_forwarding [ "$use_stun" -eq 0 ] || { [ -n "$stun_host" ] && echo "ext_stun_host=$stun_host" diff --git a/files/upnpd.config b/files/upnpd.config index bd7c3ec..9070c27 100644 --- a/files/upnpd.config +++ b/files/upnpd.config @@ -2,6 +2,7 @@ config upnpd config option enabled 0 option enable_natpmp 1 option enable_upnp 1 + option force_forwarding 1 option secure_mode 1 option log_output 0 option download 1024 diff --git a/patches/301-options-force_forwarding-support.patch b/patches/301-options-force_forwarding-support.patch new file mode 100644 index 0000000..6d1c7dd --- /dev/null +++ b/patches/301-options-force_forwarding-support.patch @@ -0,0 +1,185 @@ +From 09690d550a1ad3cc3a8cba79aa2e970c3b2b8fbe Mon Sep 17 00:00:00 2001 +From: Chen Minqiang +Date: Sun, 5 Jul 2020 10:42:52 +0800 +Subject: [PATCH] options: force_forwarding support + +This make the port forwarding force to work even +when the router is behind NAT + +Signed-off-by: Chen Minqiang +--- + miniupnpd.c | 12 ++++++++---- + miniupnpd.conf | 2 ++ + natpmp.c | 2 +- + options.c | 1 + + options.h | 1 + + testgetifaddr.c | 2 ++ + testportinuse.c | 2 ++ + upnpdescgen.c | 2 +- + upnpglobalvars.h | 2 ++ + upnpredirect.c | 2 +- + upnpsoap.c | 6 +++++- + 11 files changed, 26 insertions(+), 8 deletions(-) + +--- a/miniupnpd.c ++++ b/miniupnpd.c +@@ -1018,7 +1018,7 @@ parselanaddr(struct lan_addr_s * lan_add + INIT_PRINT_ERR("Error parsing address : %s\n", lan_addr->ext_ip_str); + return -1; + } +- if(addr_is_reserved(&lan_addr->ext_ip_addr)) { ++ if(addr_is_reserved(&lan_addr->ext_ip_addr) && !GETFLAG(FORCEFORWARDINGMASK)) { + /* error */ + INIT_PRINT_ERR("Error: option ext_ip address contains reserved / private address : %s\n", lan_addr->ext_ip_str); + return -1; +@@ -1260,6 +1260,10 @@ init(int argc, char * * argv, struct run + case UPNPEXT_IP: + use_ext_ip_addr = ary_options[i].value; + break; ++ case UPNP_FORCE_FORWARDING: ++ if(strcmp(ary_options[i].value, "yes") == 0) ++ SETFLAG(FORCEFORWARDINGMASK); ++ break; + case UPNPEXT_PERFORM_STUN: + if(strcmp(ary_options[i].value, "yes") == 0) + SETFLAG(PERFORMSTUNMASK); +@@ -1867,7 +1871,7 @@ init(int argc, char * * argv, struct run + INIT_PRINT_ERR("Error: option ext_ip contains invalid address %s\n", use_ext_ip_addr); + return 1; + } +- if (addr_is_reserved(&addr)) { ++ if (addr_is_reserved(&addr) && !GETFLAG(FORCEFORWARDINGMASK)) { + INIT_PRINT_ERR("Error: option ext_ip contains reserved / private address %s, not public routable\n", use_ext_ip_addr); + return 1; + } +@@ -2315,7 +2319,7 @@ main(int argc, char * * argv) + if (getifaddr(ext_if_name, if_addr, INET_ADDRSTRLEN, &addr, NULL) < 0) { + syslog(LOG_WARNING, "Cannot get IP address for ext interface %s. Network is down", ext_if_name); + disable_port_forwarding = 1; +- } else if (addr_is_reserved(&addr)) { ++ } else if (addr_is_reserved(&addr) && !GETFLAG(FORCEFORWARDINGMASK)) { + syslog(LOG_INFO, "Reserved / private IP address %s on ext interface %s: Port forwarding is impossible", if_addr, ext_if_name); + syslog(LOG_INFO, "You are probably behind NAT, enable option ext_perform_stun=yes to detect public IP address"); + syslog(LOG_INFO, "Or use ext_ip= / -o option to declare public IP address"); +@@ -2628,7 +2632,7 @@ main(int argc, char * * argv) + syslog(LOG_WARNING, "Cannot get IP address for ext interface %s. Network is down", ext_if_name); + disable_port_forwarding = 1; + } else { +- int reserved = addr_is_reserved(&addr); ++ int reserved = addr_is_reserved(&addr) && !GETFLAG(FORCEFORWARDINGMASK); + if (!disable_port_forwarding && reserved) { + syslog(LOG_INFO, "Reserved / private IP address %s on ext interface %s: Port forwarding is impossible", if_addr, ext_if_name); + syslog(LOG_INFO, "You are probably behind NAT, enable option ext_perform_stun=yes to detect public IP address"); +--- a/miniupnpd.conf ++++ b/miniupnpd.conf +@@ -18,6 +18,9 @@ + # the public IP address. + #ext_ip= + ++# force forwarding enable for upnp: default is no ++#force_forwarding=yes ++ + # The WAN interface must have a public IP address. Otherwise it is behind NAT + # and port forwarding is impossible. In some cases WAN interface can be + # behind unrestricted full-cone NAT 1:1 when all incoming traffic is NAT-ed and +--- a/natpmp.c ++++ b/natpmp.c +@@ -109,7 +109,7 @@ static void FillPublicAddressResponse(un + syslog(LOG_ERR, "Failed to get IP for interface %s", ext_if_name); + resp[3] = 3; /* Network Failure (e.g. NAT box itself + * has not obtained a DHCP lease) */ +- } else if (addr_is_reserved(&addr)) { ++ } else if (addr_is_reserved(&addr) && !GETFLAG(FORCEFORWARDINGMASK)) { + resp[3] = 3; /* Network Failure, box has not obtained + public IP address */ + } else { +--- a/options.c ++++ b/options.c +@@ -35,6 +35,7 @@ static const struct { + { UPNPEXT_IFNAME6, "ext_ifname6" }, + #endif + { UPNPEXT_IP, "ext_ip" }, ++ { UPNP_FORCE_FORWARDING, "force_forwarding" }, + { UPNPEXT_PERFORM_STUN, "ext_perform_stun" }, + { UPNPEXT_STUN_HOST, "ext_stun_host" }, + { UPNPEXT_STUN_PORT, "ext_stun_port" }, +--- a/options.h ++++ b/options.h +@@ -21,6 +21,7 @@ enum upnpconfigoptions { + UPNPEXT_IFNAME6, /* ext_ifname6 */ + #endif + UPNPEXT_IP, /* ext_ip */ ++ UPNP_FORCE_FORWARDING, /* force forwarding enable for upnp */ + UPNPEXT_PERFORM_STUN, /* ext_perform_stun */ + UPNPEXT_STUN_HOST, /* ext_stun_host */ + UPNPEXT_STUN_PORT, /* ext_stun_port */ +--- a/testgetifaddr.c ++++ b/testgetifaddr.c +@@ -13,6 +13,8 @@ + #include "config.h" + #include "getifaddr.h" + ++int runtime_flags = 0; ++ + #if defined(__sun) + /* solaris 10 does not define LOG_PERROR */ + #define LOG_PERROR 0 +--- a/testportinuse.c ++++ b/testportinuse.c +@@ -14,6 +14,8 @@ + #include "config.h" + #include "portinuse.h" + ++int runtime_flags = 0; ++ + int main(int argc, char * * argv) + { + #ifndef CHECK_PORTINUSE +--- a/upnpdescgen.c ++++ b/upnpdescgen.c +@@ -1316,7 +1316,7 @@ genEventVars(int * len, const struct ser + else { + struct in_addr addr; + char ext_ip_addr[INET_ADDRSTRLEN]; +- if(getifaddr(ext_if_name, ext_ip_addr, INET_ADDRSTRLEN, &addr, NULL) < 0 || addr_is_reserved(&addr)) { ++ if(getifaddr(ext_if_name, ext_ip_addr, INET_ADDRSTRLEN, &addr, NULL) < 0 || (addr_is_reserved(&addr) && !GETFLAG(FORCEFORWARDINGMASK))) { + str = strcat_str(str, len, &tmplen, "0.0.0.0"); + } else { + str = strcat_str(str, len, &tmplen, ext_ip_addr); +--- a/upnpglobalvars.h ++++ b/upnpglobalvars.h +@@ -87,6 +87,8 @@ extern int runtime_flags; + + #define PERFORMSTUNMASK 0x1000 + ++#define FORCEFORWARDINGMASK 0x2000 ++ + #define SETFLAG(mask) runtime_flags |= mask + #define GETFLAG(mask) (runtime_flags & mask) + #define CLEARFLAG(mask) runtime_flags &= ~mask +--- a/upnpredirect.c ++++ b/upnpredirect.c +@@ -444,7 +444,7 @@ upnp_redirect_internal(const char * rhos + { + /*syslog(LOG_INFO, "redirecting port %hu to %s:%hu protocol %s for: %s", + eport, iaddr, iport, protocol, desc); */ +- if(disable_port_forwarding) ++ if(disable_port_forwarding && !GETFLAG(FORCEFORWARDINGMASK)) + return -1; + if(add_redirect_rule2(ext_if_name, rhost, eport, iaddr, iport, proto, + desc, timestamp) < 0) { +--- a/upnpsoap.c ++++ b/upnpsoap.c +@@ -348,7 +348,11 @@ GetExternalIPAddress(struct upnphttp * h + ext_ip_addr[0] = '\0'; + } else if (addr_is_reserved(&addr)) { + syslog(LOG_NOTICE, "private/reserved address %s is not suitable for external IP", ext_ip_addr); +- ext_ip_addr[0] = '\0'; ++ if (!GETFLAG(FORCEFORWARDINGMASK)) { ++ ext_ip_addr[0] = '\0'; ++ } else { ++ syslog(LOG_NOTICE, "force_forwarding enable, private/reserved address %s used as external IP", ext_ip_addr); ++ } + } + } + #else