Nginx WebSocket 反向代理保持返回 200 而不是 101

axe*_*ink 8 nginx reverse-proxy node.js websocket

我目前正在尝试在我的个人服务器上运行hack.chat

长话短说,它由两台服务器组成。第一个是一个简单的 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/*;
}
Run Code Online (Sandbox Code Playgroud)

启用网站/聊天:

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;
}
Run Code Online (Sandbox Code Playgroud)

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

预先感谢您的任何回复。

编辑

感谢 mc0e,我设法让 hack.chat 服务器响应 101。通过将 nginx 和 node.js 之间实际发生的情况与直接连接上发生的情况进行比较,我看到直接在标头上升级:websocket 已设置,但 nginx 确实如此不是。所以我更正了我的网站启用/聊天:

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;
}
Run Code Online (Sandbox Code Playgroud)

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

不过还是不行。hack.chat 返回 101 连接:升级和升级:websocket 但不知何故 nginx 返回 101 连接:keep-alive(如我在 firefox 中看到的那样):/

编辑

在 nginx 通信上做了一个 ngrep,它确实发送了 hack.chat 给他的数据包,而 Firefox 则抱怨跨域。我会尽量避免交叉起源。

上次编辑

好的,现在我回家了,我做了一个测试,它就像一个魅力。我的最后一个问题是因为我的工作代理,让我们希望它是缓存,否则一切都将毫无用处。

这是我的最后一个避免交叉原点的conf:

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;
}
Run Code Online (Sandbox Code Playgroud)

mc0*_*c0e 2

根据我对 nginx websocket 码头的阅读,当您的 nginx 代理看到升级标头时,它将它们传递到 hack.chat。hack.chat 然后需要使用 101 响应进行响应。

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

您可以使用 tcpdump 或 ngrep 捕获 http 流量。我会选择 ngrep。这样做会在终端中输出。

ngrep 'Host: chat.axellink.fr' port 80
Run Code Online (Sandbox Code Playgroud)

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

ngrep '.' port 6060
Run Code Online (Sandbox Code Playgroud)

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

您也许能够从中发现问题,但如果没有,请捕获各种交互并将其添加到您的问题中。

javascript 要求在与 javascript 提供服务的域不同的域上进行 hack.chat 通信是否存在问题?这可能相关: /sf/ask/1406514931/