Opened 2 years ago

Closed 2 years ago

#1642 closed defect (wontfix)

HTTP2 proxy limits client body size even for streaming proxied protocols

Reported by: jwatte@… Owned by:
Priority: major Milestone:
Component: other Version: 1.15.x
Keywords: http2 Cc:
uname -a: Linux 279ca9cf8126 4.15.0-34-generic #37-Ubuntu SMP Mon Aug 27 15:21:48 UTC 2018 x86_64 GNU/Linux
nginx -V: nginx version: nginx/1.15.3
built by gcc 8.2.0 (Debian 8.2.0-4)
built with OpenSSL 1.1.0h 27 Mar 2018
TLS SNI support enabled
configure arguments: --prefix=/usr/share/nginx --conf-path=/etc/nginx/nginx.conf --modules-path=/etc/nginx/modules --http-log-path=/var/log/nginx/access.log --error-log-path=/var/log/nginx/error.log --lock-path=/var/lock/nginx.lock --pid-path=/run/nginx.pid --http-client-body-temp-path=/var/lib/nginx/body --http-fastcgi-temp-path=/var/lib/nginx/fastcgi --http-proxy-temp-path=/var/lib/nginx/proxy --http-scgi-temp-path=/var/lib/nginx/scgi --http-uwsgi-temp-path=/var/lib/nginx/uwsgi --with-debug --with-compat --with-pcre-jit --with-http_ssl_module --with-http_stub_status_module --with-http_realip_module --with-http_auth_request_module --with-http_addition_module --with-http_dav_module --with-http_geoip_module --with-http_gzip_static_module --with-http_sub_module --with-http_v2_module --with-stream --with-stream_ssl_module --with-stream_ssl_preread_module --with-threads --with-http_secure_link_module --with-file-aio --without-mail_pop3_module --without-mail_smtp_module --without-mail_imap_module --without-http_uwsgi_module --without-http_scgi_module --with-cc-opt='-g -Og -fPIE -fstack-protector-strong -Wformat -Werror=format-security -Wno-deprecated-declarations -fno-strict-aliasing -D_FORTIFY_SOURCE=2 --param=ssp-buffer-size=4 -DTCP_FASTOPEN=23 -fPIC -I/root/.hunter/_Base/2c5c6fc/c66e716/92161a9/Install/include -Wno-cast-function-type -m64 -mtune=native' --with-ld-opt='-fPIE -fPIC -pie -Wl,-z,relro -Wl,-z,now -L/root/.hunter/_Base/2c5c6fc/c66e716/92161a9/Install/lib' --user=www-data --group=www-data --add-module=/tmp/build/ngx_devel_kit-0.3.1rc1 --add-module=/tmp/build/set-misc-nginx-module-0.32 --add-module=/tmp/build/headers-more-nginx-module-0.33 --add-module=/tmp/build/nginx-goodies-nginx-sticky-module-ng-08a395c66e42 --add-module=/tmp/build/nginx-http-auth-digest-274490cec649e7300fea97fed13d84e596bbc0ce --add-module=/tmp/build/ngx_http_substitutions_filter_module-bc58cb11844bc42735bbaef7085ea86ace46d05b --add-module=/tmp/build/lua-nginx-module-e94f2e5d64daa45ff396e262d8dab8e56f5f10e0 --add-module=/tmp/build/lua-upstream-nginx-module-0.07 --add-module=/tmp/build/nginx_cookie_flag_module-1.1.0 --add-module=/tmp/build/nginx-influxdb-module-f20cfb2458c338f162132f5a21eb021e2cbe6383 --add-dynamic-module=/tmp/build/nginx-opentracing-0.6.0/opentracing --add-dynamic-module=/tmp/build/ModSecurity-nginx-37b76e88df4bce8a9846345c27271d7e6ce1acfb --add-dynamic-module=/tmp/build/ngx_http_geoip2_module-3.0 --add-module=/tmp/build/nginx_ajp_module-bf6cd93f2098b59260de8d494f0f4b1f11a84627 --add-module=/tmp/build/ngx_brotli

Description

When we use NGINX for ingress to GRPC using HTTP2, after receiving a certain number of bytes, we get the error "client intended to send too large chunked body" and a disconnect.

(We do HTTPS ingress on the same port, and use a path-based route to send the GRPC requests to the right place.)

Looking at the nginx source, in ngx_http_v2.c, function
ngx_http_v2_filter_request_body, we see an error when a cumulative
counter named rb->received exceeds the value of
clcf->client_max_body_size (and that limit is not 0.) "client
intended to send too large chunked body"

Further down in the source, we see the code say b->flush =
r->request_body_no_buffering

It seems to me as if the reason this config variable is there, is to
avoid infinite buffering in the proxy eating all RAM. But for a
streaming connection, like HTTP2, that's not a problem.

When buffering is turned off, NGINX should either test the amount in
buffer (rather than the amount streamed through,) OR it should not
check this at all.

The error message can be turned off by setting client_max_body_size to
0, and that's a workaround, but I think it would be better if NGINX
knew the nature of the connection.

Change History (1)

comment:1 by Maxim Dounin, 2 years ago

Resolution: wontfix
Status: newclosed

This is expected behaviour. The client_max_body_size is always checked, regardless of how the request handled, and if the request body is buffered or not. One of its goals is to protect backends from overloading with too large requests, even if the request body is not buffered by nginx.

If you want nginx to pass arbitrary large bodies to your upstream servers, you can useclient_max_body_size 0;. Note though that using some sane large enough value might be a better idea.

Note: See TracTickets for help on using tickets.