This commit is contained in:
Self-Hosting-Group 2026-02-03 08:44:24 +01:00 committed by GitHub
commit a99bbcfb94
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 70 additions and 16 deletions

View file

@ -1,5 +1,5 @@
PLUGIN_NAME= upnp
PLUGIN_VERSION= 1.8
PLUGIN_VERSION= 1.9
PLUGIN_DEPENDS= miniupnpd
PLUGIN_COMMENT= UPnP IGD & PCP/NAT-PMP Service
PLUGIN_MAINTAINER= franco@opnsense.org

View file

@ -7,6 +7,14 @@ WWW: https://miniupnp.tuxfamily.org/
Plugin Changelog
================
1.9
...
1.8
...
1.7
* Add option to allow arbitrary number of UPnP/NAT-PMP rules (contributed by Kreeblah)

View file

@ -26,6 +26,11 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
function miniupnpd_syslog()
{
return ['miniupnpd_syslog' => ['facility' => ['upnp_syslog']]];
}
function miniupnpd_enabled()
{
global $config;
@ -75,7 +80,16 @@ function miniupnpd_start()
return;
}
mwexecfb('/usr/local/sbin/miniupnpd -f %s -P %s', [ '/var/etc/miniupnpd.conf', '/var/run/miniupnpd.pid']);
global $config;
$upnp_config = $config['installedpackages']['miniupnpd']['config'][0];
if (($upnp_config['log_level'] ?? '') == 'info') {
$exec_cmd='/usr/local/sbin/miniupnpd -f %s -P %s -v';
} elseif (($upnp_config['log_level'] ?? '') == 'debug') {
$exec_cmd='/usr/local/sbin/miniupnpd -f %s -P %s -vv';
} else {
$exec_cmd='/usr/local/sbin/miniupnpd -f %s -P %s';
}
mwexecfb($exec_cmd, ['/var/etc/miniupnpd.conf', '/var/run/miniupnpd.pid']);
}
function miniupnpd_stop()
@ -217,7 +231,8 @@ function miniupnpd_configure_do($verbose = false)
/* enable system uptime instead of miniupnpd uptime */
if (!empty($upnp_config['sysuptime'])) {
$config_text .= "system_uptime=yes\n";
/* Disable system uptime to workaround daemon bug with PCP/NAT-PMP epoch on BSD */
// $config_text .= "system_uptime=yes\n";
}
/* set webgui url */

View file

@ -11,4 +11,11 @@
<pattern>status_upnp.php*</pattern>
</patterns>
</page-status-upnpstatus>
<page-services-upnp-log>
<name>Services: UPnP IGD &amp; PCP: Log File</name>
<patterns>
<pattern>ui/diagnostics/log/core/upnp/*</pattern>
<pattern>api/diagnostics/log/core/upnp/*</pattern>
</patterns>
</page-services-upnp-log>
</acl>

View file

@ -5,6 +5,7 @@
<Edit url="/services_upnp.php?*" visibility="hidden"/>
</Settings>
<ActiveMaps VisibleName="Active Maps" order="20" url="/status_upnp.php"/>
<LogFile VisibleName="Log File" order="30" url="/ui/diagnostics/log/core/upnp"/>
</UPnP>
</Services>
</menu>

View file

@ -0,0 +1,6 @@
###################################################################
# Local syslog-ng configuration filter definition [upnp].
###################################################################
filter f_local_upnp {
program("miniupnpd");
};

View file

@ -88,6 +88,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'GET') {
'sysuptime',
'upload',
'upnp_igd_compat',
'log_level'
];
foreach (miniupnpd_permuser_list() as $permuser) {
@ -186,7 +187,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'GET') {
$upnp['num_permuser'] = $pconfig['num_permuser'];
}
// text field types
foreach (['ext_iface', 'download', 'upload', 'overridewanip', 'overridesubnet', 'stun_host', 'stun_port', 'friendly_name', 'upnp_igd_compat'] as $fieldname) {
foreach (['ext_iface', 'download', 'upload', 'overridewanip', 'overridesubnet', 'stun_host', 'stun_port', 'friendly_name', 'upnp_igd_compat', 'log_level'] as $fieldname) {
$upnp[$fieldname] = $pconfig[$fieldname];
}
foreach (miniupnpd_permuser_list() as $fieldname) {
@ -233,16 +234,16 @@ include("head.inc");
</thead>
<tbody>
<tr>
<td><a id="help_for_enable" href="#" class="showhelp"><i class="fa fa-info-circle"></i></a> <?=gettext("Enable");?></td>
<td><a id="help_for_enable" href="#" class="showhelp"><i class="fa fa-info-circle"></i></a> <?=gettext("Enable service");?></td>
<td>
<input name="enable" type="checkbox" value="yes" <?=!empty($pconfig['enable']) ? "checked=\"checked\"" : ""; ?> />
<div class="hidden" data-for="help_for_enable">
<?=gettext("Start the autonomous port mapping service.");?>
<?=gettext("Enable the autonomous port mapping service.");?>
</div>
</td>
</tr>
<tr>
<td><a id="help_for_enable_upnp" href="#" class="showhelp"><i class="fa fa-info-circle"></i></a> <?=gettext("Allow UPnP IGD Port Mapping");?></td>
<td><a id="help_for_enable_upnp" href="#" class="showhelp"><i class="fa fa-info-circle"></i></a> <?=gettext("Enable UPnP IGD protocol");?></td>
<td>
<input name="enable_upnp" type="checkbox" value="yes" <?=!empty($pconfig['enable_upnp']) ? "checked=\"checked\"" : ""; ?> />
<div class="hidden" data-for="help_for_enable_upnp">
@ -251,7 +252,7 @@ include("head.inc");
</td>
</tr>
<tr>
<td><a id="help_for_enable_natpmp" href="#" class="showhelp"><i class="fa fa-info-circle"></i></a> <?=gettext("Allow PCP/NAT-PMP Port Mapping");?></td>
<td><a id="help_for_enable_natpmp" href="#" class="showhelp"><i class="fa fa-info-circle"></i></a> <?=gettext("Enable PCP/NAT-PMP protocols");?></td>
<td>
<input name="enable_natpmp" type="checkbox" value="yes" <?=!empty($pconfig['enable_natpmp']) ? "checked=\"checked\"" : ""; ?> />
<div class="hidden" data-for="help_for_enable_natpmp">
@ -324,16 +325,19 @@ include("head.inc");
</td>
</tr>
<tr>
<td><i class="fa fa-info-circle text-muted"></i> <?=gettext("Override external IPv4");?></td>
<td><a id="help_for_overridewanip" href="#" class="showhelp"><i class="fa fa-info-circle"></i></a> <?=gettext("Override external IPv4");?></td>
<td>
<input name="overridewanip" type="text" value="<?=$pconfig['overridewanip'];?>" />
<div class="hidden" data-for="help_for_overridewanip">
<?=gettext('Report custom public/external (WAN) IPv4 address.');?>
</div>
</td>
</tr>
<tr>
<td><a id="help_for_overridesubnet" href="#" class="showhelp"><i class="fa fa-info-circle"></i></a> <?=gettext("Internal interface IPv4 subnet override");?></td>
<td>
<select name="overridesubnet" class="selectpicker" id="overridesubnet">
<option value="" <?= empty($pconfig['overridesubnet']) ? 'selected="selected"' : '' ?>><?= gettext('default') ?></option>
<option value="" <?= empty($pconfig['overridesubnet']) ? 'selected="selected"' : '' ?>><?= gettext('Default') ?></option>
<?php for ($i = 32; $i >= 1; $i--): ?>
<option value="<?= $i ?>" <?=!empty($pconfig['overridesubnet']) && $pconfig['overridesubnet'] == $i ? 'selected="selected"' : '' ?>><?= $i ?></option>
<?php endfor ?>
@ -367,6 +371,16 @@ include("head.inc");
</div>
</td>
</tr> -->
<tr>
<td><i class="fa fa-info-circle text-muted"></i> <?= gettext('Log level') ?></td>
<td>
<select name="log_level">
<option value="default" <?= ($pconfig['log_level'] ?? '') == 'default' ? 'selected="selected"' : '' ?> ><?= gettext('Default') ?></option>
<option value="info" <?= ($pconfig['log_level'] ?? '') == 'info' ? 'selected="selected"' : '' ?> ><?= gettext('Info') ?></option>
<option value="debug" <?= ($pconfig['log_level'] ?? '') == 'debug' ? 'selected="selected"' : '' ?> ><?= gettext('Debug') ?></option>
</select>
</td>
</tr>
<tr>
<td><a id="help_for_logpackets" href="#" class="showhelp"><i class="fa fa-info-circle"></i></a> <?=gettext("Firewall logs");?></td>
<td>
@ -393,12 +407,15 @@ include("head.inc");
</thead>
<tbody>
<tr>
<td><i class="fa fa-info-circle text-muted"></i> <?= gettext('UPnP IGD compatibility mode') ?></td>
<td><a id="help_for_upnp_igd_compat" href="#" class="showhelp"><i class="fa fa-info-circle"></i></a> <?= gettext('UPnP IGD compatibility') ?></td>
<td>
<select name="upnp_igd_compat">
<option value="igdv1" <?= ($pconfig['upnp_igd_compat'] ?? '') == 'igdv1' ? 'selected="selected"' : '' ?> ><?= gettext('IGDv1 (IPv4 only)') ?></option>
<option value="igdv2" <?= ($pconfig['upnp_igd_compat'] ?? '') == 'igdv2' ? 'selected="selected"' : '' ?> ><?= gettext('IGDv2 (with workarounds)') ?></option>
</select>
<div class="hidden" data-for="help_for_upnp_igd_compat">
<?=sprintf(gettext('Set compatibility mode (act as device) to workaround IGDv2-incompatible clients; %s are known to only work with %s.'), 'Sony PS, Activision CoD…', 'IGDv1');?>
</div>
</td>
</tr>
<tr>
@ -436,7 +453,7 @@ include("head.inc");
<table class="table table-striped opnsense_standard_table_form">
<thead>
<tr>
<th colspan="2"><?=gettext("Custom Access Control List");?></th>
<th colspan="2"><?=gettext("Access Control List");?></th>
</tr>
</thead>
<tbody>

View file

@ -71,8 +71,8 @@ include("head.inc");
<th><?=gettext("Port")?></th>
<th><?=gettext("External port")?></th>
<th><?=gettext("Protocol")?></th>
<th><?=gettext("Source IP")?></th>
<th><?=gettext("Source port")?></th>
<th><?=gettext("Remote IP")?></th>
<th><?=gettext("Remote port")?></th>
<th><?=gettext("Added via / description")?></th>
</tr>
</thead>
@ -83,8 +83,8 @@ include("head.inc");
!preg_match('/on (?P<iface>.+) inet6 proto (?P<proto>.+) from (?P<srcaddr>[^ ]+) (port = (?P<srcport>.+) )?to (?P<intaddr>.+) port = (?P<intport>\d+) (flags [^ ]+ )?keep state (label "(?P<descr>.+)" )?rtable [0-9]/', $rdr_entry, $matches)) {
continue;
}
if (preg_match('/PCP ([A-Z]+) ([0-9a-f]{24})$/', $matches['descr'], $descrmatch) === 1) {
$descr = "PCP ({$descrmatch[1]} nonce {$descrmatch[2]})";
if (preg_match('/PCP [A-Z]+ ([0-9a-f]{24})$/', $matches['descr'], $descrmatch) === 1) {
$descr = "PCP (nonce {$descrmatch[1]})";
} elseif (preg_match('/^NAT-PMP \d+ \w+$/', $matches['descr'], $descrmatch) === 1) {
$descr = 'NAT-PMP';
} elseif (preg_match('/^pinhole-(\d+).*IGD2 pinhole$/', $matches['descr'], $descrmatch) === 1) {