limiting number of HTTP request headers
Maksim Yevmenkin
maksim.yevmenkin at gmail.com
Thu May 16 18:01:36 UTC 2024
Hello,
> > Could the community share their thoughts on introducing a directive to
> > cap the number of HTTP request headers? While we currently have the
> > ability to limit client HTTP request buffer size, having more specific
> > control over the number of headers could be advantageous.
>
> I personally tend to think that buffer size limit is enough for
> [free]nginx itself. On the other hand, an additional limit on the
> number of request headers might be beneficial to protect backend
> servers, and might worth adding.
thanks! a possible patch is attached.
max
-------------- next part --------------
diff --git a/ports/netflix/nginx/files/nginx/src/http/ngx_http_core_module.c b/ports/netflix/nginx/files/nginx/src/http/ngx_http_core_module.c
index e26705475e46..b12951fd2a09 100644
--- a/ports/netflix/nginx/files/nginx/src/http/ngx_http_core_module.c
+++ b/ports/netflix/nginx/files/nginx/src/http/ngx_http_core_module.c
@@ -287,6 +287,13 @@ static ngx_command_t ngx_http_core_commands[] = {
offsetof(ngx_http_core_srv_conf_t, underscores_in_headers),
NULL },
+ { ngx_string("max_request_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_request_headers),
+ NULL },
+
{ ngx_string("location"),
NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_BLOCK|NGX_CONF_TAKE12,
ngx_http_core_location,
@@ -3508,6 +3515,7 @@ ngx_http_core_create_srv_conf(ngx_conf_t *cf)
cscf->ignore_invalid_headers = NGX_CONF_UNSET;
cscf->merge_slashes = NGX_CONF_UNSET;
cscf->underscores_in_headers = NGX_CONF_UNSET;
+ cscf->max_request_headers = NGX_CONF_UNSET_UINT;
cscf->file_name = cf->conf_file->file.name.data;
cscf->line = cf->conf_file->line;
@@ -3554,6 +3562,9 @@ ngx_http_core_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
ngx_conf_merge_value(conf->underscores_in_headers,
prev->underscores_in_headers, 0);
+ ngx_conf_merge_value(conf->max_request_headers,
+ prev->max_request_headers, 128);
+
if (conf->server_names.nelts == 0) {
/* the array has 4 empty preallocated elements, so push cannot fail */
sn = ngx_array_push(&conf->server_names);
diff --git a/ports/netflix/nginx/files/nginx/src/http/ngx_http_core_module.h b/ports/netflix/nginx/files/nginx/src/http/ngx_http_core_module.h
index 3ed9d1632eec..1a5853fc7dc1 100644
--- a/ports/netflix/nginx/files/nginx/src/http/ngx_http_core_module.h
+++ b/ports/netflix/nginx/files/nginx/src/http/ngx_http_core_module.h
@@ -212,6 +212,7 @@ typedef struct {
ngx_flag_t ignore_invalid_headers;
ngx_flag_t merge_slashes;
ngx_flag_t underscores_in_headers;
+ ngx_uint_t max_request_headers; /* max number of request headers */
unsigned listen:1;
#if (NGX_PCRE)
diff --git a/ports/netflix/nginx/files/nginx/src/http/ngx_http_request.c b/ports/netflix/nginx/files/nginx/src/http/ngx_http_request.c
index 2ed0d99c168b..1ff03b215880 100644
--- a/ports/netflix/nginx/files/nginx/src/http/ngx_http_request.c
+++ b/ports/netflix/nginx/files/nginx/src/http/ngx_http_request.c
@@ -1728,6 +1728,7 @@ ngx_http_process_request_headers(ngx_event_t *rev)
ngx_http_request_t *r;
ngx_http_core_srv_conf_t *cscf;
ngx_http_core_main_conf_t *cmcf;
+ ngx_list_part_t *part;
c = rev->data;
r = c->data;
@@ -1816,6 +1817,25 @@ ngx_http_process_request_headers(ngx_event_t *rev)
continue;
}
+ /* apply request header limit */
+
+ for (rv = 0, part = &r->headers_in.headers.part;
+ part != NULL;
+ part = part->next) {
+ rv += part->nelts;
+ }
+
+ if (rv >= cscf->max_request_headers) {
+ ngx_log_error(NGX_LOG_INFO, c->log, 0,
+ "client sent too many request headers, have %i, limit is %ui",
+ rv, cscf->max_request_headers);
+
+ r->lingering_close = 1;
+ ngx_http_finalize_request(r, NGX_HTTP_REQUEST_ENTITY_TOO_LARGE);
+
+ break;
+ }
+
/* a header line has been parsed successfully */
h = ngx_list_push(&r->headers_in.headers);
More information about the nginx-devel
mailing list