summaryrefslogtreecommitdiffhomepage
path: root/src/http
diff options
context:
space:
mode:
authorSergey Kandaurov <pluknet@nginx.com>2026-01-13 16:51:07 +0400
committerSergey Kandaurov <s.kandaurov@f5.com>2026-01-21 20:39:00 +0400
commitcb9252ae6537d8c24addcf0822267804fc73db43 (patch)
tree26db85fed975f1c460f44813541531286086d357 /src/http
parent7fa941a55e211ebd57f512fbfb24d59dbb97940d (diff)
downloadnginx-cb9252ae6537d8c24addcf0822267804fc73db43.tar.gz
nginx-cb9252ae6537d8c24addcf0822267804fc73db43.tar.bz2
Range filter: reasonable limit on multiple ranges.
A total response length with multiple ranges can be larger than the source response size due to multipart boundary headers. This change extends max ranges limit imposed in c2c3e3105 (1.1.2) by accounting boundary headers. Notably, this covers suspicious requests with a lot of small ranges that have an increased processing overhead and are susceptible to range based amplification attacks. The limit disables ranges as long as a total response length comes close to the source size, additionally penalizing small size ranges on a large source size where a processing overhead prevails, while leaving a room for more ranges on a small source size, such that it should not affect well-behaving applications. The limit can be altered with the "max_ranges" directive. Closes #988 on GitHub.
Diffstat (limited to 'src/http')
-rw-r--r--src/http/modules/ngx_http_range_filter_module.c17
1 files changed, 16 insertions, 1 deletions
diff --git a/src/http/modules/ngx_http_range_filter_module.c b/src/http/modules/ngx_http_range_filter_module.c
index 27d1875c8..fec3642cf 100644
--- a/src/http/modules/ngx_http_range_filter_module.c
+++ b/src/http/modules/ngx_http_range_filter_module.c
@@ -273,7 +273,7 @@ ngx_http_range_parse(ngx_http_request_t *r, ngx_http_range_filter_ctx_t *ctx,
u_char *p;
off_t start, end, size, content_length, cutoff,
cutlim;
- ngx_uint_t suffix;
+ ngx_uint_t suffix, max_ranges;
ngx_http_range_t *range;
ngx_http_range_filter_ctx_t *mctx;
@@ -294,6 +294,8 @@ ngx_http_range_parse(ngx_http_request_t *r, ngx_http_range_filter_ctx_t *ctx,
p = r->headers_in.range->value.data + 6;
size = 0;
+ max_ranges = ranges;
+
content_length = r->headers_out.content_length_n;
cutoff = NGX_MAX_OFF_T_VALUE / 10;
@@ -401,10 +403,23 @@ ngx_http_range_parse(ngx_http_request_t *r, ngx_http_range_filter_ctx_t *ctx,
return NGX_HTTP_RANGE_NOT_SATISFIABLE;
}
+ if (ctx->ranges.nelts == 1) {
+ return NGX_OK;
+ }
+
if (size > content_length) {
return NGX_DECLINED;
}
+ if (max_ranges == NGX_MAX_INT32_VALUE) {
+ size += ctx->ranges.nelts * 256;
+ content_length += 4096;
+
+ if (size > content_length) {
+ return NGX_DECLINED;
+ }
+ }
+
return NGX_OK;
}