nginx关闭连接,而不是使用TLS和http2在长URI上返回HTTP414



我正在调试一个问题,在这个问题中,在没有任何HTTP响应的情况下丢弃请求,也没有访问我们的后端代码。我已经指出这是由于nginx和请求URI太长(在5000个字符的区域内(。请求不需要那么长,这是前端代码中的一个错误,但我希望nginx返回414 URI Too Long,这正是该响应存在的原因。但我得到了

$ curl https://my.server?foo=barbarbar(repeat*many times)
...
curl: (92) HTTP/2 stream 1 was not closed cleanly before end of the underlying stream

这种情况仅发生在httpshttp2时。使用普通http,我得到

...
< HTTP/1.1 414 Request-URI Too Large
...

正如预期的那样。

有了https没有http2,我也得到了HTTP 414


以下nginx配置再现了该问题:

server {
listen               443 ssl http2;
ssl_certificate      /etc/ssl/private/cert.pem;
ssl_certificate_key  /etc/ssl/private/key.pem;
server_name          localhost;
# large_client_header_buffers 4 16k;
location / {
root   /usr/share/nginx/html;
index  index.html index.htm;
}

(TLS证书是自签名的,但对于正确的证书,会复制相同的问题(

出现此问题

  • Ubuntu 20.04(服务器和Docker(
  • 发动机1.18.0、1.20.2、1.22.0

这是预期的,还是nginx中的错误?

您可能会遇到请求大小或字段大小限制,特别是在HTTP/2中,很难从中恢复,引用票证#1520:

由于HTTP/2协议中的标头是使用有状态压缩算法编码的,因此如果在处理请求中的标头时出现任何问题(例如达到限制(,则无法继续保持连接。请注意,nginx不仅会断开连接,还会发送一个带有ENHANCE_YOUR_CALM协议错误的GOAWAY帧。

换句话说,在这种情况下,nginx似乎无法发送414响应,即使它想发送;从与这张票相关的重复票的数量来看,这种情况似乎不太可能改变。

如果你愿意,你可以增加限额来完全避免这种情况:

  • http2_max_field_size
  • http2_max_header_size
  • large_client_header_buffers

但既然你说不应该出现坏的URL,我就把限制保留为默认值。

最新更新