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