diff options
| author | Sergey Kandaurov <pluknet@nginx.com> | 2026-01-13 16:51:07 +0400 |
|---|---|---|
| committer | Sergey Kandaurov <s.kandaurov@f5.com> | 2026-01-21 20:39:00 +0400 |
| commit | cb9252ae6537d8c24addcf0822267804fc73db43 (patch) | |
| tree | 26db85fed975f1c460f44813541531286086d357 /src | |
| parent | 7fa941a55e211ebd57f512fbfb24d59dbb97940d (diff) | |
| download | nginx-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')
| -rw-r--r-- | src/http/modules/ngx_http_range_filter_module.c | 17 |
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; } |
