diff --git a/www/nginx/Makefile b/www/nginx/Makefile index 912ab14b3..2b83161c5 100644 --- a/www/nginx/Makefile +++ b/www/nginx/Makefile @@ -1,5 +1,5 @@ PLUGIN_NAME= nginx -PLUGIN_VERSION= 1.15 +PLUGIN_VERSION= 1.16 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 1e77f9370..47cd12a1b 100644 --- a/www/nginx/pkg-descr +++ b/www/nginx/pkg-descr @@ -8,6 +8,10 @@ reuse, SSL offload and HTTP media streaming. Plugin Changelog ================ +1.16 + +* advanced buffering configuration in location (#1575) + 1.15 * add OCSP stapling and verify 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 8a8414cb4..b4b76dd60 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 @@ -242,6 +242,34 @@ true Enter a custom timout between data received from the client after which the connection is closed. + + location.proxy_buffer_size + + text + By default this is the size of one page (4 or 8 Kilobytes). It can be changed. + true + + + location.proxy_buffers_count + + text + true + Count of buffers for a single connection. + + + location.proxy_buffers_size + + text + true + Size of buffers of a single connection + + + location.proxy_busy_buffers_size + + text + true + When this buffer size is reached, nginx will send a part of the response to the client. + location.proxy_send_timeout diff --git a/www/nginx/src/opnsense/mvc/app/models/OPNsense/Base/Constraints/NgxBusyBufferConstraint.php b/www/nginx/src/opnsense/mvc/app/models/OPNsense/Base/Constraints/NgxBusyBufferConstraint.php new file mode 100644 index 000000000..ac100e9f1 --- /dev/null +++ b/www/nginx/src/opnsense/mvc/app/models/OPNsense/Base/Constraints/NgxBusyBufferConstraint.php @@ -0,0 +1,96 @@ +getOption('node'); + if ($node) { + $parentNode = $node->getParentNode(); + if (!$this->isEmpty($node)) { + $proxy_buffer_size_node = $parentNode->proxy_buffer_size; + $proxy_buffers_count_node = $parentNode->proxy_buffers_count; + $proxy_buffers_size_node = $parentNode->proxy_buffers_size; + $proxy_busy_buffers_size_node = $parentNode->proxy_busy_buffers_size; + + if(!$this->isEmpty($proxy_buffers_count_node) && !$this->isEmpty($proxy_buffers_size_node)) { + $proxy_buffers_count_int = intval((string) $proxy_buffers_count_node); + $proxy_buffers_size_int = intval((string) $proxy_buffers_size_node); + + $proxy_buffers_total_minus1_size = ($proxy_buffers_count_int - 1) * $proxy_buffers_size_int; + } + + if (!$this->isEmpty($proxy_busy_buffers_size_node)) { + $proxy_busy_buffers_size = intval((string) $proxy_busy_buffers_size_node); + } + + if (!$this->isEmpty($proxy_buffer_size_node)) { + $proxy_buffer_size_int = intval((string) $proxy_buffer_size_node); + } + + if (isset($proxy_buffers_total_minus1_size) && isset($proxy_busy_buffers_size) && + $proxy_buffers_total_minus1_size < $proxy_busy_buffers_size) { + $validator->appendMessage(new Message( + gettext("Proxy Buffer Size must be less than the size of all Proxy Buffers minus one buffer."), + $attribute, + $this->getOption('name'))); + } + + // nginx: [emerg] "proxy_busy_buffers_size" must be equal to or greater than the maximum of the value of "proxy_buffer_size" and one of the "proxy_buffers" + if (isset($proxy_busy_buffers_size) && isset($proxy_buffers_size_int) && + $proxy_busy_buffers_size < $proxy_buffers_size_int) { + $validator->appendMessage(new Message( + gettext("Proxy Busy Buffers Size must be equal to or greater than the maximum of one of the Proxy Buffers."), + $attribute, + $this->getOption('name'))); + } + + // nginx: [emerg] "proxy_busy_buffers_size" must be equal to or greater than the maximum of the value of "proxy_buffer_size" and one of the "proxy_buffers" + if (isset($proxy_busy_buffers_size) && isset($proxy_buffer_size_int) && + $proxy_busy_buffers_size < $proxy_buffer_size_int) { + $validator->appendMessage(new Message( + gettext("Proxy Busy Buffers Size must be equal to or greater than the maximum of the value of Proxy Buffer Size."), + $attribute, + $this->getOption('name'))); + } + } + } + return true; + } +} 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 aafd17bf6..f6ea27be9 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 @@ -367,6 +367,42 @@ Y 0 + + N + 1 + + + NgxBusyBufferConstraint + + + + + N + 1 + + + NgxBusyBufferConstraint + + + + + N + 1 + + + NgxBusyBufferConstraint + + + + + N + 1 + + + NgxBusyBufferConstraint + + + Y 0 diff --git a/www/nginx/src/opnsense/service/templates/OPNsense/Nginx/location.conf b/www/nginx/src/opnsense/service/templates/OPNsense/Nginx/location.conf index 4ed7e97cb..841da9330 100644 --- a/www/nginx/src/opnsense/service/templates/OPNsense/Nginx/location.conf +++ b/www/nginx/src/opnsense/service/templates/OPNsense/Nginx/location.conf @@ -87,36 +87,45 @@ location {{ location.matchtype }} {{ location.urlpattern }} { fastcgi_param TLS-Protocol $ssl_protocol; fastcgi_param TLS-SNI-Host $ssl_server_name; fastcgi_param TLS-Client-Intercepted $tls_intercepted; -{% if server.zero_rtt == '1' %} +{% if server.zero_rtt == '1' %} fastcgi_param Early-Data $ssl_early_data; -{% endif %} - fastcgi_intercept_errors off; -{% if location.upstream is not defined %} - fastcgi_pass unix:/var/run/php-www.socket; -{% if location.php_override_scriptname is defined and location.php_override_scriptname != '' %} - fastcgi_param SCRIPT_FILENAME $document_root/{{ location.php_override_scriptname }}; -{% else %} - fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; {% endif %} -{% else %} + fastcgi_intercept_errors off; +{% if location.upstream is not defined %} + fastcgi_pass unix:/var/run/php-www.socket; +{% if location.php_override_scriptname is defined and location.php_override_scriptname != '' %} + fastcgi_param SCRIPT_FILENAME $document_root/{{ location.php_override_scriptname }}; +{% else %} + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; +{% endif %} +{% else %} fastcgi_pass upstream{{ location.upstream.replace('-','') }}; fastcgi_connect_timeout 10s; -{% if location.php_override_scriptname is defined and location.php_override_scriptname != '' %} +{% if location.php_override_scriptname is defined and location.php_override_scriptname != '' %} fastcgi_param SCRIPT_FILENAME {{ location.php_override_scriptname }}; -{% else %} +{% else %} fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; +{% endif %} {% endif %} -{% endif %} {% endif%} {% if location.upstream is defined and (location.php_enable is not defined or location.php_enable != '1') %} -{% set upstream = helpers.getUUID(location.upstream) %} +{% set upstream = helpers.getUUID(location.upstream) %} proxy_set_header Host $host; -{% if location.websocket is defined and location.websocket == '1' %} +{% if location.websocket is defined and location.websocket == '1' %} proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; -{% endif %} -{% if location.cache_path is defined and location.cache_path != '' %} +{% endif %} +{% if location.proxy_buffer_size is defined and location.proxy_buffer_size != '' %} + proxy_buffer_size {{ location.proxy_buffer_size }}k; +{% endif %} +{% if location.proxy_buffers_count is defined and location.proxy_buffers_count != '' and location.proxy_buffers_size is defined and location.proxy_buffers_size != '' %} + proxy_buffers {{ location.proxy_buffers_count }} {{ location.proxy_buffers_size }}k; +{% endif %} +{% if location.proxy_busy_buffers_size is defined and location.proxy_busy_buffers_size != '' %} + proxy_busy_buffers_size {{ location.proxy_busy_buffers_size }}k; +{% endif %} +{% if location.cache_path is defined and location.cache_path != '' %} proxy_cache {{ location.cache_path.replace('-', '') }}; {% if location.cache_use_stale is defined and location.cache_use_stale != '' %} proxy_cache_use_stale {{ location.cache_use_stale.replace(',', ' ') }}; @@ -131,35 +140,35 @@ location {{ location.matchtype }} {{ location.urlpattern }} { proxy_set_header X-TLS-Protocol $ssl_protocol; proxy_set_header X-TLS-SNI-Host $ssl_server_name; # proxy headers for backend server -{% if server.verify_client != 'off' %} +{% if server.verify_client != 'off' %} proxy_set_header X-Client-Dn $ssl_client_s_dn; proxy_set_header X-Client-Verify $ssl_client_verify; -{% endif %} -{% if server.verify_client == 'optional_no_ca' %} +{% endif %} +{% if server.verify_client == 'optional_no_ca' %} proxy_set_header X-Client-Certificate $ssl_client_escaped_cert; -{% endif %} -{% if server.zero_rtt == '1' %} +{% endif %} +{% if server.zero_rtt == '1' %} proxy_set_header Early-Data $ssl_early_data; -{% endif %} +{% endif %} proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-TLS-Client-Intercepted $tls_intercepted; -{% if location.proxy_read_timeout is defined and location.proxy_read_timeout != '' %} +{% if location.proxy_read_timeout is defined and location.proxy_read_timeout != '' %} proxy_read_timeout {{ location.proxy_read_timeout }}s; -{% endif %} -{% if location.proxy_send_timeout is defined and location.proxy_send_timeout != '' %} +{% endif %} +{% if location.proxy_send_timeout is defined and location.proxy_send_timeout != '' %} proxy_send_timeout {{ location.proxy_send_timeout }}s; -{% endif %} +{% endif %} proxy_ignore_client_abort {% if location.proxy_ignore_client_abort == '1' %}on{% else %}off{% endif %}; proxy_request_buffering {% if location.proxy_request_buffering == '1' %}on{% else %}off{% endif %}; proxy_max_temp_file_size {% if location.proxy_max_temp_file_size is defined %}{{ location.proxy_max_temp_file_size }}{% else %}1024{% endif %}m; proxy_buffering {% if location.proxy_buffering == '1' %}on{% else %}off{% endif %}; -{% if location.path_prefix is defined and location.path_prefix != '' %} +{% if location.path_prefix is defined and location.path_prefix != '' %} proxy_pass http{% if upstream.tls_enable == '1' %}s{% endif %}://upstream{{ location.upstream.replace('-','') }}{{ location.path_prefix }}; -{% else %} +{% else %} proxy_pass http{% if upstream.tls_enable == '1' %}s{% endif %}://upstream{{ location.upstream.replace('-','') }}; -{% endif %} +{% endif %} {% if upstream.tls_enable == '1' %} {% if upstream.tls_client_certificate is defined and upstream.tls_client_certificate != '' %} proxy_ssl_certificate_key /usr/local/etc/nginx/key/{{ upstream.tls_client_certificate }}.key; @@ -190,6 +199,6 @@ location {{ location.matchtype }} {{ location.urlpattern }} { proxy_hide_header {{ our_header }}; {% endfor %} {% endif %} -{% endif %} +{% endif %}{# honeypot #} }