Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

net/upnp: enable STUN and allow LAN subnet override #3096

Merged
merged 14 commits into from Dec 13, 2022
5 changes: 2 additions & 3 deletions net/upnp/Makefile
@@ -1,7 +1,6 @@
PLUGIN_NAME= upnp
PLUGIN_VERSION= 1.4
PLUGIN_REVISION= 2
PLUGIN_DEPENDS= miniupnpd
PLUGIN_VERSION= 1.5
PLUGIN_DEPENDS= miniupnpd-devel
PLUGIN_COMMENT= Universal Plug and Play Service
PLUGIN_MAINTAINER= franco@opnsense.org

Expand Down
16 changes: 14 additions & 2 deletions net/upnp/src/etc/inc/plugins.inc.d/miniupnpd.inc
Expand Up @@ -147,7 +147,11 @@ function miniupnpd_configure_do($verbose = false)
if ($if != $iface) {
$addr = get_interface_ip($iface);
if (!empty($addr)) {
$config_text .= "listening_ip={$if}\n";
if (isset($upnp_config['overridesubnet'])) {
$config_text .= "listening_ip={$if}{$upnp_config['overridesubnet']}\n";
Tawmu marked this conversation as resolved.
Show resolved Hide resolved
} else {
$config_text .= "listening_ip={$if}\n";
}
if (!$ifaces_active) {
$webgui_ip = $addr;
$ifaces_active = $iface;
Expand All @@ -164,9 +168,17 @@ function miniupnpd_configure_do($verbose = false)

if (!empty($ifaces_active)) {
/* override wan ip address, common for carp, etc */
if (!empty($upnp_config['overridewanip'])) {
if (!empty($upnp_config['overridewanip']) && empty($upnp_config['stun_host'])) {
Tawmu marked this conversation as resolved.
Show resolved Hide resolved
$config_text .= "ext_ip={$upnp_config['overridewanip']}\n";
}

/* configure STUN server if needed */
if (empty($upnp_config['overridewanip']) && !empty($upnp_config['stun_host'])) {
$config_text .= "ext_perform_stun=yes\n";
$config_text .= "ext_stun_host=" . ($upnp_config['stun_host']) ."\n";
$config_text .= "ext_stun_port=" . ($upnp_config['stun_port'] ?? "3478") . "\n";
}

/* set upload and download bitrates */
if (!empty($upnp_config['download']) && !empty($upnp_config['upload'])) {
$download = $upnp_config['download'] * 1000;
Expand Down
57 changes: 54 additions & 3 deletions net/upnp/src/www/services_upnp.php
Expand Up @@ -68,8 +68,9 @@ function miniupnpd_validate_port($port)
if ($_SERVER['REQUEST_METHOD'] === 'GET') {
$pconfig = array();

$copy_fields = array('enable', 'enable_upnp', 'enable_natpmp', 'ext_iface', 'iface_array', 'download',
'upload', 'overridewanip', 'logpackets', 'sysuptime', 'permdefault');
$copy_fields = array('enable', 'enable_upnp', 'enable_natpmp', 'ext_iface', 'iface_array', 'stun_host',
'stun_port', 'overridesubnet', 'download', 'upload', 'overridewanip', 'logpackets', 'sysuptime',
'permdefault');

foreach (miniupnpd_permuser_list() as $permuser) {
$copy_fields[] = $permuser;
Expand Down Expand Up @@ -104,6 +105,18 @@ function miniupnpd_validate_port($port)
if (!empty($pconfig['overridewanip']) && !is_ipaddr($pconfig['overridewanip'])) {
$input_errors[] = gettext('You must specify a valid ip address in the \'Override WAN address\' field');
}
if (!empty($pconfig['overridewanip']) && !empty($pconfig['stun_host'])) {
$input_errors[] = gettext('You cannot override the WAN IP if you have a STUN host set.');
}
if (!empty($pconfig['stun_host']) && !is_addr($pconfig['stun_host']) && !is_hostname($pconfig['stun_host'])) {
$input_errors[] = gettext('The STUN host must be a valid IP address or hostname.');
}
if (!empty($pconfig['stun_port']) && !is_port($pconfig['stun_port'])) {
$input_errors[] = gettext('STUN port must contain a valid port number.');
}
if (!empty($pconfig['overridesubnet']) && count($pconfig['iface_array']) > 1) {
$input_errors[] = gettext('You can only override the interface subnet when one LAN interface is selected');
}
if ((!empty($pconfig['download']) && empty($pconfig['upload'])) || (!empty($pconfig['upload']) && empty($pconfig['download']))) {
$input_errors[] = gettext('You must fill in both \'Maximum Download Speed\' and \'Maximum Upload Speed\' fields');
}
Expand Down Expand Up @@ -146,7 +159,7 @@ function miniupnpd_validate_port($port)
$upnp[$fieldname] = !empty($pconfig[$fieldname]);
}
// text field types
foreach (array('ext_iface', 'download', 'upload', 'overridewanip') as $fieldname) {
foreach (array('ext_iface', 'download', 'upload', 'overridewanip', 'overridesubnet', 'stun_host', 'stun_port') as $fieldname) {
$upnp[$fieldname] = $pconfig[$fieldname];
}
foreach (miniupnpd_permuser_list() as $fieldname) {
Expand Down Expand Up @@ -255,6 +268,44 @@ function miniupnpd_validate_port($port)
</div>
</td>
</tr>

<tr>
<td><a id="help_for_override_subnet" href="#" class="showhelp"><i class="fa fa-info-circle"></i></a> <?=gettext("Interface subnet override");?></td>
<td>
<select name="overridesubnet" class="selectpicker" id="overridesubnet">
<option value="" <?=!empty($pconfig['overridesubnet']) ? "selected=\"selected\"" : "";?>>Interface default</option>
<?php
for ($i = 32; $i >= 1; $i--) { ?>
<option value="/<?=$i;?>" <?=!empty($pconfig['overridesubnet']) && $pconfig['overridesubnet'] == "/".$i ? "selected=\"selected\"" : "";?>>/<?=$i;?></option>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's probably safer to validate for subnet mask and add the "/" in the configuration. /32 is basically the default like when we omit the override?

Copy link
Contributor Author

@Tawmu Tawmu Dec 9, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The default ends up being the subnet of the interface rather than simply /32 afaik - not sure how to "validate" the subnet mask in this case to be honest and there may be a better way of writing this entirely.

To give context for this option - in our case, OPNsense is 10.10.0.2 behind a L3 switch on 10.10.0.1, and we have VLANs 10.40.0.0/22 and 10.50.0.0/22 routed via the switch, we simply override the miniupnpd config in OPNsense to be igb0/8 so it responds to requests coming in from the entire 10.0.0.0/8 space. It's pretty dirty but I'm not sure what we can validate subnet masks against in this case? Or do you mean just run it through the is_subnet function?

<?php
}?>
</select>
<div class="hidden" data-for="help_for_override_subnet">
<?=gettext("You can override a single LAN interface subnet here. Useful if you are rebroadcasting UPNP traffic across networks.");?>
</div>
</td>
</tr>

<tr>
<td><a id="help_for_stun_host" href="#" class="showhelp"><i class="fa fa-info-circle"></i></a> <?=gettext("Specify STUN server");?></td>
<td>
<input name="stun_host" type="text" value="<?=$pconfig['stun_host'];?>" />
<div class="hidden" data-for="help_for_stun_host">
<?=gettext("STUN server used to predict external WAN IP.");?>
</div>
</td>
</tr>

<tr>
<td><a id="help_for_stun_port" href="#" class="showhelp"><i class="fa fa-info-circle"></i></a> <?=gettext("Specify STUN port");?></td>
<td>
<input name="stun_port" type="text" value="<?=empty($pconfig['stun_port']) ? "3478" : $pconfig['stun_port'];?>" />
<div class="hidden" data-for="help_for_stun_port">
<?=gettext("STUN server port used to predict external WAN IP. Defaults to 3478 if not set.");?>
</div>
</td>
</tr>

<tr>
<td><a id="help_for_download" href="#" class="showhelp"><i class="fa fa-info-circle"></i></a> <?=gettext("Maximum Download Speed");?></td>
<td>
Expand Down