Files
op-packages/miniupnpd/patches/020-improve-logging.patch

2455 lines
100 KiB
Diff

From 7305912d42053e72ebe4c70960204efd51e42806 Mon Sep 17 00:00:00 2001
From: Self-Hosting-Group
<155233284+Self-Hosting-Group@users.noreply.github.com>
Date: Mon, 12 Oct 2026 00:00:00 +0000
Subject: [PATCH] miniupnpd: Improve logging and CGNAT use
* Clearer logging of enabled protocols/ports, IPv6 mapping, and UPnP IGD
compatibility mode… in start banner
* Log warnings with an enabled allow third-party mapping option
* Change the log level (less verbose) of many internal or normally
occurring messages, and some error messages, without functional
restrictions, to DEBUG, client requests/actions and their errors to
INFO, and only daemon-wide messages to NOTICE/WARNING/ERR…
* Comment out some log-filling messages when internal interfaces lose
link, and for e.g. `rule with label '%s' is not a IGD pinhole`, as
normally occurring
* Log IPv4 mapping disabled/enabled messages by default
* Fix IPv4 mapping re-enable after external interface down/up with a
CGNAT option set; handling was previously not entirely implemented for
both options, incl. miniupnp/miniupnp@bbdd738, miniupnp/miniupnp#905
* No IPv4 mapping disabled logging on requests, but more cases
* Clearer IPv4 mapping disabled/enabled logging
* Add `default_min_port`/max options for IPv6/IPv4
* Standardise request/action logging with `LOG_INFO`
Fixes: https://github.com/openwrt/packages/issues/11971
Fixes: https://github.com/openwrt/packages/issues/17601
Fixes: https://github.com/openwrt/packages/issues/26483
Link: https://github.com/miniupnp/miniupnp/pull/764
---
INSTALL | 45 +++---
asyncsendto.c | 4 +-
getifaddr.c | 4 +-
minissdp.c | 24 +--
miniupnpd.c | 244 ++++++++++++++++++------------
miniupnpd.conf | 258 +++++++++++++++++---------------
natpmp.c | 39 ++---
netfilter/iptcrdr.c | 13 +-
netfilter/iptpinhole.c | 10 +-
netfilter_nft/nftnlrdr.c | 4 +-
netfilter_nft/nftnlrdr_misc.c | 8 +-
netfilter_nft/nftpinhole.c | 16 +-
options.c | 7 +-
options.h | 6 +-
pcpserver.c | 100 ++++++++-----
pf/obsdrdr.c | 2 +-
pf/pfpinhole.c | 12 +-
upnpdescgen.c | 2 +-
upnpglobalvars.h | 2 +-
upnphttp.c | 6 +-
upnppermissions.c | 14 +-
upnppermissions.h | 3 +
upnppinhole.c | 16 +-
upnpredirect.c | 32 ++--
upnpsoap.c | 107 +++++++------
upnpstun.c | 37 ++---
26 files changed, 554 insertions(+), 461 deletions(-)
--- a/INSTALL
+++ b/INSTALL
@@ -156,7 +156,7 @@ ext_ifname : WAN network interface (in
listening_ip : LAN network interface (network where to supply NAT traversal)
enable_pcp_pmp=yes
enable_upnp=yes
-and the permission rules (see below).
+and the access control settings (see below).
Historically, LAN had to be specified by IP/mask, such as
listening_ip=192.168.0.1/24
@@ -168,42 +168,31 @@ the wrong mask would be picked. You can
names :
listening_ip=eth0/24
-Some users want to use miniupnpd on a NAT router which is connected to the
-internet through another NAT router (NAT behind NAT). This kind of setup is
-strongly discouraged. By default, miniupnpd will refuses to launch when
-detecting a private (RFC1918) "WAN" IP address. The ext_ip option sould be
-added :
-ext_ifname=eth1 # "WAN" network interface, whose IP could be 192.168.1.22
-ext_ip=80.1.2.3 # Real public IP address
-listening_ip=eth0
-Please note that miniupnpd doesn't redirect any port on the other NAT router.
-UPNP requests forwarding is not implemented.
-In such NAT behind NAT setups, it is also possible to use STUN :
-See the ext_perform_stun / ext_stun_host / ext_stun_port options.
-If you know what you do and want to disable the restriction on the "WAN" IP
-address, you can use the option :
-ext_allow_private_ipv4=yes
-
it is also possible to set a different interface for IPv6 WAN
ext_ifname=eth0
ext_ifname6=sit0
+Allow CGNAT use
+To enable IPv4 mapping even when using a CGNAT with a private/CGNAT-reserved
+external IPv4 address, users should refer to the documentation for the
+ext_allow_cgnat option in the sample miniupnpd.conf config file
+
miniupnpd supports some kind of security check for allowing or disallowing
-redirection to be made. The UPnP permission rules are read from the
+port maps to be made. Access control list (ACL) entries are read from the
miniupnpd.conf configuration file.
-When a new redirection is requested, permission rules are evaluated in
-top-down order and the first permission rule matched gives the response :
-redirection allowed or denied. If no rule is matching, the redirection is
-allowed, so it is a good practice to have a "catch all" deny permission
-rule at the end of your permission ruleset.
-Sample permission ruleset :
+When a new port map is requested, ACL entries are evaluated in
+top-down order and the first ACL entry matched gives the response :
+port map allowed or denied. If no entry is matching, the port map is
+allowed, so it is a good practice to have a "catch all" deny ACL entry
+at the end of your ACL.
+Sample ACL:
allow 4662-4672 192.168.1.34/32 4662-4672
-deny 0-65535 192.168.1.34/32 0-65535
+deny 1-65535 192.168.1.34 1-65535
allow 1024-65535 192.168.1.0/24 1024-65535
-deny 0-65535 0.0.0.0/0 0-65535
-With this ruleset, redirections are allowed only for host on the subnet
+deny 1-65535 0.0.0.0/0 1-65535
+With this ACL, port maps are allowed only for host on the subnet
192.168.1.0/255.255.255.0 for the ports 1024 or above. There is an exception
-for the host 192.168.1.34 for which only redirections from/to port 4662 to
+for the host 192.168.1.34 for which only port maps from/to port 4662 to
4672 are allowed.
You can generate the uuid for your UPnP device with the uuidgen available
--- a/asyncsendto.c
+++ b/asyncsendto.c
@@ -254,9 +254,9 @@ int try_sendto(fd_set * writefds)
/* uncatched error */
if(sockaddr_to_string(elt->dest_addr, addr_str, sizeof(addr_str)) <= 0)
addr_str[0] = '\0';
- syslog(LOG_ERR, "%s(sock=%d, len=%u, dest=%s): sendto: %m",
+ /*syslog(LOG_DEBUG, "%s(sock=%d, len=%u, dest=%s): sendto: %m",
"try_sendto", elt->sockfd, (unsigned)elt->len,
- addr_str);
+ addr_str);*/
ret--;
}
} else if((int)n != (int)elt->len) {
--- a/getifaddr.c
+++ b/getifaddr.c
@@ -74,7 +74,7 @@ getifaddr(const char * ifname, char * bu
} else {
r = GETIFADDR_IOCTL_ERROR;
}
- syslog(LOG_ERR, "ioctl(s, SIOCGIFADDR, ...): %m");
+ syslog(LOG_DEBUG, "ioctl(s, SIOCGIFADDR, ...): %m");
close(s);
return r;
}
@@ -149,7 +149,7 @@ getifaddr(const char * ifname, char * bu
if(addr) *addr = ((struct sockaddr_in *)candidate->ifa_addr)->sin_addr;
if(mask) *mask = ((struct sockaddr_in *)candidate->ifa_netmask)->sin_addr;
} else {
- syslog(LOG_WARNING, "no AF_INET address found for %s", ifname);
+ syslog(LOG_DEBUG, "no AF_INET address found for %s", ifname);
freeifaddrs(ifap);
return GETIFADDR_NO_ADDRESS;
}
--- a/minissdp.c
+++ b/minissdp.c
@@ -743,8 +743,8 @@ SendSSDPNotify(int s, const struct socka
}
n = sendto_or_schedule(s, bufr, l, 0, dest, dest_len);
if(n < 0) {
- syslog(LOG_ERR, "sendto(udp_notify=%d, %s): %m", s,
- host ? host : "NULL");
+ /*syslog(LOG_DEBUG, "sendto(udp_notify=%d, %s): %m", s,
+ host ? host : "NULL");*/
} else if(n != l) {
syslog(LOG_NOTICE, "sendto() sent %d out of %d bytes", n, l);
}
@@ -754,8 +754,8 @@ SendSSDPNotify(int s, const struct socka
* discovery messages SHOULD NOT be sent more than three times. */
n = sendto_schedule(s, bufr, l, 0, dest, dest_len, 250);
if(n < 0) {
- syslog(LOG_ERR, "sendto(udp_notify=%d, %s): %m", s,
- host ? host : "NULL");
+ /*syslog(LOG_DEBUG, "sendto(udp_notify=%d, %s): %m", s,
+ host ? host : "NULL");*/
}
}
@@ -1060,7 +1060,7 @@ ProcessSSDPData(int s, const char *bufr,
}
if(lan_addr == NULL)
{
- syslog(LOG_WARNING, "SSDP packet sender %s (if_index=%d) not from a LAN, ignoring",
+ syslog(LOG_DEBUG, "SSDP packet sender %s (if_index=%d) not from a LAN, ignoring",
sender_str, source_if);
return;
}
@@ -1175,7 +1175,7 @@ ProcessSSDPData(int s, const char *bufr,
sender_str );*/
if(st && (st_len > 0))
{
- syslog(LOG_INFO, "SSDP M-SEARCH from %s ST: %.*s",
+ syslog(LOG_DEBUG, "SSDP M-SEARCH from %s ST: %.*s",
sender_str, st_len, st);
/* find in which sub network the client is */
#ifdef ENABLE_IPV6
@@ -1288,7 +1288,7 @@ ProcessSSDPData(int s, const char *bufr,
else
snprintf(ver_str, sizeof(ver_str), "%d", known_service_types[i].version);
#endif
- syslog(LOG_INFO, "Single search found");
+ syslog(LOG_DEBUG, "Single search found");
#ifdef DELAY_MSEARCH_RESPONSE
delay = random() / (1 + RAND_MAX / (1000 * mx_value));
#ifdef DEBUG
@@ -1317,7 +1317,7 @@ ProcessSSDPData(int s, const char *bufr,
#ifdef DELAY_MSEARCH_RESPONSE
unsigned int delay_increment = (mx_value * 1000) / 15;
#endif
- syslog(LOG_INFO, "ssdp:all found");
+ syslog(LOG_DEBUG, "ssdp:all found");
for(i=0; known_service_types[i].s; i++)
{
#ifdef DELAY_MSEARCH_RESPONSE
@@ -1375,7 +1375,7 @@ ProcessSSDPData(int s, const char *bufr,
#endif
if(0 == memcmp(st, uuidvalue_igd, l))
{
- syslog(LOG_INFO, "ssdp:uuid (IGD) found");
+ syslog(LOG_DEBUG, "ssdp:uuid (IGD) found");
SendSSDPResponse(s, sender, st, st_len, "",
announced_host, http_port,
#ifdef ENABLE_HTTPS
@@ -1385,7 +1385,7 @@ ProcessSSDPData(int s, const char *bufr,
}
else if(0 == memcmp(st, uuidvalue_wan, l))
{
- syslog(LOG_INFO, "ssdp:uuid (WAN) found");
+ syslog(LOG_DEBUG, "ssdp:uuid (WAN) found");
SendSSDPResponse(s, sender, st, st_len, "",
announced_host, http_port,
#ifdef ENABLE_HTTPS
@@ -1395,7 +1395,7 @@ ProcessSSDPData(int s, const char *bufr,
}
else if(0 == memcmp(st, uuidvalue_wcd, l))
{
- syslog(LOG_INFO, "ssdp:uuid (WCD) found");
+ syslog(LOG_DEBUG, "ssdp:uuid (WCD) found");
SendSSDPResponse(s, sender, st, st_len, "",
announced_host, http_port,
#ifdef ENABLE_HTTPS
@@ -1456,7 +1456,7 @@ SendSSDPbyebye(int s, const struct socka
n = sendto_or_schedule(s, bufr, l, 0, dest, destlen);
if(n < 0)
{
- syslog(LOG_ERR, "sendto(udp_shutdown=%d) to %s: %m", s, dest_str);
+ syslog(LOG_DEBUG, "sendto(udp_shutdown=%d) to %s: %m", s, dest_str);
return -1;
}
else if(n != l)
--- a/miniupnpd.c
+++ b/miniupnpd.c
@@ -495,7 +495,7 @@ ProcessIncomingHTTP(int shttpl, const ch
if(get_lan_for_peer((struct sockaddr *)&clientname) == NULL)
{
/* The peer is not a LAN ! */
- syslog(LOG_WARNING,
+ syslog(LOG_DEBUG,
"%s peer %s is not from a LAN, closing the connection",
protocol, addr_str);
close(shttp);
@@ -866,7 +866,7 @@ set_startup_time(void)
}
else
{
- syslog(LOG_INFO, "system uptime is %lu seconds", uptime);
+ syslog(LOG_DEBUG, "system uptime is %lu seconds", uptime);
}
fclose(f);
startup_time -= uptime;
@@ -1059,11 +1059,11 @@ parselanaddr(struct lan_addr_s * lan_add
return -1;
}
if(addr_is_reserved(&lan_addr->ext_ip_addr)) {
- if (GETFLAG(ALLOWPRIVATEIPV4MASK)) {
- syslog(LOG_WARNING, "IGNORED : option ext_ip address contains reserved / private address : %s", lan_addr->ext_ip_str);
+ if (GETFLAG(REPORTPRIVATEIPV4MASK)) {
+ syslog(LOG_WARNING, "WARNING: IPv4 mapping enabled forcibly, as ext_allow_cgnat=report-private-ipv4 set; check security note if not set");
} else {
/* error */
- INIT_PRINT_ERR("Error: option ext_ip address contains reserved / private address : %s\n", lan_addr->ext_ip_str);
+ INIT_PRINT_ERR("Option ext_ip set to private/CGNAT-reserved (%s) IPv4, exiting\n", lan_addr->ext_ip_str);
return -1;
}
}
@@ -1117,20 +1117,19 @@ parselan_error:
static char ext_addr_str[INET_ADDRSTRLEN];
-int update_ext_ip_addr_from_stun(int init)
+int update_ext_ip_addr_from_stun(void)
{
struct in_addr if_addr, ext_addr;
- int restrictive_nat;
+ int restrictive_nat, reserved;
char if_addr_str[INET_ADDRSTRLEN];
- syslog(LOG_INFO, "STUN: Performing with host=%s and port=%u ...", ext_stun_host, (unsigned)ext_stun_port);
-
if (getifaddr(ext_if_name, if_addr_str, INET_ADDRSTRLEN, &if_addr, NULL) < 0) {
- syslog(LOG_ERR, "STUN: Cannot get IP address for ext interface %s", ext_if_name);
+ syslog(LOG_ERR, "Detected no IPv4 address on external network interface %s", ext_if_name);
return 1;
}
+ syslog(LOG_INFO, "STUN: Detecting public IPv4 and testing for unrestricted endpoint-independent (1:1) CGNAT via %s:%u...", ext_stun_host, ext_stun_port ? ext_stun_port : 3478);
if (perform_stun(ext_if_name, if_addr_str, ext_stun_host, ext_stun_port, &ext_addr, &restrictive_nat) != 0) {
- syslog(LOG_ERR, "STUN: Performing STUN failed: %s", strerror(errno));
+ syslog(LOG_ERR, "STUN: Performing test failed");
return 1;
}
if (!inet_ntop(AF_INET, &ext_addr, ext_addr_str, sizeof(ext_addr_str))) {
@@ -1138,32 +1137,29 @@ int update_ext_ip_addr_from_stun(int ini
return 1;
}
- if ((init || disable_port_forwarding) && !restrictive_nat) {
- if (addr_is_reserved(&if_addr))
- syslog(LOG_INFO, "STUN: ext interface %s with IP address %s is now behind unrestricted full-cone NAT 1:1 with public IP address %s and firewall does not block incoming connections set by miniupnpd", ext_if_name, if_addr_str, ext_addr_str);
- else
- syslog(LOG_INFO, "STUN: ext interface %s has now public IP address %s and firewall does not block incoming connections set by miniupnpd", ext_if_name, if_addr_str);
- syslog(LOG_INFO, "Port forwarding is now enabled");
- } else if ((init || !disable_port_forwarding) && restrictive_nat) {
- if (addr_is_reserved(&if_addr)) {
- syslog(LOG_WARNING, "STUN: ext interface %s with private IP address %s is now possibly behind restrictive or symmetric NAT with public IP address %s which does not support port forwarding", ext_if_name, if_addr_str, ext_addr_str);
- syslog(LOG_WARNING, "NAT on upstream router blocks incoming connections set by miniupnpd");
- syslog(LOG_WARNING, "Turn off NAT on upstream router or change it to full-cone NAT 1:1 type");
+ reserved = addr_is_reserved(&if_addr);
+ if (!restrictive_nat && !reserved) {
+ syslog(LOG_INFO, "STUN: Detected unrestricted public external IPv4 %s on %s", if_addr_str, ext_if_name);
+ } else if (!restrictive_nat && reserved) {
+ syslog(LOG_INFO, "STUN: Detected unrestricted endpoint-independent (1:1) CGNAT with public IPv4 %s and %s as external on %s", ext_addr_str, if_addr_str, ext_if_name);
+ } else if (restrictive_nat && !reserved) {
+ syslog(LOG_INFO, "STUN: Detected restricted public external IPv4 %s on %s, IPv4 mapping may not work", if_addr_str, ext_if_name);
+ } else if (restrictive_nat && reserved) {
+ syslog(LOG_INFO, "STUN: Detected restricted or address- and port-dependent (symmetric) CGNAT with public IPv4 %s and %s as external on %s, IPv4 mapping may not work", ext_addr_str, if_addr_str, ext_if_name);
+ }
+
+ use_ext_ip_addr = ext_addr_str;
+ if (!restrictive_nat || GETFLAG(ALLOWFILTEREDSTUNMASK)) {
+ if (!restrictive_nat) {
+ syslog(LOG_NOTICE, "IPv4 mapping enabled, and reachability/non-filtering tested via STUN");
} else {
- syslog(LOG_WARNING, "STUN: ext interface %s has now public IP address %s but firewall filters incoming connections set by miniunnpd", ext_if_name, if_addr_str);
- syslog(LOG_WARNING, "Check configuration of firewall on local machine and also on upstream router");
- }
- if (!GETFLAG(ALLOWFILTEREDSTUNMASK)) {
- syslog(LOG_WARNING, "Port forwarding is now disabled");
- syslog(LOG_WARNING, "Set ext_perform_stun=allow-filtered if you still want to use port forwarding in current situation");
+ syslog(LOG_WARNING, "WARNING: IPv4 mapping enabled forcibly, as ext_allow_cgnat=allow-filtered set; check security note if not set");
}
+ disable_port_forwarding = 0;
} else {
- syslog(LOG_INFO, "STUN: ... done");
+ syslog(LOG_WARNING, "IPv4 mapping disabled, as own/upstream router filters incoming, or there is an address- and port-dependent (symmetric) CGNAT; to workaround current daemon limitation, or enable it anyway, set ext_allow_cgnat=allow-filtered; check security note if not set");
+ disable_port_forwarding = 1;
}
-
- use_ext_ip_addr = ext_addr_str;
- if (!GETFLAG(ALLOWFILTEREDSTUNMASK))
- disable_port_forwarding = restrictive_nat;
return 0;
}
@@ -1183,32 +1179,41 @@ static void update_disable_port_forwardi
syslog(LOG_WARNING, "ext interface %s is down", ext_if_name);
break;
case GETIFADDR_NO_ADDRESS:
- syslog(LOG_WARNING, "ext interface %s has no IPv4 address. Network is down", ext_if_name);
+ syslog(LOG_ERR, "Detected no IPv4 address on external network interface %s", ext_if_name);
break;
default:
- syslog(LOG_ERR, "Error getting IPv4 address for ext interface %s. Network is down", ext_if_name);
+ syslog(LOG_ERR, "Detected no IPv4 address on external network interface %s", ext_if_name);
}
+ syslog(LOG_WARNING, "IPv4 mapping disabled");
disable_port_forwarding = 1;
+
} else {
int reserved = addr_is_reserved(&addr);
- if (!disable_port_forwarding && reserved) {
- if (GETFLAG(ALLOWPRIVATEIPV4MASK)) {
- syslog(LOG_WARNING, "IGNORED : Reserved / private IP address %s on ext interface %s", if_addr, ext_if_name);
- } else {
- syslog(LOG_WARNING, "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");
- syslog(LOG_INFO, "In case that miniupnpd is thinking that it's behind symmetric NAT while it actually is full-cone");
- syslog(LOG_INFO, "You can set option ext_allow_private_ipv4=yes to enable port forwarding");
- syslog(LOG_INFO, "But you may still need to configure stun server or ext_ip to make it work correctly");
- syslog(LOG_INFO, "Public IP address is required by UPnP/PCP/PMP protocols and clients do not work without it");
- disable_port_forwarding = 1;
- }
- } else if (disable_port_forwarding &&
- (!reserved || GETFLAG(ALLOWPRIVATEIPV4MASK))) {
- syslog(LOG_INFO, "%s IP address %s on ext interface %s: Port forwarding is enabled",
- reserved ? "Reserved / private" : "Public", if_addr, ext_if_name);
+ if (!reserved) {
+ syslog(LOG_INFO, "Detected public external IPv4 %s on %s", if_addr, ext_if_name);
+ } else {
+ syslog(LOG_INFO, "Detected private/CGNAT-reserved external IPv4 %s on %s, IPv4 mapping may not work", if_addr, ext_if_name);
+ }
+
+ if (!reserved || GETFLAG(REPORTPRIVATEIPV4MASK)) {
+ if (!reserved) {
+ syslog(LOG_NOTICE, "IPv4 mapping enabled");
+ } else {
+ syslog(LOG_WARNING, "WARNING: IPv4 mapping enabled forcibly, as ext_allow_cgnat=report-private-ipv4 set; check compatibility/security notes if not set");
+ }
disable_port_forwarding = 0;
+ } else {
+ syslog(LOG_WARNING, "IPv4 mapping disabled by default, as private/CGNAT-reserved external IPv4 detected. Prevented for:");
+ syslog(LOG_WARNING, "- Info, as port maps not reachable via internet without an unrestricted endpoint-independent (1:1) IPv4 CGNAT, but possibly from within");
+ syslog(LOG_WARNING, "- Compatibility, as many UPnP IGD & PCP/NAT-PMP clients require a returned public external IPv4 address");
+ syslog(LOG_WARNING, "- Security, to prevent access via internet if the external/internal network interface has been configured swapped");
+ syslog(LOG_WARNING, "To enable IPv4 mapping in this case, select a priority-listed option:");
+ syslog(LOG_WARNING, "A) Detect public external IPv4 and test for unrestricted endpoint-independent (1:1) CGNAT via STUN server, set ext_allow_cgnat=yes");
+ syslog(LOG_WARNING, "B) As A, but workaround filtered CGNAT result daemon limitation (without extra firewall rule), set ext_allow_cgnat=allow-filtered; check security note");
+ syslog(LOG_WARNING, "C) Manually override reported external IPv4 with public, set ext_ip; check security note");
+ syslog(LOG_WARNING, "D) Report private/CGNAT-reserved external IPv4 to clients, set ext_allow_cgnat=report-private-ipv4; check compatibility/security notes");
+ syslog(LOG_WARNING, "IPv4 mapping disabled");
+ disable_port_forwarding = 1;
}
}
}
@@ -1458,11 +1463,7 @@ init(int argc, char * * argv, struct run
case UPNPEXT_IP:
use_ext_ip_addr = ary_options[i].value;
break;
- case UPNPEXT_ALLOW_PRIVATE_IPV4:
- if(strcmp(ary_options[i].value, "yes") == 0)
- SETFLAG(ALLOWPRIVATEIPV4MASK);
- break;
- case UPNPEXT_PERFORM_STUN:
+ case UPNPEXT_ALLOW_CGNAT:
if(strcmp(ary_options[i].value, "yes") == 0)
SETFLAG(PERFORMSTUNMASK);
else if(strcmp(ary_options[i].value, "allow-filtered") == 0)
@@ -1470,6 +1471,14 @@ init(int argc, char * * argv, struct run
SETFLAG(PERFORMSTUNMASK);
SETFLAG(ALLOWFILTEREDSTUNMASK);
}
+ else if(strcmp(ary_options[i].value, "report-private-ipv4") == 0)
+ {
+ SETFLAG(REPORTPRIVATEIPV4MASK);
+ }
+ break;
+ case UPNPEXT_REPORT_PRIVATE_IPV4:
+ if(strcmp(ary_options[i].value, "yes") == 0)
+ SETFLAG(REPORTPRIVATEIPV4MASK);
break;
case UPNPEXT_STUN_HOST:
ext_stun_host = ary_options[i].value;
@@ -1509,6 +1518,12 @@ init(int argc, char * * argv, struct run
SETFLAG(IPV6DISABLEDMASK);
break;
#endif /* ENABLE_IPV6 */
+ case DEFAULT_MIN_PORT:
+ default_min_port = atoi(ary_options[i].value);
+ break;
+ case DEFAULT_MAX_PORT:
+ default_max_port = atoi(ary_options[i].value);
+ break;
case UPNPPORT:
v->port = atoi(ary_options[i].value);
break;
@@ -1696,7 +1711,7 @@ init(int argc, char * * argv, struct run
}
#endif /* ENABLE_PCP */
if (GETFLAG(PERFORMSTUNMASK) && !ext_stun_host) {
- INIT_PRINT_ERR("You must specify ext_stun_host= when ext_perform_stun=yes\n");
+ INIT_PRINT_ERR("You must specify ext_stun_host= when ext_allow_cgnat=yes/allow-filtered\n");
return 1;
}
}
@@ -2083,7 +2098,7 @@ init(int argc, char * * argv, struct run
#endif
if (use_ext_ip_addr && GETFLAG(PERFORMSTUNMASK)) {
- INIT_PRINT_ERR("Error: options ext_ip= and ext_perform_stun=yes cannot be specified together\n");
+ INIT_PRINT_ERR("Error: options ext_ip= and ext_allow_cgnat=yes/allow-filtered cannot be specified together\n");
return 1;
}
@@ -2093,10 +2108,10 @@ init(int argc, char * * argv, struct run
return 1;
}
if (addr_is_reserved(&addr)) {
- if (GETFLAG(ALLOWPRIVATEIPV4MASK)) {
- syslog(LOG_WARNING, "IGNORED : option ext_ip contains reserved / private address %s, not public routable", use_ext_ip_addr);
+ if (GETFLAG(REPORTPRIVATEIPV4MASK)) {
+ syslog(LOG_WARNING, "WARNING: IPv4 mapping enabled forcibly, as ext_allow_cgnat=report-private-ipv4 set; check compatibility/security notes if not set");
} else {
- INIT_PRINT_ERR("Error: option ext_ip contains reserved / private address %s, not public routable\n", use_ext_ip_addr);
+ INIT_PRINT_ERR("Option ext_ip set to private/CGNAT-reserved (%s) IPv4, exiting\n", use_ext_ip_addr);
return 1;
}
}
@@ -2229,6 +2244,25 @@ init(int argc, char * * argv, struct run
pidfilename = NULL;
#endif
+ syslog(LOG_NOTICE, "MiniUPnP daemon " MINIUPNPD_VERSION " starting, enabled protocols %s%s%s, ext_ifname=%s BOOTID=%u",
+ GETFLAG(ENABLEUPNPMASK) ? "UPnP IGD" : "",
+#ifdef ENABLE_NATPMP
+ GETFLAG(ENABLEUPNPMASK) && GETFLAG(ENABLENATPMPMASK) ? " & " : "",
+#ifdef ENABLE_PCP
+ GETFLAG(ENABLENATPMPMASK) ? "PCP/NAT-PMP" : "",
+#else
+ GETFLAG(ENABLENATPMPMASK) ? "NAT-PMP" : "",
+#endif
+#else
+ "", "",
+#endif
+ ext_if_name, upnp_bootid);
+ syslog(LOG_INFO, "More information at https://miniupnp.tuxfamily.org or http://miniupnp.free.fr");
+ syslog(LOG_NOTICE, "Extra logging with log level info (-v) or debug (-v -v)");
+
+ syslog(LOG_INFO, "Options default_min/max_port set to %d/%d apply to IPv6 and to IPv4 only, with no matching or default reject ACL entries",
+ default_min_port, default_max_port);
+
#ifdef USE_SYSTEMD
if (systemd_flag) {
int r = sd_notify(0,
@@ -2240,9 +2274,10 @@ init(int argc, char * * argv, struct run
#endif
#ifdef ENABLE_LEASEFILE
- /*remove(lease_file);*/
- syslog(LOG_INFO, "Reloading rules from lease file");
- reload_from_lease_file();
+ if (lease_file && lease_file[0] != '\0') {
+ syslog(LOG_INFO, "Reloading port maps from lease file %s", lease_file);
+ reload_from_lease_file();
+ }
#ifdef ENABLE_UPNPPINHOLE
reload_from_lease_file6();
#endif
@@ -2432,28 +2467,16 @@ main(int argc, char * * argv)
goto shutdown;
}
- syslog(LOG_INFO, "version " MINIUPNPD_VERSION " starting%s%sext if %s BOOTID=%u",
-#ifdef ENABLE_NATPMP
-#ifdef ENABLE_PCP
- GETFLAG(ENABLENATPMPMASK) ? " NAT-PMP/PCP " : " ",
-#else
- GETFLAG(ENABLENATPMPMASK) ? " NAT-PMP " : " ",
-#endif
-#else
- " ",
-#endif
- GETFLAG(ENABLEUPNPMASK) ? "UPnP-IGD " : "",
- ext_if_name, upnp_bootid);
#ifdef ENABLE_IPV6
if (strcmp(ext_if_name6, ext_if_name) != 0) {
- syslog(LOG_INFO, "specific IPv6 ext if %s", ext_if_name6);
+ syslog(LOG_INFO, "Separate ext_ifname6=%s set", ext_if_name6);
}
#endif
if(GETFLAG(PERFORMSTUNMASK))
{
- if (update_ext_ip_addr_from_stun(1) != 0) {
- syslog(LOG_ERR, "Performing STUN failed. EXITING");
+ if (update_ext_ip_addr_from_stun() != 0) {
+ syslog(LOG_ERR, "STUN: Performing test failed, exiting");
return_code = 1;
goto shutdown;
}
@@ -2461,6 +2484,8 @@ main(int argc, char * * argv)
else if (!use_ext_ip_addr)
{
update_disable_port_forwarding();
+ } else {
+ syslog(LOG_NOTICE, "IPv4 mapping enabled");
}
#ifdef DYNAMIC_OS_VERSION
@@ -2487,7 +2512,7 @@ main(int argc, char * * argv)
#ifdef ENABLE_NFQUEUE
nfqueue_data.http_port = listen_port;
#endif /* ENABLE_NFQUEUE */
- syslog(LOG_NOTICE, "HTTP listening on port %d", v.port);
+ syslog(LOG_NOTICE, "Listening for UPnP IGD (SOAP/HTTP) traffic on port %d/TCP, SSDP 1900/UDP", v.port);
#if defined(V6SOCKETS_ARE_V6ONLY) && defined(ENABLE_IPV6)
if(!GETFLAG(IPV6DISABLEDMASK))
{
@@ -2518,7 +2543,7 @@ main(int argc, char * * argv)
#ifdef ENABLE_NFQUEUE
nfqueue_data.https_port = listen_port;
#endif /* ENABLE_NFQUEUE */
- syslog(LOG_NOTICE, "HTTPS listening on port %d", v.https_port);
+ syslog(LOG_NOTICE, "Listening for UPnP IGD (SOAP/HTTPS) traffic on port %d/TCP", v.https_port);
#if defined(V6SOCKETS_ARE_V6ONLY) && defined(ENABLE_IPV6)
shttpsl_v4 = OpenAndConfHTTPSocket(&listen_port, 0);
if(shttpsl_v4 < 0)
@@ -2533,11 +2558,11 @@ main(int argc, char * * argv)
if(!GETFLAG(IPV6DISABLEDMASK)) {
if(find_ipv6_addr(lan_addrs.lh_first ? lan_addrs.lh_first->ifname : NULL,
ipv6_addr_for_http_with_brackets, sizeof(ipv6_addr_for_http_with_brackets)) > 0) {
- syslog(LOG_NOTICE, "HTTP IPv6 address given to control points : %s",
+ syslog(LOG_INFO, "Address given to UPnP IGDv2 IPv6 clients: %s",
ipv6_addr_for_http_with_brackets);
} else {
memcpy(ipv6_addr_for_http_with_brackets, "[::1]", 6);
- syslog(LOG_WARNING, "no HTTP IPv6 address, disabling IPv6");
+ syslog(LOG_DEBUG, "no HTTP IPv6 address, disabling IPv6");
SETFLAG(IPV6DISABLEDMASK);
}
}
@@ -2594,7 +2619,7 @@ main(int argc, char * * argv)
if(SendSSDPGoodbye(snotify, addr_count * 2) < 0)
#endif
{
- syslog(LOG_WARNING, "Failed to broadcast good-bye notifications");
+ syslog(LOG_DEBUG, "Failed to broadcast good-bye notifications");
}
}
#endif /* UPNP_STRICT */
@@ -2619,16 +2644,16 @@ main(int argc, char * * argv)
if(OpenAndConfNATPMPSockets(snatpmp) < 0)
#ifdef ENABLE_PCP
{
- syslog(LOG_ERR, "Failed to open sockets for NAT-PMP/PCP.");
+ syslog(LOG_ERR, "Failed to open port 5351/UDP for PCP/NAT-PMP");
} else {
- syslog(LOG_NOTICE, "Listening for NAT-PMP/PCP traffic on port %u",
+ syslog(LOG_NOTICE, "Listening for PCP/NAT-PMP traffic on port %u/UDP",
NATPMP_PORT);
}
#else
{
- syslog(LOG_ERR, "Failed to open sockets for NAT PMP.");
+ syslog(LOG_ERR, "Failed to open port 5351/UDP for NAT-PMP");
} else {
- syslog(LOG_NOTICE, "Listening for NAT-PMP traffic on port %u",
+ syslog(LOG_NOTICE, "Listening for NAT-PMP traffic on port %u/UDP",
NATPMP_PORT);
}
#endif
@@ -2739,6 +2764,30 @@ main(int argc, char * * argv)
}
#endif /* HAS_LIBCAP_NG */
+if (GETFLAG(ENABLEUPNPMASK) && !GETFLAG(SECUREMODEMASK))
+ syslog(LOG_WARNING, "WARNING: Allow adding port maps for non-requesting IP addresses via UPnP IGD, as secure_mode=no set");
+#ifdef ENABLE_PCP
+if (GETFLAG(ENABLENATPMPMASK) && GETFLAG(PCP_ALLOWTHIRDPARTYMASK))
+ syslog(LOG_WARNING, "WARNING: Allow adding port maps for non-requesting IP addresses via PCP, as pcp_allow_thirdparty=yes set");
+#endif
+#ifdef ENABLE_IPV6
+if (GETFLAG(IPV6DISABLEDMASK))
+ syslog(LOG_NOTICE, "IPv6 mapping disabled");
+#else
+syslog(LOG_NOTICE, "IPv6 mapping disabled");
+#endif
+if (GETFLAG(ENABLEUPNPMASK)) {
+#ifdef IGD_V2
+ if (GETFLAG(FORCEIGDDESCV1MASK)) {
+ syslog(LOG_NOTICE, "UPnP IGD compatibility mode set to IGDv1 (IPv4 only)");
+ } else {
+ syslog(LOG_NOTICE, "UPnP IGD compatibility mode set to IGDv2");
+ }
+#else
+ syslog(LOG_NOTICE, "UPnP IGD compatibility mode set to IGDv1 (IPv4 only)");
+#endif
+}
+
#ifdef USE_SYSTEMD
if (v.systemd_notify) {
upnp_update_status();
@@ -2768,12 +2817,13 @@ main(int argc, char * * argv)
/* send public address change notifications if needed */
if(should_send_public_address_change_notif)
{
- syslog(LOG_INFO, "should send external iface address change notification(s)");
+ syslog(LOG_NOTICE, "External network interface link/address change detected");
if(GETFLAG(PERFORMSTUNMASK))
{
- if (update_ext_ip_addr_from_stun(0) != 0) {
+ if (update_ext_ip_addr_from_stun() != 0) {
/* if stun succeed it updates disable_port_forwarding;
* if stun failed (non-zero return value) then port forwarding would not work, so disable it */
+ syslog(LOG_WARNING, "IPv4 mapping disabled");
disable_port_forwarding = 1;
}
}
@@ -3049,7 +3099,7 @@ main(int argc, char * * argv)
}
i = try_sendto(&writeset);
if(i < 0) {
- syslog(LOG_ERR, "try_sendto failed to send %d packets", -i);
+ /*syslog(LOG_DEBUG, "try_sendto failed to send %d packets", -i);*/
}
#ifdef USE_MINIUPNPDCTL
for(ectl = ctllisthead.lh_first; ectl;)
@@ -3149,7 +3199,7 @@ main(int argc, char * * argv)
if(lan_addr == NULL) {
char sender_str[64];
sockaddr_to_string((struct sockaddr *)&senderaddr, sender_str, sizeof(sender_str));
- syslog(LOG_WARNING, "NAT-PMP packet sender %s not from a LAN, ignoring",
+ syslog(LOG_DEBUG, "NAT-PMP packet sender %s not from a LAN, ignoring",
sender_str);
continue;
}
@@ -3172,7 +3222,7 @@ main(int argc, char * * argv)
if(lan_addr == NULL) {
char sender_str[64];
sockaddr_to_string((struct sockaddr *)&senderaddr, sender_str, sizeof(sender_str));
- syslog(LOG_WARNING, "NAT-PMP packet sender %s not from a LAN, ignoring",
+ syslog(LOG_DEBUG, "NAT-PMP packet sender %s not from a LAN, ignoring",
sender_str);
continue;
}
@@ -3206,7 +3256,7 @@ main(int argc, char * * argv)
/* process SSDP packets */
if(sudp >= 0 && FD_ISSET(sudp, &readset))
{
- /*syslog(LOG_INFO, "Received UDP Packet");*/
+ /*syslog(LOG_DEBUG, "Received UDP Packet");*/
#ifdef ENABLE_HTTPS
ProcessSSDPRequest(sudp, (unsigned short)v.port, (unsigned short)v.https_port);
#else
@@ -3216,7 +3266,7 @@ main(int argc, char * * argv)
#ifdef ENABLE_IPV6
if(sudpv6 >= 0 && FD_ISSET(sudpv6, &readset))
{
- syslog(LOG_INFO, "Received UDP Packet (IPv6)");
+ /*syslog(LOG_DEBUG, "Received UDP Packet (IPv6)");*/
#ifdef ENABLE_HTTPS
ProcessSSDPRequest(sudpv6, (unsigned short)v.port, (unsigned short)v.https_port);
#else
@@ -3318,7 +3368,7 @@ main(int argc, char * * argv)
shutdown:
- syslog(LOG_NOTICE, "shutting down MiniUPnPd");
+ syslog(LOG_NOTICE, "Shutting down MiniUPnPd");
#ifdef USE_SYSTEMD
if (v.systemd_notify) {
sd_notify(0,
@@ -3337,7 +3387,7 @@ shutdown:
if(SendSSDPGoodbye(snotify, addr_count * 2) < 0)
#endif
{
- syslog(LOG_ERR, "Failed to broadcast good-bye notifications");
+ syslog(LOG_DEBUG, "Failed to broadcast good-bye notifications");
}
}
/* try to send pending packets */
--- a/miniupnpd.conf
+++ b/miniupnpd.conf
@@ -3,50 +3,49 @@
# CAUTION: mixing up WAN and LAN interfaces may introduce security risks!
# Be sure to assign the correct interfaces to LAN and WAN and consider
-# implementing UPnP permission rules at the bottom of this configuration file
+# configuring access control settings at the bottom of this file
+
+##### EXTERNAL (WAN) NETWORK INTERFACE #####
-# WAN network interface
#ext_ifname=eth1
-# if the WAN network interface for IPv6 is different than for IPv4,
-# set ext_ifname6
+# If the WAN network interface for IPv6 is different than for IPv4
#ext_ifname6=eth2
-# If the WAN interface has several IP addresses, you
-# can specify the one to use below.
-# Setting ext_ip is also useful in double NAT setup, you can declare here
-# the public IP address.
+# Allow CGNAT use (default is no)
+# By default, daemon disables IPv4 mapping if a private/CGNAT-reserved external
+# IPv4 address is detected for the following reasons:
+# - Info, as port maps not reachable via internet without an unrestricted
+# endpoint-independent (1:1) IPv4 CGNAT, but possibly from within
+# - Compatibility, as many UPnP IGD & PCP/NAT-PMP clients require a returned
+# public external IPv4 address
+# - Security, to prevent access via internet if the external/internal network
+# interface has been configured swapped
+# To enable IPv4 mapping in this case, select a priority-listed option:
+# A) Detect public external IPv4 and test for unrestricted endpoint-independent
+# (1:1) CGNAT via STUN server, set ext_allow_cgnat=yes
+# B) As A, but workaround filtered CGNAT result daemon limitation (without extra
+# firewall rule), set ext_allow_cgnat=allow-filtered; check security note
+# C) Manually override reported external IPv4 with public, set ext_ip; check
+# security note
+# D) Report private/CGNAT-reserved external IPv4 to clients, set
+# ext_allow_cgnat=report-private-ipv4; check compatibility/security notes
+#ext_allow_cgnat=yes
+#ext_allow_cgnat=allow-filtered
+#ext_allow_cgnat=report-private-ipv4
+
+# Configure STUN server
+# Some CHANGE-REQUEST's capable public servers: stun.nextcloud.com,
+# stun.sipgate.net, stun.3cx.com, stun.counterpath.com, stun.miwifi.com
+ext_stun_host=stun.nextcloud.com
+#ext_stun_port=3478
+
+# Override external IPv4
+# Report custom public/external (WAN) IPv4 address to clients
+# If external interface has several IPv4 addresses, you can set which to report
#ext_ip=
-# Allow private IP address on external interface. When set to yes, program
-# won't just disable port forwarding when external address is private IP.
-# This option is disabled by default.
-#ext_allow_private_ipv4=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
-# routed to WAN interfaces without any filtering. In this cases miniupnpd
-# needs to know the public IP address and it can be learnt by asking external
-# server via STUN protocol. Following option enable retrieving external
-# public IP address from STUN server and detection of NAT type. You need
-# to specify also external STUN server in stun_host option below.
-# STUN CGNAT filter check result would be ignored when deciding whether to
-# disable port forwarding if setting this option to allow-filtered.
-# This option is disabled by default.
-#ext_perform_stun=yes
-#ext_perform_stun=allow-filtered
-
-# Specify STUN server, either hostname or IP address
-# Some public STUN servers:
-# stun.nextcloud.com
-# stun.sipgate.net
-# stun.3cx.com
-# stun.counterpath.com
-# stun.miwifi.com
-#ext_stun_host=stun.nextcloud.com
-# Specify STUN UDP port, by default it is standard port 3478.
-#ext_stun_port=3478
+##### INTERNAL (LAN) NETWORK INTERFACES #####
# LAN network interfaces IPs / networks
# There can be multiple listening IPs for SSDP traffic, in that case
@@ -64,33 +63,77 @@
#listening_ip=10.5.0.0/16
#listening_ip=eth0
+##### DAEMON CONFIGURATION #####
+
+# Enable UPNP support (default is yes)
+#enable_upnp=no
+
+# Enable NAT-PMP and PCP support (default is no)
+#enable_pcp_pmp=yes
+
+# Lease file location
+#lease_file=/var/log/upnp.leases
+
+# Report system uptime instead of daemon uptime
+system_uptime=yes
+
+# Unused rules cleaning.
+# never remove any rule before this threshold for the number
+# of redirections is exceeded. default to 20
+#clean_ruleset_threshold=10
+# Clean process work interval in seconds. default to 0 (disabled).
+# a 600 seconds (10 minutes) interval makes sense
+clean_ruleset_interval=600
+
+##### UPNP IGD CONFIGURATION #####
+
+# If compiled with IGD_V2 defined, force reporting IGDv1 in rootDesc (default
+# is no)
+#force_igd_desc_v1=no
+
+# Bitrates reported by daemon in bits per second
+# by default miniupnpd tries to get WAN interface speed
+#bitrate_up=1000000
+#bitrate_down=10000000
+
+# Daemon's serial and model number when reporting to clients
+# (in XML description)
+#serial=12345678
+#model_number=1
+
+# Default presentation URL is HTTP address on port 80
+# If set to an empty string, no presentationURL element will appear
+# in the XML description of the device, which prevents MS Windows
+# from displaying an icon in the "Network Connections" panel.
+#presentation_url=http://www.mylan/index.php
+
+# UUID, generate your own UUID with "make genuuid"
+uuid=00000000-0000-0000-0000-000000000000
+
# Port for HTTP (descriptions and SOAP) traffic. Set to 0 for autoselect.
#http_port=0
# Port for HTTPS. Set to 0 for autoselect (default)
#https_port=0
+# Notify interval in seconds. default is 900 seconds.
+# As advised in the standard, announcement have a lifetime double of this value.
+notify_interval=900
+
# Path to the UNIX socket used to communicate with MiniSSDPd
# If running, MiniSSDPd will manage M-SEARCH answering.
# default is /var/run/minissdpd.sock
#minissdpdsocket=/var/run/minissdpd.sock
-# Disable IPv6 (default is no : IPv6 enabled if enabled at build time)
-#ipv6_disable=yes
-
-# Enable NAT-PMP and PCP support (default is no)
-#enable_pcp_pmp=yes
-
-# Enable UPNP support (default is yes)
-#enable_upnp=no
+##### PCP CONFIGURATION #####
# PCP
# Configure the minimum and maximum lifetime of a port mapping in seconds
# 120s and 86400s (24h) are suggested values from PCP-base
#min_lifetime=120
#max_lifetime=86400
-# allow THIRD_PARTY Option for MAP and PEER Opcodes (default is no)
-#pcp_allow_thirdparty=yes
+
+##### LINUX NFTABLES/IPTABLES FIREWALL CONFIGURATION #####
# table names for netfilter nft. Default is "filter" for both
#upnp_table_name=
@@ -103,8 +146,27 @@
#upnp_nat_postrouting_chain=UPnP-Postrouting
#upnp_nftables_family_split=no
-# Lease file location
-#lease_file=/var/log/upnp.leases
+##### BSD'S PF FIREWALL CONFIGURATION #####
+
+# Log packets in pf (default is no)
+#packet_log=no
+
+# Anchor name in pf (default is miniupnpd)
+#anchor=miniupnpd
+
+# ALTQ queue in pf
+# Filter rules must be used for this to be used.
+# compile with PF_ENABLE_FILTER_RULES (see config.h file)
+#queue=queue_name1
+
+# Tag name in pf
+#tag=tag_name1
+
+# Make filter rules in pf quick or not. default is yes
+# active when compiled with PF_ENABLE_FILTER_RULES (see config.h file)
+#quickrules=no
+
+##### CUSTOM UPNP IGD MANUFACTURER INFORMATION #####
# To enable the next few runtime options, see compile time
# ENABLE_MANUFACTURER_INFO_CONFIGURATION (config.h)
@@ -127,83 +189,41 @@
# Model URL, default is URL of OS vendor
#model_url=https://miniupnp.tuxfamily.org/
-# Bitrates reported by daemon in bits per second
-# by default miniupnpd tries to get WAN interface speed
-#bitrate_up=1000000
-#bitrate_down=10000000
-
-# Secure Mode, UPnP clients can only add mappings to their own IP
-# Enabled by default
-#secure_mode=no
-
-# Default presentation URL is HTTP address on port 80
-# If set to an empty string, no presentationURL element will appear
-# in the XML description of the device, which prevents MS Windows
-# from displaying an icon in the "Network Connections" panel.
-#presentation_url=http://www.mylan/index.php
-
-# Report system uptime instead of daemon uptime
-system_uptime=yes
+##### ACCESS CONTROL #####
-# Notify interval in seconds. default is 900 seconds.
-# As advised in the standard, announcement have a lifetime double of this value.
-notify_interval=900
+# Default minimum/maximum port for IPv4/IPv6 port maps (default is 1)
+# Specify the default min/max accepted internal/external port. Applies with no
+# matching or default reject IPv4 ACL entries, but for all IPv6 devices, as no
+# IPv6 ACL.
+# For private use, min. of 1024 recommended; planned default in >=2.4.0 release.
+# However, for use cases where low ports (e.g. 80/443 for HTTP/HTTPS) need to be
+# made reachable via internet, it's recommended to make min. user configurable
+#default_min_port=1
+#default_max_port=65535
-# Unused rules cleaning.
-# never remove any rule before this threshold for the number
-# of redirections is exceeded. default to 20
-#clean_ruleset_threshold=10
-# Clean process work interval in seconds. default to 0 (disabled).
-# a 600 seconds (10 minutes) interval makes sense
-clean_ruleset_interval=600
-
-# Log packets in pf (default is no)
-#packet_log=no
-
-# Anchor name in pf (default is miniupnpd)
-#anchor=miniupnpd
-
-# ALTQ queue in pf
-# Filter rules must be used for this to be used.
-# compile with PF_ENABLE_FILTER_RULES (see config.h file)
-#queue=queue_name1
-
-# Tag name in pf
-#tag=tag_name1
-
-# Make filter rules in pf quick or not. default is yes
-# active when compiled with PF_ENABLE_FILTER_RULES (see config.h file)
-#quickrules=no
-
-# UUID, generate your own UUID with "make genuuid"
-uuid=00000000-0000-0000-0000-000000000000
-
-# Daemon's serial and model number when reporting to clients
-# (in XML description)
-#serial=12345678
-#model_number=1
+# Disable IPv6 mapping (default is no, available if ENABLE_IPV6 set at build)
+#ipv6_disable=yes
-# If compiled with IGD_V2 defined, force reporting IGDv1 in rootDesc (default
-# is no)
-#force_igd_desc_v1=no
+# Allow third-party mapping (use with care)
+# Allow adding port maps for non-requesting IP addresses; use with care
+# To allow this via UPnP IGD protocol, set secure_mode=no (default is yes)
+# To allow this via PCP protocol, set pcp_allow_thirdparty=yes (default is no)
+#secure_mode=no
+#pcp_allow_thirdparty=yes
-# UPnP permission rules (also enforced for NAT-PMP and PCP) for IPv4
-# (allow|deny) (external port range) IP/mask (internal port range) (optional regex filter)
-# A port range is <min port>-<max port> or <port> if there is only
-# one port in the range.
-# IP/mask format must be nnn.nnn.nnn.nnn/nn
+# Access control list (ACL) entries, for IPv4 only
+# The ACL specifies which IPv4 addresses and ports can be mapped
+# (allow/deny) (ext port/range) IP/mask (int port/range) (optional regex filter)
# Regex support must be enabled at build time : ./configure --regex
-# It is advised to only allow redirection of ports >= 1024
-# and end the rule set with "deny 0-65535 0.0.0.0/0 0-65535"
+# It is advised to end the rule set with "deny 1-65535 0.0.0.0/0 1-65535"
# The following default ruleset allows specific LAN side IP addresses
-# to request only ephemeral ports. It is recommended that users
+# to request only high ports. It is recommended that users
# modify the IP ranges to match their own internal networks, and
# also consider implementing network-specific restrictions
-# CAUTION: failure to enforce any rules may permit insecure requests to be made!
allow 1024-65535 192.168.0.0/24 1024-65535
-# disallow requests whose description string matches the given regex
-# deny 1024-65535 192.168.1.0/24 1024-65535 "My evil app ver [[:digit:]]*"
+# To disallow requests whose description string matches the given regex
+# deny 1024-65535 192.168.1.0/24 1024-65535 "My evil app ver [[:digit:]]*"
+# CAUTION: failure to enforce any rules may permit insecure requests to be made!
allow 1024-65535 192.168.1.0/24 1024-65535
-allow 1024-65535 192.168.0.0/23 22
-allow 12345 192.168.7.113/32 54321
-deny 0-65535 0.0.0.0/0 0-65535
+allow 12345 192.168.7.113 54321
+deny 1-65535 0.0.0.0/0 0-65535
--- a/natpmp.c
+++ b/natpmp.c
@@ -106,10 +106,10 @@ static void FillPublicAddressResponse(un
resp[3] = 3; /* Network Failure (e.g. NAT box itself
* has not obtained a DHCP lease) */
} else if(getifaddr(ext_if_name, tmp, INET_ADDRSTRLEN, &addr, NULL) < 0) {
- syslog(LOG_ERR, "Failed to get IP for interface %s", ext_if_name);
+ syslog(LOG_DEBUG, "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 (!GETFLAG(ALLOWPRIVATEIPV4MASK) && addr_is_reserved(&addr)) {
+ } else if (!GETFLAG(REPORTPRIVATEIPV4MASK) && addr_is_reserved(&addr)) {
resp[3] = 3; /* Network Failure, box has not obtained
public IP address */
} else {
@@ -231,7 +231,7 @@ void ProcessIncomingNATPMPPacket(int s,
syslog(LOG_ERR, "inet_ntop(natpmp): %m");
}
- syslog(LOG_INFO, "NAT-PMP request received from %s:%hu %dbytes",
+ syslog(LOG_DEBUG, "NAT-PMP request received from %s:%hu %d bytes",
senderaddrstr, ntohs(senderaddr->sin_port), n);
if(n<2 || ((((req[1]-1)&~1)==0) && n<12)) {
@@ -260,7 +260,7 @@ void ProcessIncomingNATPMPPacket(int s,
resp[3] = 1; /* unsupported version */
} else switch(req[1]) {
case 0: /* Public address request */
- syslog(LOG_INFO, "NAT-PMP public address request");
+ syslog(LOG_DEBUG, "NAT-PMP public address request");
FillPublicAddressResponse(resp, senderaddr->sin_addr.s_addr);
resplen = 12;
break;
@@ -280,10 +280,6 @@ void ProcessIncomingNATPMPPacket(int s,
eport = READNU16(req+6);
lifetime = READNU32(req+8);
proto = (req[1]==1)?IPPROTO_UDP:IPPROTO_TCP;
- syslog(LOG_INFO, "NAT-PMP port mapping request : "
- "%hu->%s:%hu %s lifetime=%us",
- eport, senderaddrstr, iport,
- (req[1]==1)?"udp":"tcp", lifetime);
/* TODO: accept port mapping if iport ok but eport not ok
* (and set eport correctly) */
if(lifetime == 0) {
@@ -319,8 +315,8 @@ void ProcessIncomingNATPMPPacket(int s,
resp[3] = 2; /* Not Authorized/Refused */
break;
} else {
- syslog(LOG_INFO, "NAT-PMP %s port %hu mapping removed",
- proto2==IPPROTO_TCP?"TCP":"UDP", eport2);
+ syslog(LOG_INFO, "Delete IPv4 port map %hu:%s:%hu/%s via NAT-PMP",
+ eport2, senderaddrstr, iport, proto2 == IPPROTO_TCP ? "TCP" : "UDP");
index--;
}
}
@@ -340,8 +336,8 @@ void ProcessIncomingNATPMPPacket(int s,
eport_first = eport;
} else if(eport == eport_first) { /* no eport available */
if(any_eport_allowed == 0) { /* all eports rejected by permissions */
- syslog(LOG_ERR, "No allowed eport for NAT-PMP %hu %s->%s:%hu",
- eport, proto_itoa(proto), senderaddrstr, iport);
+ syslog(LOG_INFO, "Reject IPv4 port map %hu:%s:%hu/%s via NAT-PMP reason ACL/default-min/max-port",
+ eport, senderaddrstr, iport, proto_itoa(proto));
resp[3] = 2; /* Not Authorized/Refused */
} else { /* at least one eport allowed (but none available) */
syslog(LOG_ERR, "Failed to find available eport for NAT-PMP %hu %s->%s:%hu",
@@ -358,7 +354,7 @@ void ProcessIncomingNATPMPPacket(int s,
any_eport_allowed = 1; /* at lease one eport is allowed */
#ifdef CHECK_PORTINUSE
if (port_in_use(ext_if_name, eport, proto, senderaddrstr, iport) > 0) {
- syslog(LOG_INFO, "port %hu protocol %s already in use",
+ syslog(LOG_INFO, "Reject IPv4 port map %hu:?:?/%s via NAT-PMP reason port in use",
eport, proto_itoa(proto));
eport++;
if(eport == 0) eport++; /* skip port zero */
@@ -373,8 +369,8 @@ void ProcessIncomingNATPMPPacket(int s,
if(strcmp(senderaddrstr, iaddr_old)==0
&& iport==iport_old) {
/* redirection already existing */
- syslog(LOG_INFO, "port %hu %s already redirected to %s:%hu, replacing",
- eport, (proto==IPPROTO_TCP)?"tcp":"udp", iaddr_old, iport_old);
+ syslog(LOG_INFO, "Renew IPv4 port map %hu:%s:%hu/%s lifetime %u via NAT-PMP",
+ eport, senderaddrstr, iport, proto_itoa(proto), lifetime);
/* remove and then add again */
if(_upnp_delete_redir(eport, proto) < 0) {
syslog(LOG_ERR, "failed to remove port mapping");
@@ -394,13 +390,17 @@ void ProcessIncomingNATPMPPacket(int s,
if(upnp_redirect_internal(NULL, eport, senderaddrstr,
iport, proto, desc,
timestamp) < 0) {
- syslog(LOG_ERR, "Failed to add NAT-PMP %hu %s->%s:%hu '%s'",
+ syslog(LOG_DEBUG, "Failed to add NAT-PMP %hu %s->%s:%hu '%s'",
eport, proto_itoa(proto), senderaddrstr, iport, desc);
resp[3] = 3; /* Failure */
}
break;
}
}
+ if (resp[3] == 0 && lifetime) {
+ syslog(LOG_INFO, "Add IPv4 port map %hu:%s:%hu/%s lifetime %u via NAT-PMP",
+ eport, senderaddrstr, iport, req[1] == 1 ? "UDP" : "TCP", lifetime);
+ }
WRITENU16(resp+8, iport); /* private port */
WRITENU16(resp+10, eport); /* public port */
WRITENU32(resp+12, lifetime); /* Port Mapping lifetime */
@@ -410,6 +410,7 @@ void ProcessIncomingNATPMPPacket(int s,
default:
resp[3] = 5; /* Unsupported OPCODE */
}
+
n = sendto_or_schedule(s, resp, resplen, 0,
(struct sockaddr *)senderaddr, sizeof(*senderaddr));
if(n<0) {
@@ -443,7 +444,7 @@ void SendNATPMPPublicAddressChangeNotifi
FillPublicAddressResponse(notif, 0);
if(notif[3])
{
- syslog(LOG_WARNING, "%s: cannot get public IP address, stopping",
+ syslog(LOG_DEBUG, "%s: cannot get public IP address, stopping",
"SendNATPMPPublicAddressChangeNotification");
return;
}
@@ -471,7 +472,7 @@ void SendNATPMPPublicAddressChangeNotifi
(struct sockaddr *)&sockname, sizeof(struct sockaddr_in));
if(n < 0)
{
- syslog(LOG_ERR, "%s: sendto(s_udp=%d, port=%d): %m",
+ syslog(LOG_DEBUG, "%s: sendto(s_udp=%d, port=%d): %m",
"SendNATPMPPublicAddressChangeNotification", sockets[j], NATPMP_PORT);
return;
}
@@ -481,7 +482,7 @@ void SendNATPMPPublicAddressChangeNotifi
(struct sockaddr *)&sockname, sizeof(struct sockaddr_in));
if(n < 0)
{
- syslog(LOG_ERR, "%s: sendto(s_udp=%d, port=%d): %m",
+ syslog(LOG_DEBUG, "%s: sendto(s_udp=%d, port=%d): %m",
"SendNATPMPPublicAddressChangeNotification", sockets[j], NATPMP_NOTIF_PORT);
return;
}
--- a/netfilter/iptcrdr.c
+++ b/netfilter/iptcrdr.c
@@ -715,7 +715,7 @@ delete_filter_rule(const char * ifname,
continue;
}
index = i;
- /*syslog(LOG_INFO, "Trying to delete filter rule at index %u", index);*/
+ /*syslog(LOG_DEBUG, "Trying to delete filter rule at index %u", index);*/
r = delete_rule_and_commit(index, h, miniupnpd_forward_chain, "delete_filter_rule");
h = NULL;
break;
@@ -808,7 +808,7 @@ delete_redirect_and_filter_rules(unsigne
#endif
if(r == 0)
{
- syslog(LOG_INFO, "Trying to delete nat rule at index %u", index);
+ syslog(LOG_DEBUG, "Trying to delete nat rule at index %u", index);
/* Now delete both rules */
/* first delete the nat rule */
h = iptc_init("nat");
@@ -852,7 +852,7 @@ delete_redirect_and_filter_rules(unsigne
if(iaddr != e->ip.dst.s_addr)
continue;
index = i;
- syslog(LOG_INFO, "Trying to delete filter rule at index %u", index);
+ syslog(LOG_DEBUG, "Trying to delete filter rule at index %u", index);
r = delete_rule_and_commit(index, h, miniupnpd_forward_chain, "delete_filter_rule");
h = NULL;
break;
@@ -867,6 +867,9 @@ delete_redirect_and_filter_rules(unsigne
iptc_free(&h);
#endif
}
+ } else {
+ syslog(LOG_INFO, "Non-existing IPv4 port map to delete %hu:?:?/%s via UPnP IGD",
+ eport, proto == IPPROTO_TCP ? "TCP" : "UDP");
}
/*delete PEER rule*/
@@ -910,7 +913,7 @@ delete_redirect_and_filter_rules(unsigne
}
index = i;
- syslog(LOG_INFO, "Trying to delete peer rule at index %u", index);
+ syslog(LOG_DEBUG, "Trying to delete peer rule at index %u", index);
r2 = delete_rule_and_commit(index, h, miniupnpd_nat_postrouting_chain, "delete_peer_rule");
h = NULL;
break;
@@ -962,7 +965,7 @@ delete_redirect_and_filter_rules(unsigne
if(iaddr != e->ip.src.s_addr)
continue;
index = i;
- syslog(LOG_INFO, "Trying to delete dscp rule at index %u", index);
+ syslog(LOG_DEBUG, "Trying to delete dscp rule at index %u", index);
r2 = delete_rule_and_commit(index, h, miniupnpd_nat_chain, "delete_dscp_rule");
h = NULL;
break;
--- a/netfilter/iptpinhole.c
+++ b/netfilter/iptpinhole.c
@@ -232,13 +232,13 @@ int add_pinhole(const char * ifname,
strncpy(e->ipv6.iniface, ifname, IFNAMSIZ);
if(rem_host && (rem_host[0] != '\0')) {
if(inet_pton(AF_INET6, rem_host, &e->ipv6.src) < 1) {
- syslog(LOG_WARNING, "failed to parse INET6 address \"%s\"", rem_host);
+ syslog(LOG_DEBUG, "Failed to parse remote IPv6 address (%s)", rem_host);
} else {
memset(&e->ipv6.smsk, 0xff, sizeof(e->ipv6.smsk));
}
}
if (inet_pton(AF_INET6, int_client, &e->ipv6.dst) < 1) {
- syslog(LOG_WARNING, "failed to parse INET6 address \"%s\"", int_client);
+ syslog(LOG_DEBUG, "Failed to parse IPv6 address (%s)", int_client);
} else {
memset(&e->ipv6.dmsk, 0xff, sizeof(e->ipv6.dmsk));
}
@@ -295,14 +295,14 @@ find_pinhole(const char * ifname,
if(rem_host && (rem_host[0] != '\0')) {
if (inet_pton(AF_INET6, rem_host, &saddr) < 1) {
- syslog(LOG_WARNING, "Failed to parse INET6 address \"%s\"", rem_host);
+ syslog(LOG_DEBUG, "Failed to parse remote IPv6 address (%s)", rem_host);
memset(&saddr, 0, sizeof(struct in6_addr));
}
} else {
memset(&saddr, 0, sizeof(struct in6_addr));
}
if (inet_pton(AF_INET6, int_client, &daddr) < 1) {
- syslog(LOG_WARNING, "Failed to parse INET6 address \"%s\"", int_client);
+ syslog(LOG_DEBUG, "Failed to parse IPv6 address (%s)", int_client);
memset(&daddr, 0, sizeof(struct in6_addr));
}
for(p = pinhole_list.lh_first; p != NULL; p = p->entries.le_next) {
@@ -483,7 +483,7 @@ clean_pinhole_list(unsigned int * next_t
while(p != NULL) {
if(p->timestamp <= (unsigned int)current_time) {
unsigned short uid = p->uid;
- syslog(LOG_INFO, "removing expired pinhole with uid=%hu", uid);
+ syslog(LOG_INFO, "Expire IPv6 port map [?]:?/?");
p = p->entries.le_next;
if(delete_pinhole(uid) == 0)
n++;
--- a/netfilter_nft/nftnlrdr.c
+++ b/netfilter_nft/nftnlrdr.c
@@ -353,8 +353,8 @@ delete_redirect_and_filter_rules(unsigne
}
}
} else {
- syslog(LOG_WARNING, "%s: redirect rule with eport=%hu proto %d NOT FOUND",
- "delete_redirect_and_filter_rules", eport, proto);
+ syslog(LOG_INFO, "Non-existing IPv4 port map to delete %hu:?:?/%s via UPnP IGD",
+ eport, proto == IPPROTO_TCP ? "TCP" : "UDP");
}
iaddr = 0;
--- a/netfilter_nft/nftnlrdr_misc.c
+++ b/netfilter_nft/nftnlrdr_misc.c
@@ -110,7 +110,7 @@ nft_mnl_connect(void)
return -1;
}
mnl_portid = mnl_socket_get_portid(mnl_sock);
- syslog(LOG_INFO, "mnl_socket bound, port_id=%u", mnl_portid);
+ syslog(LOG_DEBUG, "mnl_socket bound, port_id=%u", mnl_portid);
return 0;
}
@@ -755,7 +755,7 @@ refresh_nft_cache(struct rule_list *head
errno = 0;
ret = mnl_cb_run(buf, n, mnl_seq, mnl_portid, table_cb, &data);
if (ret <= -1 /*== MNL_CB_ERROR*/) {
- syslog(LOG_ERR, "%s: mnl_cb_run returned %d: %m",
+ syslog(LOG_DEBUG, "%s: mnl_cb_run returned %d: %m",
"refresh_nft_cache", ret);
return -1;
}
@@ -1331,7 +1331,7 @@ nft_send_rule(struct nftnl_rule * rule,
result = send_batch(batch);
if (result < 0) {
- syslog(LOG_ERR, "%s(%p, %d, %d) send_batch failed %d",
+ syslog(LOG_DEBUG, "%s(%p, %d, %d) send_batch failed %d",
"nft_send_rule", rule, (int)cmd, (int)chain_type, result);
}
}
@@ -1517,7 +1517,7 @@ send_batch(struct mnl_nlmsg_batch *batch
errno = 0;
ret = mnl_cb_run(buf, n, 0, mnl_portid, NULL, NULL);
if (ret <= -1 /*== MNL_CB_ERROR*/) {
- syslog(LOG_ERR, "%s: mnl_cb_run returned %d: %m",
+ syslog(LOG_DEBUG, "%s: mnl_cb_run returned %d: %m",
"send_batch", ret);
return -4;
}
--- a/netfilter_nft/nftpinhole.c
+++ b/netfilter_nft/nftpinhole.c
@@ -90,12 +90,12 @@ int add_pinhole(const char * ifname,
if (inet_pton(AF_INET6, rem_host, &rhost_addr) == 1) {
rhost_addr_p = &rhost_addr;
} else {
- syslog(LOG_WARNING, "Failed to parse INET6 address \"%s\"", rem_host);
+ syslog(LOG_DEBUG, "Failed to parse remote IPv6 address (%s)", rem_host);
}
}
if (inet_pton(AF_INET6, int_client, &ihost_addr) != 1) {
- syslog(LOG_WARNING, "Failed to parse INET6 address \"%s\"", int_client);
+ syslog(LOG_DEBUG, "Failed to parse IPv6 address (%s)", int_client);
}
snprintf(comment, NFT_DESCR_SIZE,
@@ -133,7 +133,7 @@ find_pinhole(const char * ifname,
if (rem_host && rem_host[0] != '\0' && rem_host[0] != '*') {
if (inet_pton(AF_INET6, rem_host, &saddr) < 1) {
- syslog(LOG_WARNING, "Failed to parse INET6 address \"%s\"", rem_host);
+ syslog(LOG_DEBUG, "Failed to parse remote IPv6 address (%s)", rem_host);
memset(&saddr, 0, sizeof(struct in6_addr));
}
} else {
@@ -141,7 +141,7 @@ find_pinhole(const char * ifname,
}
if (inet_pton(AF_INET6, int_client, &daddr) < 1) {
- syslog(LOG_WARNING, "Failed to parse INET6 address \"%s\"", int_client);
+ syslog(LOG_DEBUG, "Failed to parse IPv6 address (%s)", int_client);
memset(&daddr, 0, sizeof(struct in6_addr));
}
@@ -163,7 +163,7 @@ find_pinhole(const char * ifname,
(0 == memcmp(&daddr, &p->daddr6, sizeof(struct in6_addr)))) {
if (sscanf(p->desc, PINEHOLE_LABEL_FORMAT_SKIPDESC, &uid, &ts) != 2) {
- syslog(LOG_DEBUG, "rule with label '%s' is not a IGD pinhole", p->desc);
+ /*syslog(LOG_DEBUG, "rule with label '%s' is not a IGD pinhole", p->desc);*/
continue;
}
@@ -400,7 +400,7 @@ get_pinhole_info(unsigned short uid,
if (timestamp) {
int uid_temp;
if (sscanf(p->desc, PINEHOLE_LABEL_FORMAT_SKIPDESC, &uid_temp, &ts) != 2) {
- syslog(LOG_DEBUG, "rule with label '%s' is not a IGD pinhole", p->desc);
+ /*syslog(LOG_DEBUG, "rule with label '%s' is not a IGD pinhole", p->desc);*/
continue;
}
@@ -464,12 +464,12 @@ clean_pinhole_list(unsigned int * next_t
continue;
if (sscanf(p->desc, PINEHOLE_LABEL_FORMAT_SKIPDESC, &uid, &ts) != 2) {
- syslog(LOG_DEBUG, "rule with label '%s' is not a IGD pinhole", p->desc);
+ /*syslog(LOG_DEBUG, "rule with label '%s' is not a IGD pinhole", p->desc);*/
continue;
}
if (ts <= (unsigned int)current_time) {
- syslog(LOG_INFO, "removing expired pinhole '%s'", p->desc);
+ syslog(LOG_INFO, "Expire IPv6 port map [?]:?/?");
r = rule_del_handle(p);
nft_send_rule(r, NFT_MSG_DELRULE, RULE_CHAIN_FILTER);
n++;
--- a/options.c
+++ b/options.c
@@ -35,8 +35,9 @@ static const struct {
{ UPNPEXT_IFNAME6, "ext_ifname6" },
#endif
{ UPNPEXT_IP, "ext_ip" },
- { UPNPEXT_ALLOW_PRIVATE_IPV4, "ext_allow_private_ipv4" },
- { UPNPEXT_PERFORM_STUN, "ext_perform_stun" },
+ { UPNPEXT_ALLOW_CGNAT, "ext_allow_cgnat" },
+ { UPNPEXT_ALLOW_CGNAT, "ext_perform_stun" },
+ { UPNPEXT_REPORT_PRIVATE_IPV4, "ext_allow_private_ipv4" },
{ UPNPEXT_STUN_HOST, "ext_stun_host" },
{ UPNPEXT_STUN_PORT, "ext_stun_port" },
{ UPNPLISTENING_IP, "listening_ip" },
@@ -44,6 +45,8 @@ static const struct {
{ UPNPIPV6_LISTENING_IP, "ipv6_listening_ip" },
{ UPNPIPV6_DISABLE, "ipv6_disable" },
#endif /* ENABLE_IPV6 */
+ { DEFAULT_MIN_PORT, "default_min_port" },
+ { DEFAULT_MAX_PORT, "default_max_port" },
{ UPNPPORT, "port" },
{ UPNPPORT, "http_port" }, /* "port" and "http_port" are synonims */
#ifdef ENABLE_HTTPS
--- a/options.h
+++ b/options.h
@@ -25,8 +25,8 @@ enum upnpconfigoptions {
UPNPEXT_IFNAME6, /*!< ext_ifname6 */
#endif
UPNPEXT_IP, /*!< ext_ip */
- UPNPEXT_ALLOW_PRIVATE_IPV4, /*!< ext_allow_private_ipv4 */
- UPNPEXT_PERFORM_STUN, /*!< ext_perform_stun */
+ UPNPEXT_ALLOW_CGNAT, /*!< ext_allow_cgnat */
+ UPNPEXT_REPORT_PRIVATE_IPV4, /*!< old ext_allow_private_ipv4 */
UPNPEXT_STUN_HOST, /*!< ext_stun_host */
UPNPEXT_STUN_PORT, /*!< ext_stun_port */
UPNPLISTENING_IP, /*!< listening_ip */
@@ -34,6 +34,8 @@ enum upnpconfigoptions {
UPNPIPV6_LISTENING_IP, /*!< listening address for IPv6 */
UPNPIPV6_DISABLE, /*!< ipv6_disable */
#endif /* ENABLE_IPV6 */
+ DEFAULT_MIN_PORT, /*!< default_min_port */
+ DEFAULT_MAX_PORT, /*!< default_max_port */
UPNPPORT, /*!< "port" / "http_port" */
#ifdef ENABLE_HTTPS
UPNPHTTPSPORT, /*!< "https_port" */
--- a/pcpserver.c
+++ b/pcpserver.c
@@ -631,7 +631,7 @@ static int CheckExternalAddress(pcp_info
}
if (!IN6_ARE_ADDR_EQUAL(pcp_msg_info->ext_ip, &external_addr)) {
- syslog(LOG_ERR,
+ syslog(LOG_DEBUG,
"PCP: External IP in request didn't match interface IP \n");
#ifdef DEBUG
{
@@ -943,7 +943,7 @@ static int CreatePCPMap_NAT(pcp_info_t *
((struct in_addr*)pcp_msg_info->mapped_ip->s6_addr)[3],
pcp_msg_info->int_port, pcp_msg_info->desc)))) {
if (pcp_msg_info->pfailure_present) {
- return PCP_ERR_CANNOT_PROVIDE_EXTERNAL;
+ return PCP_ERR_NOT_AUTHORIZED;
}
pcp_msg_info->ext_port++;
if (pcp_msg_info->ext_port == 0) { /* skip port zero */
@@ -955,7 +955,7 @@ static int CreatePCPMap_NAT(pcp_info_t *
#ifdef CHECK_PORTINUSE
if (port_in_use(ext_if_name, pcp_msg_info->ext_port, pcp_msg_info->protocol,
pcp_msg_info->mapped_str, pcp_msg_info->int_port) > 0) {
- syslog(LOG_INFO, "port %hu protocol %s already in use",
+ syslog(LOG_INFO, "Reject IPv4 port map %hu:?:?/%s via PCP reason port in use",
pcp_msg_info->ext_port,
proto_itoa(pcp_msg_info->protocol));
pcp_msg_info->ext_port++;
@@ -980,9 +980,9 @@ static int CreatePCPMap_NAT(pcp_info_t *
return PCP_ERR_CANNOT_PROVIDE_EXTERNAL;
}
} else {
- syslog(LOG_INFO, "port %hu %s already redirected to %s:%hu, replacing",
- pcp_msg_info->ext_port, proto_itoa(pcp_msg_info->protocol),
- iaddr_old, iport_old);
+ syslog(LOG_INFO, "Renew IPv4 port map %hu:%s:%hu/%s lifetime %d via PCP",
+ pcp_msg_info->ext_port, iaddr_old, iport_old,
+ proto_itoa(pcp_msg_info->protocol), pcp_msg_info->lifetime);
/* remove and then add again */
if (_upnp_delete_redir(pcp_msg_info->ext_port,
pcp_msg_info->protocol)==0) {
@@ -1016,6 +1016,14 @@ static int CreatePCPMap_FW(pcp_info_t *p
int uid;
int r;
char desc[64];
+
+ if (!IN6_IS_ADDR_V4MAPPED(pcp_msg_info->mapped_ip) &&
+ (pcp_msg_info->int_port < default_min_port || pcp_msg_info->int_port > default_max_port)) {
+ syslog(LOG_INFO, "Reject IPv6 port map [%s]:%hu/%s via PCP reason default-min/max-port",
+ pcp_msg_info->mapped_str, pcp_msg_info->int_port, proto_itoa(pcp_msg_info->protocol));
+ return PCP_ERR_NOT_AUTHORIZED;
+ }
+
/* first check if pinhole already exists */
uid = upnp_find_inboundpinhole(NULL, 0,
pcp_msg_info->mapped_str,
@@ -1027,13 +1035,14 @@ static int CreatePCPMap_FW(pcp_info_t *p
/* pinhole already exists, updating */
if (0 != strcmp(desc, pcp_msg_info->desc)) {
/* nonce does not match */
- syslog(LOG_ERR, "Unauthorized to update pinhole : \"%s\" != \"%s\"",
- desc, pcp_msg_info->desc);
+ syslog(LOG_INFO, "Reject IPv6 port map [%s]:%hu/%s via PCP nonce %s reason nonce not matching",
+ pcp_msg_info->mapped_str, pcp_msg_info->int_port,
+ proto_itoa(pcp_msg_info->protocol), pcp_msg_info->desc + 8);
return PCP_ERR_NOT_AUTHORIZED;
}
- syslog(LOG_INFO, "updating pinhole %d to %s:%hu %s",
- uid, pcp_msg_info->mapped_str, pcp_msg_info->int_port,
- proto_itoa(pcp_msg_info->protocol));
+ syslog(LOG_INFO, "Renew IPv6 port map [%s]:%hu/%s lifetime %d via PCP",
+ pcp_msg_info->mapped_str, pcp_msg_info->int_port,
+ proto_itoa(pcp_msg_info->protocol), pcp_msg_info->lifetime);
r = upnp_update_inboundpinhole((unsigned short)uid, pcp_msg_info->lifetime);
return r >= 0 ? PCP_SUCCESS : PCP_ERR_NO_RESOURCES;
} else {
@@ -1089,19 +1098,25 @@ static void CreatePCPMap(pcp_info_t *pcp
{
int r;
- if (pcp_msg_info->is_fw)
+ if (pcp_msg_info->is_fw) {
r = CreatePCPMap_FW(pcp_msg_info);
- else
+ syslog(LOG_INFO,
+ "%s IPv6 port map [%s]:%hu/%s remote IP ?/? remote port ? lifetime %d via PCP nonce %s %s",
+ r == PCP_SUCCESS ? "Add" : "Reject",
+ pcp_msg_info->mapped_str, pcp_msg_info->int_port,
+ proto_itoa(pcp_msg_info->protocol), pcp_msg_info->lifetime,
+ pcp_msg_info->desc + 8, r == PCP_ERR_NOT_AUTHORIZED ? "reason default-min/max-port" : "");
+ } else {
r = CreatePCPMap_NAT(pcp_msg_info);
+ syslog(LOG_INFO,
+ "%s IPv4 port map %hu:%s:%hu/%s remote IP ?/? remote port ? lifetime %d via PCP nonce %s %s",
+ r == PCP_SUCCESS ? "Add" : "Reject",
+ pcp_msg_info->ext_port,
+ pcp_msg_info->mapped_str, pcp_msg_info->int_port,
+ proto_itoa(pcp_msg_info->protocol), pcp_msg_info->lifetime,
+ pcp_msg_info->desc + 8, r == PCP_ERR_NOT_AUTHORIZED ? "reason ACL/default-min/max-port" : "");
+ }
pcp_msg_info->result_code = r;
- syslog(r == PCP_SUCCESS ? LOG_INFO : LOG_ERR,
- "PCP MAP: %s mapping %s %hu->%s:%hu '%s'",
- r == PCP_SUCCESS ? "added" : "failed to add",
- proto_itoa(pcp_msg_info->protocol),
- pcp_msg_info->ext_port,
- pcp_msg_info->mapped_str,
- pcp_msg_info->int_port,
- pcp_msg_info->desc);
}
static void DeletePCPMap(pcp_info_t *pcp_msg_info)
@@ -1136,8 +1151,8 @@ static void DeletePCPMap(pcp_info_t *pcp
if(0 != strcmp(desc, pcp_msg_info->desc)) {
/* nonce does not match */
pcp_msg_info->result_code = PCP_ERR_NOT_AUTHORIZED;
- syslog(LOG_ERR, "Unauthorized to remove PCP mapping internal port %hu, protocol %s",
- iport, proto_itoa(pcp_msg_info->protocol));
+ syslog(LOG_INFO, "Reject IPv6 port map [?]:%hu/%s via PCP nonce %s reason nonce not matching",
+ iport, proto_itoa(pcp_msg_info->protocol), pcp_msg_info->desc + 8);
return;
} else {
r = _upnp_delete_redir(eport2, proto2);
@@ -1154,15 +1169,15 @@ static void DeletePCPMap(pcp_info_t *pcp
desc, sizeof(desc),
NULL /* lifetime */);
if (uid < 0) {
- syslog(LOG_ERR, "Failed to find mapping to %s:%hu, protocol %s",
- pcp_msg_info->mapped_str, iport, proto_itoa(pcp_msg_info->protocol));
+ syslog(LOG_INFO, "Non-existing IPv6 port map to delete [%s]:%hu/%s via PCP nonce %s",
+ pcp_msg_info->mapped_str, iport, proto_itoa(pcp_msg_info->protocol), pcp_msg_info->desc + 8);
return;
} else {
if(0 != strcmp(desc, pcp_msg_info->desc)) {
/* nonce does not match */
pcp_msg_info->result_code = PCP_ERR_NOT_AUTHORIZED;
- syslog(LOG_ERR, "Unauthorized to remove PCP mapping internal port %hu, protocol %s",
- iport, proto_itoa(pcp_msg_info->protocol));
+ syslog(LOG_INFO, "Reject IPv6 port map [?]:%hu/%s via PCP nonce %s reason nonce not matching",
+ iport, proto_itoa(pcp_msg_info->protocol), pcp_msg_info->desc + 8);
return;
} else {
r = upnp_delete_inboundpinhole(uid);
@@ -1173,11 +1188,21 @@ static void DeletePCPMap(pcp_info_t *pcp
#endif /* ENABLE_UPNPPINHOLE */
}
if (r >= 0) {
- syslog(LOG_INFO, "PCP: %s port %hu mapping removed",
- proto==IPPROTO_TCP?"TCP":"UDP", (pcp_msg_info->is_fw ? iport : eport2));
+ if (!pcp_msg_info->is_fw) {
+ syslog(LOG_INFO, "Delete IPv4 port map %hu:%s:%hu/%s via PCP nonce %s",
+ iport, pcp_msg_info->mapped_str, iport, proto_itoa(proto), pcp_msg_info->desc + 8);
+ } else {
+ syslog(LOG_INFO, "Delete IPv6 port map [%s]:%hu/%s via PCP nonce %s",
+ pcp_msg_info->mapped_str, iport, proto_itoa(proto), pcp_msg_info->desc + 8);
+ }
} else {
- syslog(LOG_ERR, "Failed to remove PCP mapping to %s:%hu %s",
- pcp_msg_info->mapped_str, iport, proto_itoa(proto));
+ if (!pcp_msg_info->is_fw) {
+ syslog(LOG_INFO, "Non-existing IPv4 port map to delete ?:%s:%hu/%s via PCP nonce %s",
+ pcp_msg_info->mapped_str, iport, proto_itoa(proto), pcp_msg_info->desc + 8);
+ } else {
+ syslog(LOG_INFO, "Non-existing IPv6 port map to delete %s:%hu/%s via PCP nonce %s",
+ pcp_msg_info->mapped_str, iport, proto_itoa(proto), pcp_msg_info->desc + 8);
+ }
pcp_msg_info->result_code = PCP_ERR_NO_RESOURCES;
}
}
@@ -1199,6 +1224,7 @@ static int ValidatePCPMsg(pcp_info_t *pc
if (pcp_msg_info->thirdp_ip) {
if (!GETFLAG(PCP_ALLOWTHIRDPARTYMASK)) {
+ syslog(LOG_INFO, "Reject IPv? port map ?:?:?/? via PCP reason for third-party from ?");
pcp_msg_info->result_code = PCP_ERR_UNSUPP_OPTION;
return 0;
}
@@ -1253,8 +1279,8 @@ static int ValidatePCPMsg(pcp_info_t *pc
snprintf(pcp_msg_info->desc, sizeof(pcp_msg_info->desc),
"PCP %s %08x%08x%08x",
getPCPOpCodeStr(pcp_msg_info->opcode),
- pcp_msg_info->nonce[0],
- pcp_msg_info->nonce[1], pcp_msg_info->nonce[2]);
+ ntohl(pcp_msg_info->nonce[0]),
+ ntohl(pcp_msg_info->nonce[1]), ntohl(pcp_msg_info->nonce[2]));
break;
}
return 1;
@@ -1399,7 +1425,7 @@ static int processPCPRequest(void * req,
CreatePCPMap(pcp_msg_info);
}
} else {
- syslog(LOG_ERR, "PCP: Invalid PCP v2 MAP message.");
+ syslog(LOG_DEBUG, "PCP: Invalid PCP v2 MAP message.");
return pcp_msg_info->result_code;
}
@@ -1609,7 +1635,7 @@ int ProcessIncomingPCPPacket(int s, unsi
if (!GETFLAG(PCP_ALLOWTHIRDPARTYMASK)) {
lan_addr = get_lan_for_peer(senderaddr);
if(lan_addr == NULL) {
- syslog(LOG_WARNING, "PCP packet sender %s not from a LAN, ignoring",
+ syslog(LOG_DEBUG, "PCP packet sender %s not from a LAN, ignoring",
addr_str);
return 0;
}
@@ -1730,7 +1756,7 @@ void PCPSendUnsolicitedAnnounce(int * so
}
len = sendto_or_schedule(sockets[i], buff, PCP_MIN_LEN, 0, (struct sockaddr *)&addr, sizeof(struct sockaddr_in));
if( len < 0 ) {
- syslog(LOG_ERR, "PCPSendUnsolicitedAnnounce(sockets[%d]) sendto(): %m", i);
+ syslog(LOG_DEBUG, "PCPSendUnsolicitedAnnounce(sockets[%d]) sendto(): %m", i);
}
}
#ifdef ENABLE_IPV6
@@ -1741,7 +1767,7 @@ void PCPSendUnsolicitedAnnounce(int * so
addr6.sin6_port = htons(5350);
len = sendto_or_schedule(socket6, buff, PCP_MIN_LEN, 0, (struct sockaddr *)&addr6, sizeof(struct sockaddr_in6));
if( len < 0 ) {
- syslog(LOG_ERR, "PCPSendUnsolicitedAnnounce() IPv6 sendto(): %m");
+ syslog(LOG_DEBUG, "PCPSendUnsolicitedAnnounce() IPv6 sendto(): %m");
}
}
#endif /* ENABLE_IPV6 */
--- a/pf/obsdrdr.c
+++ b/pf/obsdrdr.c
@@ -1302,7 +1302,7 @@ priv_delete_redirect_rule_check_desc(con
}
}
if (r == -2)
- syslog(LOG_NOTICE, "could not find redirect rule to delete eport=%hu", eport);
+ syslog(LOG_DEBUG, "could not find redirect rule to delete eport=%hu", eport);
release_ticket(dev, tnum);
return r;
}
--- a/pf/pfpinhole.c
+++ b/pf/pfpinhole.c
@@ -246,12 +246,12 @@ int find_pinhole(const char * ifname,
(0 == memcmp(&daddr, &RULE.dst.addr.v.a.addr.v6, sizeof(struct in6_addr)))) {
#ifdef USE_LIBPFCTL
if(sscanf(RULE.label[0], PINEHOLE_LABEL_FORMAT_SKIPDESC, &uid, &ts) != 2) {
- syslog(LOG_DEBUG, "rule with label '%s' is not a IGD pinhole", RULE.label[0]);
+ /*syslog(LOG_DEBUG, "rule with label '%s' is not a IGD pinhole", RULE.label[0]);*/
continue;
}
#else /* USE_LIBPFCTL */
if(sscanf(RULE.label, PINEHOLE_LABEL_FORMAT_SKIPDESC, &uid, &ts) != 2) {
- syslog(LOG_DEBUG, "rule with label '%s' is not a IGD pinhole", RULE.label);
+ /*syslog(LOG_DEBUG, "rule with label '%s' is not a IGD pinhole", RULE.label);*/
continue;
}
#endif /* USE_LIBPFCTL */
@@ -565,7 +565,7 @@ int clean_pinhole_list(unsigned int * ne
return -1;
}
if(sscanf(RULE.label[0], PINEHOLE_LABEL_FORMAT_SKIPDESC, &uid, &ts) != 2) {
- syslog(LOG_DEBUG, "rule with label '%s' is not a IGD pinhole", RULE.label[0]);
+ /*syslog(LOG_DEBUG, "rule with label '%s' is not a IGD pinhole", RULE.label[0]);*/
continue;
}
#else /* USE_LIBPFCTL */
@@ -576,7 +576,7 @@ int clean_pinhole_list(unsigned int * ne
return -1;
}
if(sscanf(RULE.label, PINEHOLE_LABEL_FORMAT_SKIPDESC, &uid, &ts) != 2) {
- syslog(LOG_DEBUG, "rule with label '%s' is not a IGD pinhole", RULE.label);
+ /*syslog(LOG_DEBUG, "rule with label '%s' is not a IGD pinhole", RULE.label);*/
continue;
}
#endif /* USE_LIBPFCTL */
@@ -589,9 +589,9 @@ int clean_pinhole_list(unsigned int * ne
pr.ticket = ri.ticket;
pr.nr = i;
strlcpy(pr.anchor, anchor_name, MAXPATHLEN);
- syslog(LOG_INFO, "removing expired pinhole '%s'", RULE.label[0]);
+ syslog(LOG_INFO, "Expire IPv6 port map [?]:?/?");
#else /* USE_LIBPFCTL */
- syslog(LOG_INFO, "removing expired pinhole '%s'", RULE.label);
+ syslog(LOG_INFO, "Expire IPv6 port map [?]:?/?");
#endif /* USE_LIBPFCTL */
pr.action = PF_CHANGE_GET_TICKET;
if(ioctl(dev, DIOCCHANGERULE, &pr) < 0) {
--- a/upnpdescgen.c
+++ b/upnpdescgen.c
@@ -1311,7 +1311,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 || (!GETFLAG(ALLOWPRIVATEIPV4MASK) && addr_is_reserved(&addr))) {
+ if(getifaddr(ext_if_name, ext_ip_addr, INET_ADDRSTRLEN, &addr, NULL) < 0 || (!GETFLAG(REPORTPRIVATEIPV4MASK) && addr_is_reserved(&addr))) {
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
@@ -102,7 +102,7 @@ extern int runtime_flags;
#define PERFORMSTUNMASK 0x1000
/*! \brief Allow the external IPv4 to be private */
-#define ALLOWPRIVATEIPV4MASK 0x2000
+#define REPORTPRIVATEIPV4MASK 0x2000
/*! \brief do not stop on STUN detecting restricive NAT */
#define ALLOWFILTEREDSTUNMASK 0x4000
--- a/upnphttp.c
+++ b/upnphttp.c
@@ -554,7 +554,7 @@ ProcessHTTPPOST_upnphttp(struct upnphttp
if(h->req_soapActionOff > 0)
{
/* we can process the request */
- syslog(LOG_INFO, "SOAPAction: %.*s",
+ syslog(LOG_DEBUG, "SOAPAction: %.*s",
h->req_soapActionLen, h->req_buf + h->req_soapActionOff);
ExecuteSoapAction(h,
h->req_buf + h->req_soapActionOff,
@@ -854,7 +854,7 @@ ProcessHttpQuery_upnphttp(struct upnphtt
for(i = 0; i<15 && *p != '\r'; i++)
HttpVer[i] = *(p++);
HttpVer[i] = '\0';
- syslog(LOG_INFO, "HTTP REQUEST from %s : %s %s (%s)",
+ syslog(LOG_DEBUG, "HTTP REQUEST from %s : %s %s (%s)",
h->clientaddr_str, HttpCommand, HttpUrl, HttpVer);
ParseHttpHeaders(h);
if(h->req_contentlen > CONTENT_LENGTH_LIMIT) {
@@ -940,7 +940,7 @@ ProcessHttpQuery_upnphttp(struct upnphtt
return;
}
#endif
- syslog(LOG_NOTICE, "%s not found, responding ERROR 404", HttpUrl);
+ syslog(LOG_DEBUG, "%s not found, responding ERROR 404", HttpUrl);
Send404(h);
}
#ifdef ENABLE_EVENTS
--- a/upnppermissions.c
+++ b/upnppermissions.c
@@ -23,6 +23,9 @@
#include "upnppermissions.h"
#include "upnputils.h"
+uint16_t default_min_port = 1;
+uint16_t default_max_port = 65535;
+
static int
isodigit(char c)
{
@@ -523,14 +526,19 @@ check_upnp_rule_against_permissions(cons
if(match_permission(permary + i, eport, address, iport, desc))
{
syslog(LOG_DEBUG,
- "UPnP permission rule %d matched : port mapping %s",
+ "ACL entry %d matched, port mapping %s",
i, (permary[i].type == UPNPPERM_ALLOW)?"accepted":"rejected"
);
return (permary[i].type == UPNPPERM_ALLOW);
}
}
- syslog(LOG_DEBUG, "no permission rule matched : accept by default (n_perms=%d)", n_perms);
- return 1; /* Default : accept */
+
+ if (iport < default_min_port || eport < default_min_port || iport > default_max_port || eport > default_max_port) {
+ return 0;
+ } else {
+ syslog(LOG_DEBUG, "No ACL entry matched, ACL accepted by default");
+ return 1; /* Default : accept */
+ }
}
void
--- a/upnppermissions.h
+++ b/upnppermissions.h
@@ -18,6 +18,9 @@
#include <regex.h>
#endif
+extern uint16_t default_min_port;
+extern uint16_t default_max_port;
+
/* UPnP permission rule samples:
* allow 1024-65535 192.168.3.0/24 1024-65535
* deny 0-65535 192.168.1.125/32 0-65535 */
--- a/upnppinhole.c
+++ b/upnppinhole.c
@@ -110,7 +110,7 @@ lease_file6_add(const char * rem_client,
fd = fopen( lease_file6, "a");
if (fd==NULL) {
- syslog(LOG_ERR, "could not open lease file: %s", lease_file);
+ syslog(LOG_DEBUG, "could not open lease file: %s", lease_file);
return -1;
}
@@ -398,7 +398,7 @@ int lease_file6_expire(void)
// Internal Host
p = strchr(line, ';');
if(!p) {
- syslog(LOG_ERR, "unrecognized data in lease file");
+ syslog(LOG_DEBUG, "unrecognized data in lease file (non-critical bug)");
continue;
}
*(p++) = '\0';
@@ -489,7 +489,7 @@ int reload_from_lease_file6(void)
if(!lease_file6) return -1;
fd = fopen( lease_file6, "r");
if (fd==NULL) {
- syslog(LOG_ERR, "could not open lease file: %s", lease_file6);
+ syslog(LOG_DEBUG, "could not open lease file: %s", lease_file6);
return -1;
}
if(unlink(lease_file6) < 0) {
@@ -560,11 +560,6 @@ int reload_from_lease_file6(void)
while(isspace(*p) && (p > desc))
*(p--) = '\0';
- /* Ensure port is non-privileged and RemoteHost is valid */
- if (int_port < 1024) {
- syslog(LOG_WARNING, "ignoring lease file pinhole with privileged port %hu", int_port);
- continue;
- }
if (rem_client && rem_client[0] != '\0' && rem_client[0] != '*') {
struct in6_addr rem_addr;
if (inet_pton(AF_INET6, rem_client, &rem_addr) != 1) {
@@ -575,7 +570,7 @@ int reload_from_lease_file6(void)
if(timestamp > 0) {
if(timestamp <= (unsigned int)current_unix_time) {
- syslog(LOG_NOTICE, "already expired lease in lease file");
+ syslog(LOG_INFO, "Expire IPv6 port map ?:[?]:[?]/? reason lease file reload");
continue;
} else {
leaseduration = timestamp - current_unix_time;
@@ -652,7 +647,8 @@ upnp_add_inboundpinhole(const char * rad
*uid = upnp_find_inboundpinhole(raddr, rport, iaddr, iport, proto, NULL, 0, NULL);
if(*uid >= 0) {
- syslog(LOG_INFO, "Pinhole for inbound traffic from [%s]:%hu to [%s]:%hu with proto %d found uid=%d. Updating it.", raddr, rport, iaddr, iport, proto, *uid);
+ syslog(LOG_INFO, "Renew IPv6 port map [%s]:%hu/%s remote IP %s remote port %hu lifetime %d via UPnP IGDv2 IPv6 UID %d",
+ iaddr, iport, proto_itoa(proto), raddr[0] != '\0' ? raddr : "any", rport, leasetime, *uid);
r = upnp_update_inboundpinhole(*uid, leasetime);
#ifdef ENABLE_LEASEFILE
if (r >= 0) {
--- a/upnpredirect.c
+++ b/upnpredirect.c
@@ -67,7 +67,7 @@ lease_file_add(const char * rhost,
fd = fopen( lease_file, "a");
if (fd==NULL) {
- syslog(LOG_ERR, "could not open lease file: %s", lease_file);
+ syslog(LOG_DEBUG, "could not open lease file: %s", lease_file);
return -1;
}
@@ -196,7 +196,7 @@ int reload_from_lease_file(void)
if(!lease_file) return -1;
fd = fopen( lease_file, "r");
if (fd==NULL) {
- syslog(LOG_ERR, "could not open lease file: %s", lease_file);
+ syslog(LOG_DEBUG, "could not open lease file: %s", lease_file);
return -1;
}
if(unlink(lease_file) < 0) {
@@ -266,7 +266,7 @@ int reload_from_lease_file(void)
timestamp += current_time; /* convert to our time */
#else
if(timestamp <= (unsigned int)current_unix_time) {
- syslog(LOG_NOTICE, "already expired lease in lease file (%hu=>%s:%hu %s)",
+ syslog(LOG_INFO, "Expire IPv4 port map %hu:%s:%hu/%s reason lease file reload",
eport, iaddr, iport, proto);
continue;
} else {
@@ -348,8 +348,8 @@ upnp_redirect(const char * rhost, unsign
if(!check_upnp_rule_against_permissions(upnppermlist, num_upnpperm,
eport, address, iport, desc)) {
- syslog(LOG_INFO, "redirection permission check failed for "
- "%hu->%s:%hu %s %s", eport, iaddr, iport, protocol, desc);
+ syslog(LOG_INFO, "Reject IPv4 port map %hu:%s:%hu/%s via UPnP IGD reason ACL/default-min/max-port",
+ eport, iaddr, iport, protocol);
return -3;
}
@@ -397,8 +397,8 @@ upnp_redirect(const char * rhost, unsign
((rhost == NULL && rhost_old[0]=='\0') ||
(rhost && (strcmp(rhost, "*") == 0) && rhost_old[0]=='\0') ||
(rhost && (strcmp(rhost, rhost_old) == 0)))) {
- syslog(LOG_INFO, "updating existing port mapping %hu %s (rhost '%s') => %s:%hu",
- eport, protocol, rhost_old, iaddr_old, iport_old);
+ syslog(LOG_INFO, "Renew IPv4 port map %hu:%s:%hu/%s remote IP %s lifetime %d via UPnP IGD",
+ eport, iaddr_old, iport_old, protocol, rhost_old[0] != '\0' ? rhost_old : "any", leaseduration);
timestamp = (leaseduration > 0) ? upnp_time() + leaseduration : 0;
if(iport != iport_old) {
r = update_portmapping(ext_if_name, eport, proto, iport, desc, timestamp);
@@ -413,19 +413,19 @@ upnp_redirect(const char * rhost, unsign
#endif /* ENABLE_LEASEFILE */
return r;
} else {
- syslog(LOG_INFO, "port %hu %s (rhost '%s') already redirected to %s:%hu",
- eport, protocol, rhost_old, iaddr_old, iport_old);
+ syslog(LOG_INFO, "Reject IPv4 port map %hu:%s:%hu/%s via UPnP IGD reason port in use",
+ eport, iaddr_old, iport_old, protocol);
return -2;
}
#ifdef CHECK_PORTINUSE
} else if (port_in_use(ext_if_name, eport, proto, iaddr, iport) > 0) {
- syslog(LOG_INFO, "port %hu protocol %s already in use",
- eport, protocol);
+ syslog(LOG_INFO, "Reject IPv4 port map %hu:%s:%hu/%s via UPnP IGD reason port in use",
+ eport, iaddr, iport, protocol);
return -4;
#endif /* CHECK_PORTINUSE */
} else {
timestamp = (leaseduration > 0) ? upnp_time() + leaseduration : 0;
- syslog(LOG_INFO, "redirecting port %hu to %s:%hu protocol %s for: %s",
+ syslog(LOG_DEBUG, "redirecting port %hu to %s:%hu protocol %s for: %s",
eport, iaddr, iport, protocol, desc);
return upnp_redirect_internal(rhost, eport, iaddr, iport, proto,
desc, timestamp);
@@ -438,8 +438,6 @@ upnp_redirect_internal(const char * rhos
int proto, const char * desc,
unsigned int timestamp)
{
- /*syslog(LOG_INFO, "redirecting port %hu to %s:%hu protocol %s for: %s",
- eport, iaddr, iport, protocol, desc); */
if(disable_port_forwarding)
return -1;
if(add_redirect_rule2(ext_if_name, rhost, eport, iaddr, iport, proto,
@@ -450,8 +448,6 @@ upnp_redirect_internal(const char * rhos
#ifdef ENABLE_LEASEFILE
lease_file_add(rhost, eport, iaddr, iport, proto, desc, timestamp);
#endif
-/* syslog(LOG_INFO, "creating pass rule to %s:%hu protocol %s for: %s",
- iaddr, iport, protocol, desc);*/
if(add_filter_rule2(ext_if_name, rhost, iaddr, eport, iport, proto, desc) < 0) {
/* clean up the redirect rule */
#if !defined(__linux__)
@@ -571,7 +567,7 @@ _upnp_delete_redir(unsigned short eport,
int
upnp_delete_redirection(unsigned short eport, const char * protocol)
{
- syslog(LOG_INFO, "removing redirect rule port %hu %s", eport, protocol);
+ syslog(LOG_INFO, "Delete IPv4 port map %hu:?:?/%s via UPnP IGD", eport, protocol);
return _upnp_delete_redir(eport, proto_atoi(protocol));
}
@@ -675,7 +671,7 @@ get_upnp_rules_state_list(int max_rules_
{
if(tmp->to_remove)
{
- syslog(LOG_NOTICE, "remove port mapping %hu %s because it has expired",
+ syslog(LOG_INFO, "Expire IPv4 port map %hu:?:?/%s",
tmp->eport, proto_itoa(tmp->proto));
_upnp_delete_redir(tmp->eport, tmp->proto);
*p = tmp->next;
--- a/upnpsoap.c
+++ b/upnpsoap.c
@@ -412,18 +412,9 @@ GetExternalIPAddress(struct upnphttp * h
else
{
struct in_addr addr;
- if(getifaddr(ext_if_name, ext_ip_addr, INET_ADDRSTRLEN, &addr, NULL) < 0)
- {
- syslog(LOG_ERR, "Failed to get ip address for interface %s",
- ext_if_name);
- ext_ip_addr[0] = '\0';
- } else if (addr_is_reserved(&addr)) {
- if (GETFLAG(ALLOWPRIVATEIPV4MASK)) {
- syslog(LOG_WARNING, "IGNORED : private/reserved address %s is not suitable for external IP", ext_ip_addr);
- } else {
- syslog(LOG_NOTICE, "private/reserved address %s is not suitable for external IP", ext_ip_addr);
+ if (getifaddr(ext_if_name, ext_ip_addr, INET_ADDRSTRLEN, &addr, NULL) < 0 ||
+ (addr_is_reserved(&addr) && !GETFLAG(REPORTPRIVATEIPV4MASK))) {
ext_ip_addr[0] = '\0';
- }
}
}
#else
@@ -545,7 +536,7 @@ AddPortMapping(struct upnphttp * h, cons
}
else
{
- syslog(LOG_ERR, "Failed to convert hostname '%s' to ip address", int_ip);
+ syslog(LOG_INFO, "Failed to parse or resolve to (%s) IPv4 address via UPnP IGD", int_ip);
ClearNameValueList(&data);
SoapError(h, 402, "Invalid Args");
return;
@@ -557,8 +548,8 @@ AddPortMapping(struct upnphttp * h, cons
{
if(h->clientaddr.s_addr != result_ip.s_addr)
{
- syslog(LOG_INFO, "Client %s tried to redirect port to %s",
- inet_ntoa(h->clientaddr), int_ip);
+ syslog(LOG_INFO, "Reject IPv4 port map ?:%s:?/? via UPnP IGD reason for third-party from %s",
+ int_ip, inet_ntoa(h->clientaddr));
ClearNameValueList(&data);
#ifdef IGD_V2
SoapError(h, 606, "Action not authorized");
@@ -606,9 +597,9 @@ AddPortMapping(struct upnphttp * h, cons
leaseduration = 604800;
#endif
- syslog(LOG_INFO, "%s: ext port %hu to %s:%hu protocol %s for: %s leaseduration=%u rhost=%s",
- action, eport, int_ip, iport, protocol, desc, leaseduration,
- r_host ? r_host : "NULL");
+ syslog(LOG_INFO, "Add IPv4 port map %hu:%s:%hu/%s remote IP %s lifetime %u via UPnP IGD",
+ eport, int_ip, iport, protocol, r_host[0] != '\0' ? r_host : "any",
+ leaseduration);
r = upnp_redirect(r_host, eport, int_ip, iport, protocol, desc, leaseduration);
@@ -750,7 +741,7 @@ AddAnyPortMapping(struct upnphttp * h, c
}
else
{
- syslog(LOG_ERR, "Failed to convert hostname '%s' to ip address", int_ip);
+ syslog(LOG_INFO, "Failed to parse or resolve to (%s) IPv4 address via UPnP IGDv2 AddAny", int_ip);
ClearNameValueList(&data);
SoapError(h, 402, "Invalid Args");
return;
@@ -762,8 +753,8 @@ AddAnyPortMapping(struct upnphttp * h, c
{
if(h->clientaddr.s_addr != result_ip.s_addr)
{
- syslog(LOG_INFO, "Client %s tried to redirect port to %s",
- inet_ntoa(h->clientaddr), int_ip);
+ syslog(LOG_INFO, "Reject IPv4 port map ?:%s:?/? via UPnP IGDv2 AddAny reason for third-party from %s",
+ int_ip, inet_ntoa(h->clientaddr));
ClearNameValueList(&data);
SoapError(h, 606, "Action not authorized");
return;
@@ -826,6 +817,8 @@ AddAnyPortMapping(struct upnphttp * h, c
SoapError(h, 501, "Action Failed");
return;
}
+ syslog(LOG_INFO, "Add IPv4 port map %hu:%s:%hu/%s remote IP %s lifetime %u via UPnP IGDv2 AddAny",
+ eport, int_ip, iport, protocol, r_host[0] != '\0' ? r_host : "any", leaseduration);
BuildSendAndCloseSoapResp(h, body, bodylen);
break;
case -2: /* already redirected */
@@ -913,7 +906,7 @@ GetSpecificPortMappingEntry(struct upnph
}
else
{
- syslog(LOG_INFO, "%s: rhost='%s' %s %s found => %s:%u desc='%s' duration=%u",
+ syslog(LOG_DEBUG, "%s: rhost='%s' %s %s found => %s:%u desc='%s' duration=%u",
action,
r_host ? r_host : "NULL", ext_port, protocol, int_ip,
(unsigned int)iport, desc, leaseduration);
@@ -1003,7 +996,7 @@ DeletePortMapping(struct upnphttp * h, c
return;
}
- syslog(LOG_INFO, "%s: external port: %hu, protocol: %s",
+ syslog(LOG_DEBUG, "%s: external port: %hu, protocol: %s",
action, eport, protocol);
/* if in secure mode, check the IP
@@ -1042,6 +1035,8 @@ DeletePortMapping(struct upnphttp * h, c
if(r < 0)
{
+ syslog(LOG_INFO, "Non-existing IPv4 port map to delete %hu:?:?/%s via UPnP IGD",
+ eport, protocol);
SoapError(h, 714, "NoSuchEntryInArray");
}
else
@@ -1109,8 +1104,8 @@ DeletePortMappingRange(struct upnphttp *
return;
}
- syslog(LOG_INFO, "%s: deleting external ports: %hu-%hu, protocol: %s",
- action, startport, endport, protocol);
+ syslog(LOG_INFO, "Delete IPv4 port map %hu-%hu:?:?/%s via UPnP IGDv2 DeleteRange",
+ startport, endport, protocol);
port_list = upnp_get_portmappings_in_range(startport, endport,
protocol, &number);
@@ -1125,7 +1120,7 @@ DeletePortMappingRange(struct upnphttp *
for(i = 0; i < number; i++)
{
r = upnp_delete_redirection(port_list[i], protocol);
- syslog(LOG_INFO, "%s: deleting external port: %hu, protocol: %s: %s",
+ syslog(LOG_DEBUG, "%s: deleting external port: %hu, protocol: %s: %s",
action, port_list[i], protocol, r < 0 ? "failed" : "ok");
}
free(port_list);
@@ -1196,7 +1191,7 @@ GetGenericPortMappingEntry(struct upnpht
return;
}
- syslog(LOG_INFO, "%s: index=%d", action, (int)index);
+ syslog(LOG_DEBUG, "%s: index=%d", action, (int)index);
rhost[0] = '\0';
r = upnp_get_redirection_infos_by_index((int)index, &eport, protocol, &iport,
@@ -1777,8 +1772,8 @@ PinholeVerification(struct upnphttp * h,
struct addrinfo hints, *ai, *p;
int found = 0;
- syslog(LOG_INFO, "%s: InternalClient %s is not an IPv6, assume hostname and convert",
- "PinholeVerification", int_ip);
+ syslog(LOG_DEBUG, "Resolve hostname (%s) to IPv6 address",
+ int_ip);
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
@@ -1788,8 +1783,8 @@ PinholeVerification(struct upnphttp * h,
r = getaddrinfo(int_ip, NULL, &hints, &ai);
if (r != 0)
{
- syslog(LOG_WARNING, "%s: Failed to convert hostname '%s' to IP address : %s",
- "PinholeVerification", int_ip, gai_strerror(r));
+ syslog(LOG_INFO, "Failed to parse or resolve to (%s) IPv6 address via UPnP IGDv2 IPv6",
+ int_ip);
SoapError(h, 402, "Invalid Args");
return -1;
}
@@ -1803,12 +1798,12 @@ PinholeVerification(struct upnphttp * h,
if (inet_ntop(AF_INET6, &result_ip, int_ip_resolved, INET6_ADDRSTRLEN) == NULL)
{
- syslog(LOG_WARNING, "%s: inet_ntop(): %m", "PinholeVerification");
+ syslog(LOG_INFO, "%s: inet_ntop(): %m", "PinholeVerification");
SoapError(h, 501, "Action Failed");
return -1;
}
- syslog(LOG_INFO, "%s: InternalClient \"%s\" resolved as %s",
- "PinholeVerification", int_ip, int_ip_resolved);
+ syslog(LOG_DEBUG, "Resolve hostname (%s) to IPv6 address (%s)",
+ int_ip, int_ip_resolved);
found = 1;
}
else
@@ -1823,8 +1818,8 @@ PinholeVerification(struct upnphttp * h,
freeaddrinfo(ai);
if (!found)
{
- syslog(LOG_NOTICE, "%s: No IPv6 address for hostname '%s'",
- "PinholeVerification", int_ip);
+ syslog(LOG_INFO, "Failed to parse or resolve to (%s) IPv6 address via UPnP IGDv2 IPv6",
+ int_ip);
SoapError(h, 402, "Invalid Args");
return -1;
}
@@ -1841,7 +1836,7 @@ PinholeVerification(struct upnphttp * h,
/* no need to copy to int_ip_resolved, but we still need to fill result_ip up */
if (inet_pton(AF_INET6, int_ip, &result_ip) <= 0)
{
- syslog(LOG_ERR, "inet_pton(%s)", int_ip);
+ syslog(LOG_DEBUG, "inet_pton(%s)", int_ip);
SoapError(h, 501, "Action Failed");
return -1;
}
@@ -1855,8 +1850,8 @@ PinholeVerification(struct upnphttp * h,
if(memcmp(&h->clientaddr_v6, &result_ip, sizeof(struct in6_addr)) != 0)
{
- syslog(LOG_INFO, "%s: Client %s tried to access pinhole for internal %s and is not authorized",
- "PinholeVerification", clientaddr_str, int_ip_resolved == NULL ? int_ip : int_ip_resolved);
+ syslog(LOG_INFO, "Reject IPv6 port map [%s]:?/? via UPnP IGDv2 IPv6 reason for third-party from %s",
+ int_ip_resolved == NULL ? int_ip : int_ip_resolved, clientaddr_str);
SoapError(h, 606, "Action not authorized");
return 0;
}
@@ -1868,11 +1863,10 @@ PinholeVerification(struct upnphttp * h,
}
#endif
- /* Pinhole InternalPort must be greater than or equal to 1024 */
- if (int_port < 1024)
+ if (int_port < default_min_port || int_port > default_max_port)
{
- syslog(LOG_INFO, "Client %s tried to access pinhole with port < 1024 and is not authorized to do it",
- clientaddr_str);
+ syslog(LOG_INFO, "Reject IPv6 port map [%s]:%hu/? via UPnP IGDv2 IPv6 reason default-min/max-port",
+ clientaddr_str, int_port);
SoapError(h, 606, "Action not authorized");
return 0;
}
@@ -1974,7 +1968,7 @@ AddPinhole(struct upnphttp * h, const ch
inet_ntop(AF_INET6,
&(((struct sockaddr_in6 *)p->ai_addr)->sin6_addr),
rem_ip, sizeof(rem_ip));
- syslog(LOG_INFO, "resolved '%s' to '%s'", rem_host, rem_ip);
+ syslog(LOG_DEBUG, "Resolve hostname (%s) to IPv6 address (%s)", rem_host, rem_ip);
rem_host = rem_ip;
break;
}
@@ -1983,8 +1977,8 @@ AddPinhole(struct upnphttp * h, const ch
}
else
{
- syslog(LOG_WARNING, "AddPinhole : getaddrinfo(%s) : %s",
- rem_host, gai_strerror(err));
+ syslog(LOG_INFO, "Failed to parse or resolve to (%s) IPv6 address via UPnP IGDv2 IPv6",
+ rem_host);
#if 0
SoapError(h, 402, "Invalid Args");
goto clear_and_exit;
@@ -2017,10 +2011,8 @@ AddPinhole(struct upnphttp * h, const ch
if(PinholeVerification(h, int_ip, iport, int_ip_resolved) <= 0)
goto clear_and_exit;
- syslog(LOG_INFO, "%s: (inbound) from [%s]:%hu to [%s]:%hu with proto %ld during %d sec",
- action, rem_host?rem_host:"any",
- rport, int_ip_resolved, iport,
- proto, ltime);
+ syslog(LOG_INFO, "Add IPv6 port map [%s]:%hu/%s remote IP %s remote port %hu lifetime %d via UPnP IGDv2 IPv6",
+ int_ip_resolved, iport, proto_itoa(proto), rem_host[0] != '\0' ? rem_host : "any", rport, ltime);
/* In cases where the RemoteHost, RemotePort, InternalPort,
* InternalClient and Protocol are the same than an existing pinhole,
@@ -2124,8 +2116,8 @@ UpdatePinhole(struct upnphttp * h, const
return;
}
- syslog(LOG_INFO, "%s: (inbound) updating lease duration to %d for pinhole with ID: %d",
- action, ltime, uid);
+ syslog(LOG_INFO, "Renew IPv6 port map [?]:?/? lifetime %d via UPnP IGDv2 IPv6 Update UID %d",
+ ltime, uid);
n = upnp_update_inboundpinhole(uid, ltime);
if(n == -1)
@@ -2188,7 +2180,7 @@ GetOutboundPinholeTimeout(struct upnphtt
iport = (unsigned short)atoi(int_port);
/*proto = atoi(protocol);*/
- syslog(LOG_INFO, "%s: retrieving timeout for outbound pinhole from [%s]:%hu to [%s]:%hu protocol %s", action, int_ip, iport,rem_host, rport, protocol);
+ syslog(LOG_DEBUG, "%s: retrieving timeout for outbound pinhole from [%s]:%hu to [%s]:%hu protocol %s", action, int_ip, iport,rem_host, rport, protocol);
/* TODO */
r = -1;/*upnp_check_outbound_pinhole(proto, &opt);*/
@@ -2264,11 +2256,14 @@ DeletePinhole(struct upnphttp * h, const
&leasetime, NULL);
if (n >= 0)
{
- if(PinholeVerification(h, iaddr, iport, NULL) <= 0)
+ if(PinholeVerification(h, iaddr, iport, NULL) <= 0) {
+ syslog(LOG_INFO, "Non-existing IPv6 port map to delete via UPnP IGDv2 IPv2 UID %d", uid);
return;
+ }
}
else if(n == -2)
{
+ syslog(LOG_INFO, "Non-existing IPv6 port map to delete via UPnP IGDv2 IPv2 UID %d", uid);
SoapError(h, 704, "NoSuchEntry");
return;
}
@@ -2286,8 +2281,8 @@ DeletePinhole(struct upnphttp * h, const
SoapError(h, 501, "Action Failed");
return;
}
- syslog(LOG_INFO, "%s: (inbound) pinhole with ID %d successfully removed",
- action, uid);
+ syslog(LOG_INFO, "Delete IPv6 port map [?]:?/? via UPnP IGDv2 IPv6 UID %d",
+ uid);
bodylen = snprintf(body, sizeof(body), resp,
action, ns, action);
if (bodylen < 0 || bodylen >= (int)sizeof(body)) {
@@ -2696,7 +2691,7 @@ SoapError(struct upnphttp * h, int errCo
char body[2048];
int bodylen;
- syslog(LOG_INFO, "Returning UPnPError %d: %s", errCode, errDesc);
+ syslog(LOG_DEBUG, "Returning UPnPError %d: %s", errCode, errDesc);
bodylen = snprintf(body, sizeof(body), resp, errCode, errDesc);
if(bodylen < 0) {
syslog(LOG_ERR, "snprintf() returned %d", bodylen);
--- a/upnpstun.c
+++ b/upnpstun.c
@@ -10,9 +10,10 @@
/*! \file upnpstun.c
* \brief STUN client implementation
*
- * - https://datatracker.ietf.org/doc/html/rfc3489 (obsolete)
- * - https://datatracker.ietf.org/doc/html/rfc5389
- * - https://datatracker.ietf.org/doc/html/rfc5780 (experimental)
+ * - https://www.rfc-editor.org/info/rfc3489/ (classic STUN, obsoleted)
+ * - https://www.rfc-editor.org/info/rfc5389/ (STUN obsoleted)
+ * - https://www.rfc-editor.org/info/rfc5780/ (STUN NAT behavior, experimental)
+ * - https://www.rfc-editor.org/info/rfc8489/ (STUN current, not implemented)
*/
#include <sys/select.h>
#include <sys/time.h>
@@ -124,8 +125,8 @@ static int resolve_stun_host(const char
r = getaddrinfo(stun_host, service, &hints, &result);
if (r != 0) {
- syslog(LOG_ERR, "%s: getaddrinfo(%s, %s, ...) failed : %s",
- "resolve_stun_host", stun_host, service, gai_strerror(r));
+ syslog(LOG_ERR, "STUN: Failed to resolve hostname (%s) to IPv4 address (%s)",
+ stun_host, gai_strerror(r));
errno = EHOSTUNREACH;
return -1;
}
@@ -149,8 +150,8 @@ static int resolve_stun_host(const char
} else {
char addr_str[48];
if (sockaddr_to_string((struct sockaddr *)sock_addr, addr_str, sizeof(addr_str)) > 0) {
- syslog(LOG_DEBUG, "%s: %s:%s => %s",
- "resolve_stun_host", stun_host, service, addr_str);
+ syslog(LOG_DEBUG, "%s: Resolve hostname (%s) and connect to %s",
+ "resolve_stun_host", stun_host, addr_str);
}
}
@@ -274,7 +275,7 @@ static int wait_for_stun_responses(int f
FD_SET(fds[i], &fdset);
}
- syslog(LOG_DEBUG, "%s: waiting %ld secs and %ld usecs", "wait_for_stun_responses", (long)timeout.tv_sec, (long)timeout.tv_usec);
+ syslog(LOG_DEBUG, "%s: waiting %ld.%ld s", "wait_for_stun_responses", (long)timeout.tv_sec, (long)timeout.tv_usec);
ret = select(max_fd+1, &fdset, NULL, NULL, &timeout);
if (ret < 0) {
if (errno == EINTR)
@@ -484,7 +485,8 @@ static int parse_stun_response(unsigned
if (!have_other_address && have_address) {
syslog(LOG_ERR, "STUN server not supported, not returning "
"OTHER-ADDRESS / support CHANGE-REQUEST's required for "
- "endpoint-independent (1:1) CGNAT filtering tests per RFC 5780.");
+ "endpoint-independent (1:1) CGNAT filtering tests per RFC 5780, "
+ "see compatible servers in sample config");
return -1;
}
return (have_address && have_other_address) ? 0 : -1;
@@ -529,13 +531,13 @@ int perform_stun(const char *if_name, co
/* Determine unrestricted endpoint-independent (1:1) CGNAT in two STUN requests per RFC 5780 4.4 test I/II */
/* 1. Connectivity (binding, detect public IPv4), 2. CHANGE-REQUEST with change-IP and change-port set */
- /* https://datatracker.ietf.org/doc/html/rfc5780#section-4.4 */
+ /* https://www.rfc-editor.org/info/rfc5780/#section-4.4 */
fill_request(requests[i], i, i);
transaction_ids[i] = requests[i]+8;
}
- syslog(LOG_INFO, "%s: local ports %hu %hu %hu %hu",
- "perform_stun", local_ports[0], local_ports[1],
+ syslog(LOG_INFO, "STUN: Testing with local UDP ports %hu %hu %hu %hu",
+ local_ports[0], local_ports[1],
local_ports[2], local_ports[3]);
/* Unblock local ports */
@@ -600,16 +602,15 @@ int perform_stun(const char *if_name, co
if (mapped_addrs_count < 4) {
/* We have not received all four responses,
* therefore NAT or firewall is doing some filtering */
- syslog(LOG_NOTICE, "%s: %d response out of 4 received",
- "perform_stun", mapped_addrs_count);
+ syslog(LOG_NOTICE, "STUN: Filtering detected as %d/4 responses received (1: IPv4 detection, 2-4: filtering tests)",
+ mapped_addrs_count);
*restrictive_nat = 1;
}
if (memcmp(&remote_addr, &peer_addrs[0], sizeof(peer_addrs[0])) != 0) {
/* We received STUN response from different address
* even we did not asked for it, so some strange NAT is active */
- syslog(LOG_NOTICE, "%s: address changed",
- "perform_stun");
+ syslog(LOG_NOTICE, "STUN: Public IPv4 change detected in responses");
*restrictive_nat = 1;
}
@@ -621,8 +622,8 @@ int perform_stun(const char *if_name, co
sockaddr_to_string((struct sockaddr *)&mapped_addrs[i], mapped_addr_str, sizeof(mapped_addr_str));
/* External IP address or port was changed,
* therefore symmetric NAT is active */
- syslog(LOG_NOTICE, "%s: #%d external address or port changed : %s:%hu => %s",
- "perform_stun", i, inet_ntoa(*ext_addr), local_ports[i], mapped_addr_str);
+ syslog(LOG_NOTICE, "STUN: Public IPv4/port change detected in response #%d (%s:%hu => %s)",
+ i+1, inet_ntoa(*ext_addr), local_ports[i], mapped_addr_str);
*restrictive_nat = 1;
}
}