Nginx WebSocket 反向代理一直返回 200 而不是 101

Nginx WebSocket 反向代理一直返回 200 而不是 101

我目前正在尝试黑客聊天在我的个人服务器上工作。

长话短说,它由两台服务器组成。第一台是一个简单的 httpd 服务器,用于提供 javascript 和 CSS。第二台是聊天系统,是一个 node.js 服务器,javascript 使用 websocket 连接到该服务器。问题就来了。

我希望所有服务器都使用端口 80,在单个 IP 上使用不同的域名,并使用 Nginx 中单独的服务器块。

我跟着Nginx websocket 文档但这不起作用。当 websocket 尝试连接时,它总是会得到 200 返回代码,而如果我理解正确的话,它应该得到 101(切换协议)。

我的 Nginx 版本是 1.8.0,我的服务器在 gentoo 上运行,系统是 Linux 4.0.5

以下是相关 nginx conf 文件的转储:

nginx.conf:

user nginx nginx;
worker_processes 1;

error_log /var/log/nginx/error_log info;

events {
    worker_connections 1024;
    use epoll;
}

http {
    include /etc/nginx/mime.types;
    default_type application/octet-stream;

    log_format main
        '$remote_addr - $remote_user [$time_local] '
        '"$request" $status $bytes_sent '
        '"$http_referer" "$http_user_agent" '
        '"$gzip_ratio"';

    client_header_timeout 10m;
    client_body_timeout 10m;
    send_timeout 10m;

    connection_pool_size 256;
    client_header_buffer_size 1k;
    large_client_header_buffers 4 2k;
    request_pool_size 4k;

    gzip on;
    gzip_min_length 1100;
    gzip_buffers 4 8k;
    gzip_types text/plain;

    output_buffers 1 32k;
    postpone_output 1460;

    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;

    keepalive_timeout 75 20;

    ignore_invalid_headers on;

    include /etc/nginx/sites-enabled/*;
}

站点启用/聊天:

map $http_upgrade $connection_upgrade{
    default upgrade;
    ''  close;
}

server{
    listen 0.0.0.0:80;
    server_name chat.axellink.fr;

    location / {
        proxy_pass http://127.0.0.1:6060;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
    }

    access_log /var/log/nginx/chat_access;
    error_log /var/log/nginx/chat_error debug;
}

当我查看 access_log 时,它有效地显示了 200 响应,并且 error_log 中没有错误。不幸的是,node.js 服务器没有给我任何日志(或者我不知道如何查看它)。

提前感谢您的任何回复。

编辑

感谢 mc0e,我设法让 hack.chat 服务器响应 101。通过比较 nginx 和 node.js 之间实际发生的情况与直接连接上发生的情况,我发现直接连接上设置了标头升级:websocket,但 nginx 没有设置。因此,我将 sites-enabled/chat 更正为:

server{
    listen 0.0.0.0:80;
    server_name chat.axellink.fr;

    location / {
        proxy_pass http://127.0.0.1:6060;
        proxy_http_version 1.1;
        proxy_set_header Upgrade "websocket";
        proxy_set_header Connection "Upgrade";
    }

    access_log /var/log/nginx/chat_access;
    error_log /var/log/nginx/chat_error debug;
}

我还删除了地图块,因为它用于将连接头设置为关闭而不是升级。

但仍然不起作用。hack.chat 返回 101 连接:升级和升级:websocket 但不知何故 nginx 返回 101 连接:保持活动(就像我在 Firefox 中看到的那样):/

编辑

在 nginx 通信上执行了 ngrep,它确实将 hack.chat 返回的数据包发送给了他,而 Firefox 则抱怨跨源。我会尽量避免跨源。

最后编辑

好吧,现在我回到家,我做了一个测试,它运行得很好。我确信我上次的问题是由于我的工作代理,希望是缓存,否则一切都将毫无用处。

下面是我的最后一个避免跨源的配置:

server{
        listen 0.0.0.0:80;
        server_name chat.axellink.fr;

        location / {
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header Host $http_host;
                proxy_set_header X-NginX-Proxy true;
                proxy_pass http://127.0.0.1:8081;
        }

        location /chat/ {
                proxy_pass http://127.0.0.1:6060;
                proxy_http_version 1.1;
                proxy_set_header Upgrade "websocket";
                proxy_set_header Connection "Upgrade";
        }

        access_log /var/log/nginx/chat_access;
        error_log /var/log/nginx/chat_error debug;
}

答案1

从我对 nginx websocket dock 的解读来看,当您的 nginx 代理看到升级标头时,它会将它们传递给 hack.chat。hack.chat 然后需要使用 101 响应进行响应。

首先,您希望能够调试实际的 HTTP 和 hack.chat 事务,这样您就知道问题出在您的客户端应用程序、Web 服务器上还是 hack.chat 通信上。这还可以让您获得准确的 HTTP 响应,您说您目前不知道如何获得它。但是,如果问题出在服务器端,您可能仍希望获得更好的日志来了解问题出在哪里。

您可以使用 tcpdump 或 ngrep 捕获 http 流量。我建议使用 ngrep。这样做会在您的终端中显示输出。

ngrep 'Host: chat.axellink.fr' port 80

您可能希望在您的 Web 服务器上运行它,但如果您有一个可以运行 ngrep 的桌面环境,您可能选择在那里运行它。如果您在服务器上运行它,您还可以捕获 nginx 和聊天服务器之间的交互。

ngrep '.' port 6060

终端输出通常足以看到您需要的内容,但您也可以使用 ngrep 的“-O”标志将数据写入 pcap 转储文件,就像 tcpdump 使用“-w”一样。然后,您可以将该文件带回桌面,使用 wireshark 等图形客户端查看它。

您也许可以从中发现问题,如果不能,请捕捉各种交互并将其添加到您的问题中。

当 JavaScript 要求在与提供 JavaScript 的域不同的域上进行 hack.chat 通信时,是否存在问题?这可能与以下情​​况有关: https://stackoverflow.com/questions/20093070/unable-to-create-cross-domain-websocket-connection-to-node-js-socket-io-server

相关内容