首页 > 解决方案 > Nginx 没有正确转发我的 SSL WebSockets 连接?

问题描述

我正在尝试将 Django 应用程序与基于 flask+gevent 的 websocket 后端(不讲 SSL)放在同一个域上。我发现虽然直接连接到 websocket 后端是可行的,但尝试通过 nginx 访问它却失败了。这是 nginx 和 websockets 服务器之间通信的 hexdump,包括我用来捕获它的命令:

# ncat -x /dev/stdout -k -vv -l 13006 --sh-exec "ncat localhost 13005"                                                                                                
Ncat: Version 7.60 ( https://nmap.org/ncat )
Ncat: Generating a temporary 1024-bit RSA key. Use --ssl-key and --ssl-cert to use a permanent one.
Ncat: SHA-1 fingerprint: 6E88 CB89 DEA4 09E4 0863 CD09 90D8 BDFE 3030 A87A
Ncat: Listening on :::13006
Ncat: Listening on 0.0.0.0:13006
Ncat: Connection from 127.0.0.1.
Ncat: Connection from 127.0.0.1:49634.
NCAT DEBUG: Executing with shell: ncat localhost 13005
[0000]   47 45 54 20 2F 73 69 6E   67 6C 65 2F 3F 72 65 67   GET /sin gle/?reg
[0010]   65 78 3D 6F 66 6F 20 48   54 54 50 2F 31 2E 31 0D   ex=ofo H TTP/1.1.
[0020]   0A 55 70 67 72 61 64 65   3A 20 77 65 62 73 6F 63   .Upgrade : websoc
[0030]   6B 65 74 0D 0A 43 6F 6E   6E 65 63 74 69 6F 6E 3A   ket..Con nection:
[0040]   20 55 70 67 72 61 64 65   0D 0A 53 65 63 2D 57 65    Upgrade ..Sec-We
[0050]   62 53 6F 63 6B 65 74 2D   56 65 72 73 69 6F 6E 3A   bSocket- Version:
[0060]   20 31 33 0D 0A 53 65 63   2D 57 65 62 53 6F 63 6B    13..Sec -WebSock
[0070]   65 74 2D 4B 65 79 3A 20   61 45 41 6D 30 65 50 4B   et-Key:  aEAm0ePK
[0080]   5A 75 65 77 61 37 48 42   73 32 32 32 76 41 3D 3D   Zuewa7HB s222vA==
[0090]   0D 0A 53 65 63 2D 57 65   62 53 6F 63 6B 65 74 2D   ..Sec-We bSocket-
[00a0]   45 78 74 65 6E 73 69 6F   6E 73 3A 20 70 65 72 6D   Extensio ns: perm
[00b0]   65 73 73 61 67 65 2D 64   65 66 6C 61 74 65 3B 20   essage-d eflate; 
[00c0]   63 6C 69 65 6E 74 5F 6D   61 78 5F 77 69 6E 64 6F   client_m ax_windo
[00d0]   77 5F 62 69 74 73 0D 0A   48 6F 73 74 3A 20 6C 6F   w_bits.. Host: lo
[00e0]   63 61 6C 68 6F 73 74 3A   31 33 30 30 36 0D 0A 0D   calhost: 13006...
[00f0]   0A                                                  .
[0000]   48 54 54 50 2F 31 2E 31   20 31 30 31 20 53 77 69   HTTP/1.1  101 Swi
[0010]   74 63 68 69 6E 67 20 50   72 6F 74 6F 63 6F 6C 73   tching P rotocols
[0020]   0D 0A 55 70 67 72 61 64   65 3A 20 77 65 62 73 6F   ..Upgrad e: webso
[0030]   63 6B 65 74 0D 0A 43 6F   6E 6E 65 63 74 69 6F 6E   cket..Co nnection
[0040]   3A 20 55 70 67 72 61 64   65 0D 0A 53 65 63 2D 57   : Upgrad e..Sec-W
[0050]   65 62 53 6F 63 6B 65 74   2D 41 63 63 65 70 74 3A   ebSocket -Accept:
[0060]   20 68 74 4F 6D 31 78 78   78 64 35 6C 30 48 6A 66    htOm1xx xd5l0Hjf
[0070]   4D 43 6C 72 34 54 72 35   4A 51 4D 45 3D 0D 0A 0D   MClr4Tr5 JQME=...
[0080]   0A 88 00                                            ...
[0000]   88 80 C5 99 4F E0                                   ....O.

这是我正在使用的配置:

/etc/nginx/sites-enabled/default

server {
        listen 80;
        listen [::]:80;
        server_name _;


        return 301 https://$host$request_uri;
}
server {
        listen 443 ssl default_server;
        listen [::]:443 ssl default_server;
        include snippets/profound-ssl.conf;
        server_name _;


        location / {
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header X-Forwarded-Proto $scheme;
                proxy_set_header Host $http_host;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_redirect off;
                proxy_pass http://localhost:8000/;
        }


        location ^~ /ws/ {
                proxy_pass http://localhost:13006/;
                proxy_http_version 1.1;
                proxy_set_header Upgrade $http_upgrade;
                proxy_set_header Connection $http_connection;
                proxy_redirect off;

                proxy_set_header Sec-WebSocket-Version $http_sec_websocket_version;
                proxy_set_header Sec-WebSocket-Protocol $http_sec_websocket_protocol;
                proxy_set_header Sec-WebSocket-Key $http_sec_websocket_key;
                proxy_set_header Sec-WebSocket-Extensions $http_sec_websocket_extensions;
                proxy_set_header Sec-WebSocket-Accept $http_sec_websocket_accept;

        }


}

/etc/nginx/nginx.conf

user www-data;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;
events {
        worker_connections 768;
}
http {


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

        sendfile on;
        tcp_nopush on;
        tcp_nodelay on;
        keepalive_timeout 65;
        types_hash_max_size 2048;
        include /etc/nginx/mime.types;
        default_type application/octet-stream;
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2; 
        ssl_prefer_server_ciphers on;
        access_log /var/log/nginx/access.log;
        error_log /var/log/nginx/error.log;
        gzip on;
        include /etc/nginx/conf.d/*.conf;
        include /etc/nginx/sites-enabled/*;
}

除了后端的错误之外,不会记录任何错误:

2018-11-15T13:53:17.569402589Z DEBUG:geventwebsocket.handler:Initializing WebSocket
2018-11-15T13:53:17.570682796Z DEBUG:geventwebsocket.handler:Validating WebSocket request
2018-11-15T13:53:17.570698284Z DEBUG:geventwebsocket.handler:Attempting to upgrade connection
2018-11-15T13:53:17.570701438Z DEBUG:geventwebsocket.handler:WebSocket request accepted, switching protocols
2018-11-15T13:53:17.570704839Z DEBUG:geventwebsocket.handler:Closed WebSocket
2018-11-15T13:53:17.570708858Z DEBUG:geventwebsocket.handler:Failed to write closing frame -> closing socket
2018-11-15T13:53:17.570713594Z DEBUG:geventwebsocket.handler:Closed WebSocket

我该如何调试呢?我还应该检查什么?

标签: sslnginxwebsocketgevent

解决方案


史上最诡异的错误!看来我需要更改:

proxy_pass http://localhost:13006/

至:

proxy_pass http://localhost:13006/ws


推荐阅读