From ee12197aca53bf9b9f8cd6811ec29214c2dac362 Mon Sep 17 00:00:00 2001 From: Markus Peter Date: Mon, 22 Nov 2021 08:52:34 +0100 Subject: [PATCH] Add nginx listen addresses and default_server, fixes #973, #1218, #1675, #2574 (#2578) - Changed listen_http_port, listen_https_port, listen_port to listen_http_address, listen_https_address, listen_address (issue #973, #2574) - Migrated the old listen_X_port to the new listen_X_address - Data Model ver 1.20.0 -> 1.21.0 - implemented default_server directive for non-tls listeners (issue #1218) - amended Help Message - added defaults for http server listen addresses - added changelog - fixed setup.php certificate setup - fixed inexplicable missing Reconfigureaction in ServiceController - fixed version numbers - removed reconfigureaction in ServiceController again, because it was due to a code cleanup by fichtner and has to be fixed on a higher level - added NgxUniqueDefaultServerConstraint which makes sure that default_servers do not conflict - added i18n for the error message - fixed some formatting issues - added type hints --- www/nginx/Makefile | 3 +- www/nginx/pkg-descr | 5 + .../OPNsense/Nginx/Api/LogsController.php | 2 +- .../OPNsense/Nginx/Api/SettingsController.php | 4 +- .../OPNsense/Nginx/forms/httpserver.xml | 23 ++- .../OPNsense/Nginx/forms/streamserver.xml | 9 +- .../NgxUniqueDefaultServerConstraint.php | 134 ++++++++++++++++++ .../OPNsense/Nginx/Migrations/M1_24_0.php | 59 ++++++++ .../mvc/app/models/OPNsense/Nginx/Nginx.xml | 48 ++++--- .../mvc/app/views/OPNsense/Nginx/index.volt | 7 +- .../src/opnsense/scripts/nginx/setup.php | 4 +- .../templates/OPNsense/Nginx/http.conf | 18 +-- .../templates/OPNsense/Nginx/streams.conf | 8 +- 13 files changed, 278 insertions(+), 46 deletions(-) create mode 100644 www/nginx/src/opnsense/mvc/app/models/OPNsense/Base/Constraints/NgxUniqueDefaultServerConstraint.php create mode 100644 www/nginx/src/opnsense/mvc/app/models/OPNsense/Nginx/Migrations/M1_24_0.php diff --git a/www/nginx/Makefile b/www/nginx/Makefile index 42b0ebce2..1fa6c45f0 100644 --- a/www/nginx/Makefile +++ b/www/nginx/Makefile @@ -1,6 +1,5 @@ PLUGIN_NAME= nginx -PLUGIN_VERSION= 1.23 -PLUGIN_REVISION= 2 +PLUGIN_VERSION= 1.24 PLUGIN_COMMENT= Nginx HTTP server and reverse proxy PLUGIN_DEPENDS= nginx PLUGIN_MAINTAINER= franz.fabian.94@gmail.com diff --git a/www/nginx/pkg-descr b/www/nginx/pkg-descr index 5dde33a51..4978ddb05 100644 --- a/www/nginx/pkg-descr +++ b/www/nginx/pkg-descr @@ -10,6 +10,11 @@ WWW: https://nginx.org/ Plugin Changelog ================ +1.24 + +* Change all Listen Port directives to Listen Address and migrate the Port data to Addresses +* Add default_server option to HTTP Server + 1.23 * Add custom error pages on a per HTTP server basis (contributed by 8191) diff --git a/www/nginx/src/opnsense/mvc/app/controllers/OPNsense/Nginx/Api/LogsController.php b/www/nginx/src/opnsense/mvc/app/controllers/OPNsense/Nginx/Api/LogsController.php index de4d4cf5b..765c1be82 100644 --- a/www/nginx/src/opnsense/mvc/app/controllers/OPNsense/Nginx/Api/LogsController.php +++ b/www/nginx/src/opnsense/mvc/app/controllers/OPNsense/Nginx/Api/LogsController.php @@ -170,7 +170,7 @@ class LogsController extends ApiControllerBase { $data = []; foreach ($this->nginx->stream_server->iterateItems() as $item) { - $data[] = array('id' => $item->getAttributes()['uuid'], 'port' => (string)$item->listen_port); + $data[] = array('id' => $item->getAttributes()['uuid'], 'port' => (string)$item->listen_address); } return $data; } diff --git a/www/nginx/src/opnsense/mvc/app/controllers/OPNsense/Nginx/Api/SettingsController.php b/www/nginx/src/opnsense/mvc/app/controllers/OPNsense/Nginx/Api/SettingsController.php index 29c56282e..8cc0f4587 100644 --- a/www/nginx/src/opnsense/mvc/app/controllers/OPNsense/Nginx/Api/SettingsController.php +++ b/www/nginx/src/opnsense/mvc/app/controllers/OPNsense/Nginx/Api/SettingsController.php @@ -233,7 +233,7 @@ class SettingsController extends ApiMutableModelControllerBase { return $this->searchBase('http_server', array( 'servername', 'locations', 'root', 'https_only', 'certificate', - 'listen_http_port', 'listen_https_port' + 'listen_http_address', 'listen_https_address', 'default_server' )); } @@ -261,7 +261,7 @@ class SettingsController extends ApiMutableModelControllerBase // stream server public function searchstreamserverAction() { - return $this->searchBase('stream_server', array('description', 'certificate', 'udp', 'listen_port')); + return $this->searchBase('stream_server', array('description', 'certificate', 'udp', 'listen_address')); } public function getstreamserverAction($uuid = null) diff --git a/www/nginx/src/opnsense/mvc/app/controllers/OPNsense/Nginx/forms/httpserver.xml b/www/nginx/src/opnsense/mvc/app/controllers/OPNsense/Nginx/forms/httpserver.xml index f59e1e5f7..2809f56c9 100644 --- a/www/nginx/src/opnsense/mvc/app/controllers/OPNsense/Nginx/forms/httpserver.xml +++ b/www/nginx/src/opnsense/mvc/app/controllers/OPNsense/Nginx/forms/httpserver.xml @@ -1,13 +1,24 @@
- httpserver.listen_http_port - - text + httpserver.listen_http_address + + true + + select_multiple + Enter a list of IP addresses and ports which can be used in nginx listen directives. To listen on a port on all IPs, use for example "80,[::]:80" - httpserver.listen_https_port - - text + httpserver.listen_https_address + + true + + select_multiple + Enter a list of IP addresses and ports which can be used in nginx listen directives. To listen on a port on all IPs, use for example "443,[::]:443" + + + httpserver.default_server + + checkbox httpserver.syslog_targets diff --git a/www/nginx/src/opnsense/mvc/app/controllers/OPNsense/Nginx/forms/streamserver.xml b/www/nginx/src/opnsense/mvc/app/controllers/OPNsense/Nginx/forms/streamserver.xml index b0d524d8c..a76c22e97 100644 --- a/www/nginx/src/opnsense/mvc/app/controllers/OPNsense/Nginx/forms/streamserver.xml +++ b/www/nginx/src/opnsense/mvc/app/controllers/OPNsense/Nginx/forms/streamserver.xml @@ -1,8 +1,11 @@ - streamserver.listen_port - - text + streamserver.listen_address + + true + + select_multiple + Enter a list of IP addresses and ports which can be used in nginx listen directives. To listen on a port on all IPs, use for example "22,[::]:22" streamserver.udp diff --git a/www/nginx/src/opnsense/mvc/app/models/OPNsense/Base/Constraints/NgxUniqueDefaultServerConstraint.php b/www/nginx/src/opnsense/mvc/app/models/OPNsense/Base/Constraints/NgxUniqueDefaultServerConstraint.php new file mode 100644 index 000000000..1b5423465 --- /dev/null +++ b/www/nginx/src/opnsense/mvc/app/models/OPNsense/Base/Constraints/NgxUniqueDefaultServerConstraint.php @@ -0,0 +1,134 @@ +getOption('node'); + if ($node) { + $httpServerNode = $node->getParentNode(); + $defaultServerNode = $httpServerNode->getChild("default_server"); + if (!$this->isEmpty($defaultServerNode)) + { + $myUUID = $httpServerNode->getAttribute("uuid"); + $myListenHTTPAddress = $httpServerNode->getChild("listen_http_address"); + + $httpServersNode = $httpServerNode->getParentNode(); + + $httpServers = $httpServersNode->getChildren(); + + $msg = ""; + foreach ($httpServers as $httpServer) + { + $uuid = $httpServer->getAttribute("uuid"); + if ($uuid != $myUUID) + { + $defaultServerNode = $httpServer->getChild("default_server"); + if (!$this->isEmpty($defaultServerNode)) + { + $listenHTTPAddressNode = $httpServer->getChild("listen_http_address"); + if ($this->compareListenAddresses($myListenHTTPAddress, $listenHTTPAddressNode, $msg)) + { + $validator->appendMessage(new Message( + sprintf(gettext("There can only be one Default Server on each listening address: %s conflict."), $msg), + $attribute + )); + } + } + } + } + } + } + return true; + } + + private function compareListenAddresses($as, $bs, &$msg): bool + { + foreach (explode(",", $as) as $a) + { + list($a_af, $a_ip, $a_port) = $this->extractAFIPPort($a); + foreach (explode(",", $bs) as $b) + { + list($b_af, $b_ip, $b_port) = $this->extractAFIPPort($b); + if ($a_af == $b_af && $a_port == $b_port) + { + if ($a_ip == null || $a_ip == "::" || $b_ip == null || $b_ip == "::" || $a_ip == $b_ip) + { + $msg = "IPv" . $a_af . ": [" . $a_ip . "]:" . $a_port . " and IPv" . $b_af . ": [" . $b_ip . "]:" . $b_port; + return true; + } + } + } + } + return false; + } + private function extractAFIPPort($in): array + { + $af = null; + $ip = null; + $port = null; + if (!strpos($in, ":")) + { + //if only number, then ipv4 port only + $af = 4; + $port = $in; + } + else + { + //extract ip and port + if (preg_match("/(?:([0-9.]+)|\[([0-9a-fA-F:]+)\]):(\d+)/", $in, $parts)); + { + if (strpos($in, "[") === 0) + { + $af = 6; + $ip = inet_ntop(inet_pton($parts[2])); + $port = $parts[3]; + } + else + { + $af = 4; + $ip = long2ip(ip2long($parts[1])); + $port = $parts[3]; + } + } + } + return [$af, $ip, $port]; + } +} diff --git a/www/nginx/src/opnsense/mvc/app/models/OPNsense/Nginx/Migrations/M1_24_0.php b/www/nginx/src/opnsense/mvc/app/models/OPNsense/Nginx/Migrations/M1_24_0.php new file mode 100644 index 000000000..cac938df9 --- /dev/null +++ b/www/nginx/src/opnsense/mvc/app/models/OPNsense/Nginx/Migrations/M1_24_0.php @@ -0,0 +1,59 @@ +getNodeByReference('http_server')->iterateItems() as $http_server) { + if ($http_server->listen_http_port != '') + { + $http_server->listen_http_address = $http_server->listen_http_port . ',[::]:' . $http_server->listen_http_port; + $http_server->listen_http_port = null; + } + if ($http_server->listen_https_port != '') + { + $http_server->listen_https_address = $http_server->listen_https_port . ',[::]:' . $http_server->listen_https_port; + $http_server->listen_https_port = null; + } + } + foreach ($model->getNodeByReference('stream_server')->iterateItems() as $server) { + if ($server->listen_port != '') + { + $server->listen_address = $server->listen_port . ',[::]:' . $server->listen_port; + $server->listen_port = null; + } + } + } +} diff --git a/www/nginx/src/opnsense/mvc/app/models/OPNsense/Nginx/Nginx.xml b/www/nginx/src/opnsense/mvc/app/models/OPNsense/Nginx/Nginx.xml index c5ac1ca22..0bea091e0 100644 --- a/www/nginx/src/opnsense/mvc/app/models/OPNsense/Nginx/Nginx.xml +++ b/www/nginx/src/opnsense/mvc/app/models/OPNsense/Nginx/Nginx.xml @@ -1,6 +1,6 @@ //OPNsense/Nginx - 1.20.1 + 1.24.0 nginx web server, reverse proxy and waf @@ -662,14 +662,34 @@ N Y - + N - 80 - - + Y + 80,[::]:80 + /^(?:(?:(?:\d{1,3}(?:\.\d{1,3}){3})|(?:\[[a-f0-9:]{1,4}(?::[a-f0-9:]{0,4}){1,7}\])):\d+|:?\d+)(?:\s*,\s*(?:(?:(?:\d{1,3}(?:\.\d{1,3}){3})|(?:\[[a-f0-9:]{1,4}(?::[a-f0-9:]{0,4}){1,7}\])):\d+|:?\d+))*$/i + Please provide a valid listen address or port, i.e. 127.0.0.1:8080, [::1]:8080, 8080. + + + NgxUniqueDefaultServerConstraint + + + + N - 443 - + Y + 443,[::]:443 + /^(?:(?:(?:\d{1,3}(?:\.\d{1,3}){3})|(?:\[[a-f0-9:]{1,4}(?::[a-f0-9:]{0,4}){1,7}\])):\d+|:?\d+)(?:\s*,\s*(?:(?:(?:\d{1,3}(?:\.\d{1,3}){3})|(?:\[[a-f0-9:]{1,4}(?::[a-f0-9:]{0,4}){1,7}\])):\d+|:?\d+))*$/i + Please provide a valid listen address or port, i.e. 127.0.0.1:8080, [::1]:8080, 8080. + + + Y + 0 + + + NgxUniqueDefaultServerConstraint + + + 0 Y @@ -894,16 +914,12 @@ - + N - 80 - - - You can only use one server at this port. - UniqueConstraint - - - + Y + /^(?:(?:(?:\d{1,3}(?:\.\d{1,3}){3})|(?:\[[a-f0-9:]{1,4}(?::[a-f0-9:]{0,4}){1,7}\])):\d+|:?\d+)(?:\s*,\s*(?:(?:(?:\d{1,3}(?:\.\d{1,3}){3})|(?:\[[a-f0-9:]{1,4}(?::[a-f0-9:]{0,4}){1,7}\])):\d+|:?\d+))*$/i + Please provide a valid listen address or port, i.e. 127.0.0.1:8080, [::1]:8080, 8080. +