From 107a7f40e36d4b46cbf180e7bcc69d2d2a883477 Mon Sep 17 00:00:00 2001 From: Franco Fichtner Date: Tue, 11 Dec 2018 12:51:21 +0100 Subject: [PATCH] www/nginx: version 1.5 --- www/nginx/Makefile | 2 +- www/nginx/pkg-descr | 29 ++ .../OPNsense/Nginx/Api/LogsController.php | 47 ++- .../OPNsense/Nginx/Api/SettingsController.php | 230 +++++++++++++ .../OPNsense/Nginx/IndexController.php | 5 +- .../OPNsense/Nginx/forms/httpserver.xml | 60 ++++ .../OPNsense/Nginx/forms/ipacl.xml | 19 ++ .../OPNsense/Nginx/forms/location.xml | 59 +++- .../OPNsense/Nginx/forms/sni_hostname_map.xml | 14 + .../OPNsense/Nginx/forms/streamserver.xml | 76 +++++ .../OPNsense/Nginx/forms/upstream.xml | 7 + .../OPNsense/Nginx/StreamAccessLogLine.php | 39 +++ .../OPNsense/Nginx/StreamAccessLogParser.php | 63 ++++ .../mvc/app/models/OPNsense/Nginx/Nginx.php | 31 ++ .../mvc/app/models/OPNsense/Nginx/Nginx.xml | 322 +++++++++++++++++- .../mvc/app/views/OPNsense/Nginx/index.volt | 274 +++++++++------ .../mvc/app/views/OPNsense/Nginx/logs.volt | 2 +- .../opnsense/scripts/nginx/ngx_autoblock.php | 25 +- .../src/opnsense/scripts/nginx/read_log.php | 94 +++-- .../src/opnsense/scripts/nginx/setup.php | 125 ++++--- .../service/templates/OPNsense/Nginx/+TARGETS | 1 + .../templates/OPNsense/Nginx/http.conf | 34 +- .../templates/OPNsense/Nginx/ipacl.conf | 15 + .../templates/OPNsense/Nginx/location.conf | 19 ++ .../templates/OPNsense/Nginx/naxsirule.conf | 4 + .../templates/OPNsense/Nginx/newsyslog.conf | 5 + .../templates/OPNsense/Nginx/nginx.conf | 6 +- .../OPNsense/Nginx/security_rule.conf | 8 + .../templates/OPNsense/Nginx/streams.conf | 95 ++++++ .../src/opnsense/www/js/nginx/dist/bundle.js | 1 - .../www/js/nginx/dist/configuration.min.js | 1 + .../www/js/nginx/dist/logviewer.min.js | 1 + .../src/opnsense/www/js/nginx/src/config.js | 12 +- .../nginx/src/controller/KeyValueMapField.js | 50 +++ .../src/controller/KeyValueMapFieldEntry.js | 152 +++++++++ .../www/js/nginx/src/controller/LogView.js | 20 +- .../js/nginx/src/models/IPACLCollection.js | 15 + .../www/js/nginx/src/models/IPACLModel.js | 3 + .../js/nginx/src/models/LogLinesCollection.js | 6 + .../models/SNIHostnameUpstreamCollection.js | 15 + .../src/models/SNIHostnameUpstreamModel.js | 3 + .../js/nginx/src/models/UpstreamCollection.js | 7 + .../opnsense/www/js/nginx/src/nginx_config.js | 151 ++++++++ .../src/templates/StreamAccessLogLine.html | 6 + .../js/nginx/src/templates/TabCollection.html | 2 +- .../www/js/nginx/src/templates/TabModel.html | 2 +- .../www/js/nginx/src/templates/logviewer.html | 22 +- .../nginx/src/templates/noDataAvailable.html | 3 + .../src/opnsense/www/js/nginx/webpack.conf.js | 7 +- 49 files changed, 1968 insertions(+), 221 deletions(-) create mode 100644 www/nginx/src/opnsense/mvc/app/controllers/OPNsense/Nginx/forms/ipacl.xml create mode 100644 www/nginx/src/opnsense/mvc/app/controllers/OPNsense/Nginx/forms/sni_hostname_map.xml create mode 100644 www/nginx/src/opnsense/mvc/app/controllers/OPNsense/Nginx/forms/streamserver.xml create mode 100644 www/nginx/src/opnsense/mvc/app/library/OPNsense/Nginx/StreamAccessLogLine.php create mode 100644 www/nginx/src/opnsense/mvc/app/library/OPNsense/Nginx/StreamAccessLogParser.php create mode 100644 www/nginx/src/opnsense/service/templates/OPNsense/Nginx/ipacl.conf create mode 100644 www/nginx/src/opnsense/service/templates/OPNsense/Nginx/newsyslog.conf create mode 100644 www/nginx/src/opnsense/service/templates/OPNsense/Nginx/streams.conf delete mode 100644 www/nginx/src/opnsense/www/js/nginx/dist/bundle.js create mode 100644 www/nginx/src/opnsense/www/js/nginx/dist/configuration.min.js create mode 100644 www/nginx/src/opnsense/www/js/nginx/dist/logviewer.min.js create mode 100644 www/nginx/src/opnsense/www/js/nginx/src/controller/KeyValueMapField.js create mode 100644 www/nginx/src/opnsense/www/js/nginx/src/controller/KeyValueMapFieldEntry.js create mode 100644 www/nginx/src/opnsense/www/js/nginx/src/models/IPACLCollection.js create mode 100644 www/nginx/src/opnsense/www/js/nginx/src/models/IPACLModel.js create mode 100644 www/nginx/src/opnsense/www/js/nginx/src/models/SNIHostnameUpstreamCollection.js create mode 100644 www/nginx/src/opnsense/www/js/nginx/src/models/SNIHostnameUpstreamModel.js create mode 100644 www/nginx/src/opnsense/www/js/nginx/src/models/UpstreamCollection.js create mode 100644 www/nginx/src/opnsense/www/js/nginx/src/nginx_config.js create mode 100644 www/nginx/src/opnsense/www/js/nginx/src/templates/StreamAccessLogLine.html create mode 100644 www/nginx/src/opnsense/www/js/nginx/src/templates/noDataAvailable.html diff --git a/www/nginx/Makefile b/www/nginx/Makefile index 8c403128c..d55c1c9f4 100644 --- a/www/nginx/Makefile +++ b/www/nginx/Makefile @@ -1,5 +1,5 @@ PLUGIN_NAME= nginx -PLUGIN_VERSION= 1.3 +PLUGIN_VERSION= 1.5 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 fe7205cec..958626fdd 100644 --- a/www/nginx/pkg-descr +++ b/www/nginx/pkg-descr @@ -8,6 +8,35 @@ reuse, SSL offload and HTTP media streaming. Plugin Changelog ================ +1.5 + +* Add proxy options for ignore client abort and disabling buffering +* Add logviewer support for streams +* Fix charset is not defined bug (contributed by ccesario [1]) +* Add an existence check for locations +* Add PROXY protocol for HTTP and Streams frontend +* Add PROXY backend support for Streams +* Add support for better whitelist rules in the WAF + +[1] https://github.com/opnsense/plugins/pull/1035 + +1.4 (Development only) + +* move upstreams from HTTP to their own menu because they are used for TCP load balancing as well +* add TCP load balancing [1] +* add support for IP based ACLs +* add log rotation (contributed by Julius Cesar Camargo [2]) +* add support for satisfy, body size limitation +* change: allow to disable internal bot protection (contributed by @fzoske) [3] +* change: do not save when no change in the list happened to prevent filling the log history +* fix: translate a german string in upstream server to english +* replace headers instead of just adding our own (duplication issue #971), suppress X-Powered-By from Upstream [4] + +[1] https://github.com/opnsense/plugins/pull/930 +[2] https://github.com/opnsense/plugins/pull/982 +[3] https://github.com/opnsense/plugins/pull/934 +[4] https://github.com/opnsense/plugins/issues/971 + 1.3 * bugfix: correctly set upstream header 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 00de73e5f..dbbee6481 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 @@ -57,6 +57,28 @@ class LogsController extends ApiControllerBase return $this->call_configd('error', $uuid); } } + public function stream_accessesAction($uuid = null) + { + $this->nginx = new Nginx(); + if (!isset($uuid)) { + // emulate REST API -> /stream_accesses delivers a list of servers with access logs + return $this->list_streams(); + } else { + // emulate REST call for a specific log /stream_accesses/uuid + return $this->call_configd_stream('streamaccess', $uuid); + } + } + public function stream_errorsAction($uuid = null) + { + $this->nginx = new Nginx(); + if (!isset($uuid)) { + // emulate REST API -> /stream_errors delivers a list of servers with error logs + return $this->list_streams(); + } else { + // emulate REST call for a specific log /stream_errors/uuid + return $this->call_configd_stream('streamerror', $uuid); + } + } private function call_configd($type, $uuid) { @@ -68,19 +90,42 @@ class LogsController extends ApiControllerBase $data = $backend->configdRun('nginx log ' . $type . ' ' . $uuid); return json_decode($data, true); } + private function call_configd_stream($type, $uuid) + { + if (!$this->stream_exists($uuid)) { + $this->response->setStatusCode(404, "Not Found"); + } + + $backend = new Backend(); + $data = $backend->configdRun('nginx log ' . $type . ' ' . $uuid); + return json_decode($data, true); + } private function list_vhosts() { $data = []; - foreach ($this->nginx->http_server->__items as $item) { + foreach ($this->nginx->http_server->iterateItems() as $item) { $data[] = array('id' => $item->getAttributes()['uuid'], 'server_name' => (string)$item->servername); } return $data; } + private function list_streams() + { + $data = []; + foreach ($this->nginx->stream_server->iterateItems() as $item) { + $data[] = array('id' => $item->getAttributes()['uuid'], 'port' => (string)$item->listen_port); + } + return $data; + } private function vhost_exists($uuid) { $data = $this->nginx->getNodeByReference('http_server.'. $uuid); return isset($data); } + private function stream_exists($uuid) + { + $data = $this->nginx->getNodeByReference('stream_server.'. $uuid); + return isset($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 aefcc98de..1c93711db 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 @@ -236,6 +236,33 @@ class SettingsController extends ApiMutableModelControllerBase return $this->setBase('httpserver', 'http_server', $uuid); } + // stream server + public function searchstreamserverAction() + { + return $this->searchBase('stream_server', array('description', 'certificate', 'udp', 'listen_port')); + } + + public function getstreamserverAction($uuid = null) + { + $this->sessionClose(); + return $this->getBase('streamserver', 'stream_server', $uuid); + } + + public function addstreamserverAction() + { + return $this->addBase('streamserver', 'stream_server'); + } + + public function delstreamserverAction($uuid) + { + return $this->delBase('stream_server', $uuid); + } + + public function setstreamserverAction($uuid) + { + return $this->setBase('streamserver', 'stream_server', $uuid); + } + // naxsi rules public function searchnaxsiruleAction() { @@ -405,4 +432,207 @@ class SettingsController extends ApiMutableModelControllerBase { return $this->setBase('cache_path', 'cache_path', $uuid); } + + // SNI Forward + public function searchsnifwdAction() + { + return $this->searchBase('sni_hostname_upstream_map', array('description')); + } + + public function getsnifwdAction($uuid = null) + { + $this->sessionClose(); + $base = $this->getBase('snihostname', 'sni_hostname_upstream_map', $uuid); + return $this->convert_sni_fwd_for_client($base); + } + + public function addsnifwdAction() + { + if ($this->request->isPost()) { + $this->regenerate_hostname_map(null); + return $this->addBase('snihostname', 'sni_hostname_upstream_map'); + } + return []; + } + + public function delsnifwdAction($uuid) + { + $nginx = $this->getModel(); + $uuid_attached = $nginx->find_sni_hostname_upstream_map_entry_uuids($uuid); + + $ret = $this->delBase('sni_hostname_upstream_map', $uuid); + if ($ret['result'] == 'deleted') { + foreach ($uuid_attached as $old_uuid) { + $this->delBase('sni_hostname_upstream_map_item', $old_uuid); + } + } + return $ret; + } + + public function setsnifwdAction($uuid) + { + if ($this->request->isPost()) { + $this->regenerate_hostname_map($uuid); + return $this->setBase('snihostname', 'sni_hostname_upstream_map', $uuid); + } + return []; + } + // IP / Network based ACLs + public function searchipaclAction() + { + return $this->searchBase('ip_acl', array('description')); + } + + public function getipaclAction($uuid = null) + { + $this->sessionClose(); + $base = $this->getBase('ipacl', 'ip_acl', $uuid); + return $this->convert_ipacl_for_client($base); + } + + public function addipaclAction() + { + if ($this->request->isPost()) { + $this->regenerate_ipacl(null); + return $this->addBase('ipacl', 'ip_acl'); + } + return []; + } + + public function delipaclAction($uuid) + { + $nginx = $this->getModel(); + $uuid_attached = $nginx->find_ip_acl_entry_uuids($uuid); + + $ret = $this->delBase('ip_acl', $uuid); + if ($ret['result'] == 'deleted') { + foreach ($uuid_attached as $old_uuid) { + $this->delBase('ip_acl_item', $old_uuid); + } + } + return $ret; + } + + public function setipaclAction($uuid) + { + if ($this->request->isPost()) { + $this->regenerate_ipacl($uuid); + return $this->setBase('ipacl', 'ip_acl', $uuid); + } + return []; + } + /* + * worker code starts here + */ + + private function convert_sni_fwd_for_client($response_data) + { + if (!isset($response_data['snihostname']['data'])) { + return $response_data; + } + $nginx = $this->getModel(); + $uuids_map = explode(',', $response_data['snihostname']['data']); + $response_data['snihostname']['data'] = []; + foreach ($uuids_map as $uuid_line) { + $rowdata = $nginx->getNodeByReference('sni_hostname_upstream_map_item.' . $uuid_line); + if ($rowdata != null) { + $response_data['snihostname']['data'][] = + array('hostname' => (string)$rowdata->hostname, + 'upstream' => (string)$rowdata->upstream); + } + } + return $response_data; + } + private function convert_ipacl_for_client($response_data) + { + if (!isset($response_data['ipacl']['data'])) { + return $response_data; + } + $nginx = $this->getModel(); + $uuids_map = explode(',', $response_data['ipacl']['data']); + $response_data['ipacl']['data'] = []; + foreach ($uuids_map as $uuid_line) { + $rowdata = $nginx->getNodeByReference('ip_acl_item.' . $uuid_line); + if ($rowdata != null) { + $response_data['ipacl']['data'][] = + array('network' => (string)$rowdata->network, + 'action' => (string)$rowdata->action); + } + } + return $response_data; + } + + /** + * @param null $uuid the uuid which should get cleared before + * @throws \ReflectionException if the model was not found + * @throws \Phalcon\Validation\Exception on validation errors + */ + private function regenerate_hostname_map($uuid = null) + { + $nginx = $this->getModel(); + if ($this->request->hasPost('snihostname') && is_array($_POST['snihostname']['data'])) { + if ($uuid != null) { + // for an update, we have to clear it. + $this->delete_uuids( + $nginx->find_sni_hostname_upstream_map_entry_uuids($uuid), + 'sni_hostname_upstream_map_item' + ); + } + $ids = []; + $postdata = $_POST['snihostname']['data']; + foreach ($postdata as $post_item) { + $item = $nginx->sni_hostname_upstream_map_item->Add(); + $ids[] = $item->getAttributes()['uuid']; + $item->hostname = $post_item['hostname']; + $item->upstream = $post_item['upstream']; + } + $nginx->serializeToConfig(); + $_POST['snihostname']['data'] = implode(',', $ids); + } + } + + /** + * @param null $uuid the uuid which should get cleared before + * @throws \ReflectionException if the model was not found + * @throws \Phalcon\Validation\Exception on validation errors + */ + private function regenerate_ipacl($uuid = null) + { + $nginx = $this->getModel(); + if ($this->request->hasPost('ipacl') && is_array($_POST['ipacl']['data'])) { + if ($uuid != null) { + // for an update, we have to clear it. + $this->delete_uuids( + $nginx->find_ip_acl_uuids($uuid), + 'ip_acl_item' + ); + } + $ids = []; + $postdata = $_POST['ipacl']['data']; + foreach ($postdata as $post_item) { + $item = $nginx->ip_acl_item->Add(); + $ids[] = $item->getAttributes()['uuid']; + $item->network = $post_item['network']; + $item->action = $post_item['action']; + } + $nginx->serializeToConfig(); + $_POST['ipacl']['data'] = implode(',', $ids); + } + } + + /** + * @param $uuids array list of UUIDs + * @param $path string the model prefix from the element to delete + * @throws \Phalcon\Validation\Exception + */ + private function delete_uuids($uuids, $path): void + { + foreach ($uuids as $item_uuid) { + try { + $this->delBase($path, $item_uuid); + } catch (\Exception $e) { + // we don't care about then. + } + } + } } diff --git a/www/nginx/src/opnsense/mvc/app/controllers/OPNsense/Nginx/IndexController.php b/www/nginx/src/opnsense/mvc/app/controllers/OPNsense/Nginx/IndexController.php index 257d51da8..e3782a706 100644 --- a/www/nginx/src/opnsense/mvc/app/controllers/OPNsense/Nginx/IndexController.php +++ b/www/nginx/src/opnsense/mvc/app/controllers/OPNsense/Nginx/IndexController.php @@ -50,6 +50,7 @@ class IndexController extends \OPNsense\Base\IndexController $this->view->credential = $this->getForm("credential"); $this->view->userlist = $this->getForm("userlist"); $this->view->httpserver = $this->getForm("httpserver"); + $this->view->streamserver = $this->getForm("streamserver"); $this->view->httprewrite = $this->getForm("httprewrite"); $this->view->naxsi_rule = $this->getForm("naxsi_rule"); $this->view->naxsi_custom_policy = $this->getForm("naxsi_custom_policy"); @@ -57,9 +58,11 @@ class IndexController extends \OPNsense\Base\IndexController $this->view->limit_request_connection = $this->getForm("limit_request_connection"); $this->view->limit_zone = $this->getForm("limit_zone"); $this->view->cache_path = $this->getForm("cache_path"); + $this->view->sni_hostname_map = $this->getForm("sni_hostname_map"); + $this->view->ipacl = $this->getForm("ipacl"); $nginx = new Nginx(); $this->view->show_naxsi_download_button = - count($nginx->custom_policy->__items) == 0 && count($nginx->naxsi_rule->__items) == 0; + count($nginx->custom_policy->iterateItems()) == 0 && count($nginx->naxsi_rule->iterateItems()) == 0; $this->view->pick('OPNsense/Nginx/index'); } 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 3a213f715..50282f3d5 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 @@ -9,6 +9,30 @@ text + + httpserver.proxy_protocol + + checkbox + true + If you enable the proxy protocol, a downstream proxy can send the client IP and port before the real traffic is set. + + + httpserver.trusted_proxies + + true + + select_multiple + true + Enter a list of IP addresses or CIDR networks which are allowed to override the source IP address using the specified header. + + + httpserver.real_ip_source + + + true + X-Real-IP and X-Forwarded-For are HTTP headers, while PROXY protocol is a protocol which needs to be enabled. + dropdown + httpserver.servername @@ -34,6 +58,20 @@ text + + httpserver.max_body_size + + text + true + If the request is larger, it will be rejectet with error 413 (Request Entity Too Large). For example, you can enter 200m. + + + httpserver.body_buffer_size + + text + true + If the request exceeds this size, it will be written to disk. Enter a number and a unit like 1m. + httpserver.certificate @@ -79,6 +117,28 @@ true Blocks files like .htaccess files or other files not intended for the public. + + httpserver.disable_bot_protection + + checkbox + true + Blocks the request when a possibly bad bot is detected and adds the originating IP to the managed firewall alias for permanent blocking. + + + httpserver.ip_acl + + dropdown + + If you select an IP ACL, the client can only access this service if it fulfills this requirement. + + + httpserver.satisfy + + dropdown + true + + All: All access restrictions must be fulfilled; Any: Any of the access restrictions must be fulfilled. + httpserver.naxsi_extensive_log diff --git a/www/nginx/src/opnsense/mvc/app/controllers/OPNsense/Nginx/forms/ipacl.xml b/www/nginx/src/opnsense/mvc/app/controllers/OPNsense/Nginx/forms/ipacl.xml new file mode 100644 index 000000000..c1cd23adf --- /dev/null +++ b/www/nginx/src/opnsense/mvc/app/controllers/OPNsense/Nginx/forms/ipacl.xml @@ -0,0 +1,19 @@ +
+ + ipacl.description + + text + Enter a short description like a name for this ACL. It will be shown in the drop downs. + + + ipacl.data + + + hidden + + + ipacl.default_action + + dropdown + +
diff --git a/www/nginx/src/opnsense/mvc/app/controllers/OPNsense/Nginx/forms/location.xml b/www/nginx/src/opnsense/mvc/app/controllers/OPNsense/Nginx/forms/location.xml index 4ebd04b20..70f4572eb 100644 --- a/www/nginx/src/opnsense/mvc/app/controllers/OPNsense/Nginx/forms/location.xml +++ b/www/nginx/src/opnsense/mvc/app/controllers/OPNsense/Nginx/forms/location.xml @@ -131,10 +131,26 @@ text Enter the file system root from which the files are served.
+ + location.max_body_size + + text + true + If the request is larger, it will be rejectet with error 413 (Request Entity Too Large). For example, you can enter 200m. + + + location.body_buffer_size + + text + true + If the request exceeds this size, it will be written to disk. Enter a number and a unit like 1m. + location.index select_multiple + true + Enter a list of file extensions, which are served instead of a directory. It is common to use index.html or index.php here. @@ -161,6 +177,21 @@ checkbox Send an authentication request to the OPNsense backend for advanced access control. + + location.ip_acl + + dropdown + + If you select an IP ACL, the client can only access this service if it fulfills this requirement. + + + location.satisfy + + dropdown + + true + All: All access restrictions must be fulfilled; Any: Any of the access restrictions must be fulfilled. + location.force_https @@ -192,11 +223,37 @@ true If you enable the honeypot, all requests to this location will go to a special temporary log which will be used to block the IP. This is dangerous because you may accidentally block legitimate users or search engines. The result is available as a special alias in the firewall section. For example you can trigger on locations of Wordpress for phpMyAdmin if you are not using it. + + header + + true + location.websocket - + + checkbox + true + If you enable the WebSocket Support option, nginx will pass the upgrade header to the backed server. + + + location.proxy_buffering + + checkbox + true + If you enable the Response Buffering option, nginx will buffer response from the backed server. + + + location.proxy_request_buffering + checkbox true If you enable the WebSocket option, nginx will pass the upgrade header to the backed server. + + location.proxy_ignore_client_abort + + checkbox + true + If you enable this option, nginx will not terminate the connection to the backend server if the client connection is terminated. + diff --git a/www/nginx/src/opnsense/mvc/app/controllers/OPNsense/Nginx/forms/sni_hostname_map.xml b/www/nginx/src/opnsense/mvc/app/controllers/OPNsense/Nginx/forms/sni_hostname_map.xml new file mode 100644 index 000000000..0e27c51b4 --- /dev/null +++ b/www/nginx/src/opnsense/mvc/app/controllers/OPNsense/Nginx/forms/sni_hostname_map.xml @@ -0,0 +1,14 @@ +
+ + snihostname.description + + text + Enter a short description like a name for this redirect. + + + snihostname.data + + + hidden + +
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 new file mode 100644 index 000000000..e2f6044b0 --- /dev/null +++ b/www/nginx/src/opnsense/mvc/app/controllers/OPNsense/Nginx/forms/streamserver.xml @@ -0,0 +1,76 @@ +
+ + streamserver.listen_port + + text + + + streamserver.udp + + checkbox + + + streamserver.proxy_protocol + + checkbox + If you enable the proxy protocol, a downstream proxy can send the client IP and port before the real traffic is set. + + + httpserver.trusted_proxies + + true + + select_multiple + true + Enter a list of IP addresses or CIDR networks which are allowed to override the source IP address using the specified header. + + + streamserver.certificate + + dropdown + + + streamserver.ca + + dropdown + + + streamserver.verify_client + + dropdown + true +
  • On: the certificate is requested and validated. Use this option to protect a service with TLS authentication.
  • Off: The certificate is not requested. Choose this option for a normal website.
  • Optional: The certificate is requested and validated if existing. Choose this option for websites, with TLS login support or mixed TLS protected API and web content.
  • Optional, don't verify: Do accept the certificate and let the application choose what to do. Choose this option, for the same reasons as optional but in this case, the request is passed to the backend without rejecting untrusted certificates.
  • ]]>
    +
    + + streamserver.access_log_format + + dropdown + + + streamserver.route_field + + dropdown + + + + streamserver.upstream + + dropdown + + Select an upstream to proxy to. + + + streamserver.sni_upstream_map + + dropdown + + Select an upstream map to choose the host based on the name given by the client. + + + streamserver.ip_acl + + dropdown + + If you select an IP ACL, the client can only access this service if it fulfills this requirement. + +
    diff --git a/www/nginx/src/opnsense/mvc/app/controllers/OPNsense/Nginx/forms/upstream.xml b/www/nginx/src/opnsense/mvc/app/controllers/OPNsense/Nginx/forms/upstream.xml index f2303d759..091431302 100644 --- a/www/nginx/src/opnsense/mvc/app/controllers/OPNsense/Nginx/forms/upstream.xml +++ b/www/nginx/src/opnsense/mvc/app/controllers/OPNsense/Nginx/forms/upstream.xml @@ -10,6 +10,13 @@ select_multiple + + upstream.proxy_protocol + + checkbox + true + If you enable the proxy protocol, an upstream proxy or server will get the client IP and the server port before the real traffic is sent. + upstream.tls_enable diff --git a/www/nginx/src/opnsense/mvc/app/library/OPNsense/Nginx/StreamAccessLogLine.php b/www/nginx/src/opnsense/mvc/app/library/OPNsense/Nginx/StreamAccessLogLine.php new file mode 100644 index 000000000..db58bb5e3 --- /dev/null +++ b/www/nginx/src/opnsense/mvc/app/library/OPNsense/Nginx/StreamAccessLogLine.php @@ -0,0 +1,39 @@ +file_name = $file_name; + $this->lines = file($this->file_name); + $this->result = array_map([$this, 'parse_line'], $this->lines); + } + private function parse_line($line) + { + $container = new StreamAccessLogLine(); + if (preg_match(self::LogLineRegex, $line, $data)) { + $container->remote_ip = $data[1]; + $container->time = $data[2]; + $container->status = $data[3]; + $container->bytes_sent = $data[4]; + $container->bytes_received = $data[5]; + $container->session_time = $data[6]; + } + return $container; + } + + public function get_result() + { + return $this->result; + } +} diff --git a/www/nginx/src/opnsense/mvc/app/models/OPNsense/Nginx/Nginx.php b/www/nginx/src/opnsense/mvc/app/models/OPNsense/Nginx/Nginx.php index cfed5580e..5453074b4 100644 --- a/www/nginx/src/opnsense/mvc/app/models/OPNsense/Nginx/Nginx.php +++ b/www/nginx/src/opnsense/mvc/app/models/OPNsense/Nginx/Nginx.php @@ -31,4 +31,35 @@ use OPNsense\Base\BaseModel; class Nginx extends BaseModel { + /** + * @param $uuid string UUID of sni_hostname_upstream_map + * @return array list of UUIDs + */ + function find_sni_hostname_upstream_map_entry_uuids($uuid) + { + return $this->find_x_uuids($uuid, 'sni_hostname_upstream_map.'); + } + + /** + * @param $uuid string UUID of sni_hostname_upstream_map + * @return array list of UUIDs + */ + function find_ip_acl_uuids($uuid) + { + return $this->find_x_uuids($uuid, 'ip_acl.'); + } + + private function find_x_uuids($uuid, $prefix) + { + $tmp = $this->getNodeByReference($prefix . $uuid); + if ($tmp == null) { + return []; + } + $tmp = (string)$tmp->data; + if (empty($tmp)) { + return []; + } + + return explode(',', $tmp); + } } 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 1b97ad26a..8b7e3b827 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.1.2 + 1.5.0 nginx web server, reverse proxy and waf @@ -74,6 +74,10 @@ Y Y + + 0 + Y + Y 0 @@ -300,9 +304,9 @@ name - Selected server not found + Selected user file not found N - Y + N 0 @@ -330,6 +334,16 @@ N Y + + N + /^\d+[kmg]$/i + Enter a number followed by k, m or g. + + + N + /^\d+[kmg]$/i + Enter a number followed by k, m or g. + Y 0 @@ -338,10 +352,41 @@ Y 0 + + Y + 0 + + + Y + 1 + + + Y + 1 + Y 0 + + + + + Selected ACL not found + N + N + + + + Any + All + + N + @@ -398,8 +443,16 @@ Y - Y + N /^[^"]+$/ + + + This field must be set. + SetIfConstraint + match_type + id + + Y @@ -414,8 +467,16 @@ /^[^"]+$/ - Y + N /^[^"]+$/ + + + This field must be set. + SetIfConstraint + match_type + id + + Y @@ -429,8 +490,16 @@ Y - Y + N 8 + + + This field must be set. + SetIfConstraint + match_type + id + + Y @@ -473,6 +542,23 @@ N 443 + + 0 + Y + + + N + /^((?:\d+\.){3,3}\d+|[a-f0-9\:]+)(?:\/\d+)?(,?(?:(?:(\d+\.){3,3}\d+|[a-f0-9\:]+)(?:\/\d+)?))*$/i + Y + + + + X-Real-IP (default) + X-Forwarded-For + PROXY Protocol + + N +