【问题标题】:Nginx not receiving second request after 100-Contnue, 401 responseNginx 在 100-Continue 后没有收到第二个请求,401 响应
【发布时间】:2019-12-13 08:32:18
【问题描述】:

对于以下配置,请求 2 没有反映在 nginx 中。没有错误日志,请求 2 的访问日志中也没有任何内容。

该问题仅在 100-Continue, 401 Unauthorized 作为初始响应引入后才开始出现。如果请求 1 得到代理服务器的 101 响应,则一切正常(结束 websocket 连接已建立)。

预期行为: 第二个请求应该成功到达代理,然后到达代理服务器。之后,它将被转换为 websocket 连接。

Nginx 配置

server {
    listen 443 ssl;
    server_name admin.example.com;
    ssl_certificate       /etc/nginx/server.pem;
    ssl_certificate_key   /etc/nginx/key.pem;
    ssl_session_cache shared:SSL:5m;
    ssl_protocols TLSv1.2;
    ssl_dhparam /etc/ssl/certs/dhparam.pem;
    ssl_ecdh_curve secp384r1;
    server_name_in_redirect on;
    client_max_body_size 100m;

    location /my_line/ {
        proxy_pass        https://y.y.y.y/;
        proxy_set_header  Host y.y.y.y;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $http_connection;
        proxy_ignore_client_abort on;
        proxy_buffering off;
        proxy_http_version 1.1;
        proxy_set_header Origin '';
        keepalive_timeout 100s;
        proxy_set_header Expect $http_expect;
        proxy_read_timeout 7200;
    }

    error_page  404              /index.html;
    location / {
        root   /usr/share/nginx/html;
        add_header X-Frame-Options DENY always;
        add_header X-Content-Type-Options nosniff always;
        add_header X-XSS-Protection "1; mode=block"  always;
    }
}

请求 1:

GET /myserver/my_line/84620 HTTP/1.1
Connection: Upgrade
Authorization: Basic ODQ2MjA6c3MxOE1VRUs5UEF6RTB5eHoyVmpSZ0Roc3VyV0tCcA==
User-Agent: MyApp/WebSocketClient/
Host: x.x.x.x
Upgrade: websocket
Sec-WebSocket-Key: DhaIyjupEbTHXQvX3asVeA==
Sec-WebSocket-Protocol: Web_Proxy
Sec-WebSocket-Version: 13
Sec-WebSocket-Extensions: mux
Expect: 100-continue

响应 1

HTTP/1.1 100 Continue
Server: nginx
Date: Mon, 09 Dec 2019 16:33:51 GMT
Connection: keep-alive

响应 2

HTTP/1.1 401 Unauthorized
Date: Mon, 09 Dec 2019 16:33:51 GMT
Expires: Mon, 09 Dec 2019 16:34:51 GMT
Cache-Control: private,max-age=60
WWW-Authenticate: Digest realm="WebSocket Group@myapp", domain="", nonce="f9beaf5521a1cdf078362b68a4332df5", algorithm=MD5
Server: MyServer/
X-Frame-Options: DENY
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
Strict-Transport-Security: max-age=31536000
Content-Length: 0

请求 2

GET /myserver/my_line/84620 HTTP/1.1
Connection: Upgrade
Authorization: Digest username="84620", realm="WebSocket Group@myapp", nonce="f9beaf5521a1cdf078362b68a4332df5", uri="/myserver/my_line/84620", response="5d8bb7c396724bb840da698c06f19629", algorithm=MD5, nc=00000056
User-Agent: MyApp/WebSocketClient/
Host: x.x.x.x
Upgrade: websocket
Sec-WebSocket-Key: DhaIyjupEbTHXQvX3asVeA==
Sec-WebSocket-Protocol: Web_Proxy
Sec-WebSocket-Version: 13
Sec-WebSocket-Extensions: mux

Issue -> nginx访问日志中没有反映第二个请求,错误日志中没有任何内容。

支持 nginx 将请求代理到代理服务器,而不做任何其他拥有它自己的事情。当从客户端触发 REQUEST2 时,客户端与代理、代理与代理服务器之间的 TCP 连接是完整的。我怀疑 nginx 的配置有问题 wrt 连接和升级标头。 我已经在 nginx 上捕获了所有的 wireshark,它清楚地表明 tcp 连接已经到位并且请求 2 是 nginx 的确认。只是 nginx 没有处理它——就好像它进入了黑洞而不是从中出来。

请求您的专家帮助。谢谢。

【问题讨论】:

  • 这里要注意的一点是websocket代理的使用方式有所不同-nginx.com/blog/websocket-nginx。这里有多个HTTP请求在同一个tcp连接上流动,然后应该升级到ws。
  • 为什么请求2中有不同的授权头和用户代理,你能解释一下原因吗?
  • 这是用户代理的一种错字。我纠正了它,它们具有相同的价值。至于 Authorization 标头,值完全传递给代理服务器,是客户端和服务器之间设计的响应挑战机制。

标签: nginx websocket nginx-location nginx-config


【解决方案1】:

如果您查看您的请求 1,没有正文,但您从代理服务器获得 100 继续响应,我认为这是由于 Nginx 添加的 Expect 请求标头“100-continue”(可能是由于配置条目 proxy_set_header Expect $http_expect;),但根据规范这是错误的,

https://www.w3.org/Protocols/rfc2616/rfc2616-sec8.html

如果客户端不打算发送请求正文,则不得发送带有“100-continue”期望的 Expect 请求头字段(第 14.20 节)。

这可能是挂起的原因,因为服务器可能正在等待永远不会到达的主体(请求 1)。

【讨论】:

  • REQUEST 1 中的客户端正在传递 Expect: 100-continue,因此代理服务器(以及 nginx)按预期发送 100 Continue 响应。问题出在第 3 步,请求到达 nginx 并进一步中继到代理服务器,底层 TCP 连接是一个新连接,与第一次请求 1 中创建的不同。
  • 所以,如果我理解正确的话,第二个请求是由代理 Nginx 接收的,并在单独的 TCP 连接上转发到代理 Nginx,但是您在代理 Nginx 的日志中看不到第二个请求,对吗?
  • 是的,第二个请求由 nginx 代理收到,但没有进一步的线索知道它发生了什么。根据wireshark跟踪,ACK被发送到请求客户端。与代理服务器的 TCP 连接被 nginx 终止。所以看起来 nginx 吞噬了 Request 2,没有任何痕迹。
猜你喜欢
  • 2017-10-02
  • 1970-01-01
  • 1970-01-01
  • 2014-08-05
  • 2022-11-20
  • 2018-03-14
  • 1970-01-01
  • 1970-01-01
  • 2020-04-28
相关资源
最近更新 更多