127 lines
4.9 KiB
Diff
127 lines
4.9 KiB
Diff
From edb82a3e2388938f6230731e1f50e98fbde5f83f Mon Sep 17 00:00:00 2001
|
|
From: Maxim Dounin <mdounin@mdounin.ru>
|
|
Date: Fri, 24 May 2024 00:20:01 +0300
|
|
Subject: [PATCH] Added max_headers directive.
|
|
|
|
The directive limits the number of request headers accepted from clients.
|
|
While the total amount of headers is believed to be sufficiently limited
|
|
by the existing buffer size limits (client_header_buffer_size and
|
|
large_client_header_buffers), the additional limit on the number of headers
|
|
might be beneficial to better protect backend servers.
|
|
|
|
Requested by Maksim Yevmenkin.
|
|
|
|
Signed-off-by: Elijah Zupancic <e.zupancic@f5.com>
|
|
Origin: <https://freenginx.org/hg/nginx/rev/199dc0d6b05be814b5c811876c20af58cd361fea>
|
|
---
|
|
src/http/ngx_http_core_module.c | 10 ++++++++++
|
|
src/http/ngx_http_core_module.h | 2 ++
|
|
src/http/ngx_http_request.c | 9 +++++++++
|
|
src/http/ngx_http_request.h | 1 +
|
|
src/http/v2/ngx_http_v2.c | 9 +++++++++
|
|
5 files changed, 31 insertions(+)
|
|
|
|
diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c
|
|
index 6664fa6..2516331 100644
|
|
--- a/src/http/ngx_http_core_module.c
|
|
+++ b/src/http/ngx_http_core_module.c
|
|
@@ -252,6 +252,13 @@ static ngx_command_t ngx_http_core_commands[] = {
|
|
offsetof(ngx_http_core_srv_conf_t, large_client_header_buffers),
|
|
NULL },
|
|
|
|
+ { ngx_string("max_headers"),
|
|
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
|
|
+ ngx_conf_set_num_slot,
|
|
+ NGX_HTTP_SRV_CONF_OFFSET,
|
|
+ offsetof(ngx_http_core_srv_conf_t, max_headers),
|
|
+ NULL },
|
|
+
|
|
{ ngx_string("ignore_invalid_headers"),
|
|
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG,
|
|
ngx_conf_set_flag_slot,
|
|
@@ -3370,6 +3377,7 @@ ngx_http_core_create_srv_conf(ngx_conf_t *cf)
|
|
cscf->request_pool_size = NGX_CONF_UNSET_SIZE;
|
|
cscf->client_header_timeout = NGX_CONF_UNSET_MSEC;
|
|
cscf->client_header_buffer_size = NGX_CONF_UNSET_SIZE;
|
|
+ cscf->max_headers = NGX_CONF_UNSET_UINT;
|
|
cscf->ignore_invalid_headers = NGX_CONF_UNSET;
|
|
cscf->merge_slashes = NGX_CONF_UNSET;
|
|
cscf->underscores_in_headers = NGX_CONF_UNSET;
|
|
@@ -3411,6 +3419,8 @@ ngx_http_core_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
|
|
return NGX_CONF_ERROR;
|
|
}
|
|
|
|
+ ngx_conf_merge_uint_value(conf->max_headers, prev->max_headers, 1000);
|
|
+
|
|
ngx_conf_merge_value(conf->ignore_invalid_headers,
|
|
prev->ignore_invalid_headers, 1);
|
|
|
|
diff --git a/src/http/ngx_http_core_module.h b/src/http/ngx_http_core_module.h
|
|
index 2341fd4..2e787e2 100644
|
|
--- a/src/http/ngx_http_core_module.h
|
|
+++ b/src/http/ngx_http_core_module.h
|
|
@@ -196,6 +196,8 @@ typedef struct {
|
|
|
|
ngx_msec_t client_header_timeout;
|
|
|
|
+ ngx_uint_t max_headers;
|
|
+
|
|
ngx_flag_t ignore_invalid_headers;
|
|
ngx_flag_t merge_slashes;
|
|
ngx_flag_t underscores_in_headers;
|
|
diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c
|
|
index 404aa77..dccc9de 100644
|
|
--- a/src/http/ngx_http_request.c
|
|
+++ b/src/http/ngx_http_request.c
|
|
@@ -1468,6 +1468,15 @@ ngx_http_process_request_headers(ngx_event_t *rev)
|
|
|
|
/* a header line has been parsed successfully */
|
|
|
|
+ if (r->headers_in.count++ >= cscf->max_headers) {
|
|
+ r->lingering_close = 1;
|
|
+ ngx_log_error(NGX_LOG_INFO, c->log, 0,
|
|
+ "client sent too many header lines");
|
|
+ ngx_http_finalize_request(r,
|
|
+ NGX_HTTP_REQUEST_HEADER_TOO_LARGE);
|
|
+ break;
|
|
+ }
|
|
+
|
|
h = ngx_list_push(&r->headers_in.headers);
|
|
if (h == NULL) {
|
|
ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
|
|
diff --git a/src/http/ngx_http_request.h b/src/http/ngx_http_request.h
|
|
index 6dfb4a4..3b46c41 100644
|
|
--- a/src/http/ngx_http_request.h
|
|
+++ b/src/http/ngx_http_request.h
|
|
@@ -180,6 +180,7 @@ typedef struct {
|
|
|
|
typedef struct {
|
|
ngx_list_t headers;
|
|
+ ngx_uint_t count;
|
|
|
|
ngx_table_elt_t *host;
|
|
ngx_table_elt_t *connection;
|
|
diff --git a/src/http/v2/ngx_http_v2.c b/src/http/v2/ngx_http_v2.c
|
|
index 291677a..7812ddc 100644
|
|
--- a/src/http/v2/ngx_http_v2.c
|
|
+++ b/src/http/v2/ngx_http_v2.c
|
|
@@ -1860,6 +1860,15 @@ ngx_http_v2_state_process_header(ngx_http_v2_connection_t *h2c, u_char *pos,
|
|
}
|
|
|
|
} else {
|
|
+ cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
|
|
+
|
|
+ if (r->headers_in.count++ >= cscf->max_headers) {
|
|
+ ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
|
|
+ "client sent too many header lines");
|
|
+ ngx_http_finalize_request(r, NGX_HTTP_REQUEST_HEADER_TOO_LARGE);
|
|
+ goto error;
|
|
+ }
|
|
+
|
|
h = ngx_list_push(&r->headers_in.headers);
|
|
if (h == NULL) {
|
|
return ngx_http_v2_connection_error(h2c,
|
|
--
|
|
2.44.0
|
|
|