首页 > 解决方案 > 通过 https 的 socket.io 问题,使用 nginx 作为代理

问题描述

我有一个非常奇怪的问题,socket.io我希望有人可以帮助我。

由于某种原因当我使用https. 我收到以下错误代码:(ERR_CRYPTO_OPERATION_FAILED请参阅下面的详细日志)

同样,大多数时候连接都很好,只有一些(随机)客户端似乎有这个问题。

我创建了一个超级简单server.jsclient.js易于测试的方法。

我正在使用socket.io@2.4.1,并且socket.io-client@2.4.0

不幸的是,版本3.x.x不是一个选项。

操作系统是Ubuntu 18.04,在服务器端和客户端。

Nginx:

server {
        listen 80;
        server_name example.domain.com;
        return 301 https://example.domain.com$request_uri;
}

server {
        listen 443 ssl http2;
        server_name example.domain.com;

        ssl_certificate /path/to/cert.pem;
        ssl_certificate_key /path/to/cert.key;
        ssl_protocols TLSv1.2 TLSv1.3;

        location /
        {
                proxy_pass http://127.0.0.1:8000;
                include /etc/nginx/proxy_params;
        }

        location /socket.io {
                proxy_http_version 1.1;
                proxy_buffering off;
                proxy_set_header Upgrade $http_upgrade;
                proxy_set_header Connection "Upgrade";
                proxy_set_header X-Forwarded-Host $host;
                proxy_set_header X-Forwarded-Server $host;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_connect_timeout 30s;
                proxy_read_timeout 30s;
                proxy_send_timeout 30s;
                proxy_pass http://127.0.0.1:8000/socket.io;
        }

        error_page 500 502 503 504 /50x.html;
        location = /50x.html {
                root /usr/share/nginx/html;
                internal;
        }
}

客户端.js:

const client = io.connect("https://example.domain.com", {
    origins: '*:*',
    transportOptions: {
        polling: {
            extraHeaders: {
                'Authorization': token
            }
        }
    },
});

尝试添加secure: true,reconnect: truerejectUnauthorized : false,但没有区别。另外,我在没有transportOptions.

server.js:

const port = 5000;
const app = express();
const server = app.listen(port, () => {
    console.log(`Listening on port: ${port}`);
});

const io = socket(server);

io.on("connection", (socket) => {
    console.log("Client connected", socket.id);
});

当然,当我删除重定向nginx并使用普通旧http的连接时,一切都很好。

当我运行时DEBUG=* node client.js,我得到以下信息:

socket.io-client:url parse https://example.domain.com/ +0ms
socket.io-client new io instance for https://example.domain.com/ +0ms
socket.io-client:manager readyState closed +0ms
socket.io-client:manager opening https://example.domain.com/ +1ms
engine.io-client:socket creating transport "polling" +0ms
engine.io-client:polling polling +0ms
engine.io-client:polling-xhr xhr poll +0ms
engine.io-client:polling-xhr xhr open GET: https://example.domain.com/socket.io/?EIO=3&transport=polling&t=NVowV1t&b64=1 +2ms
engine.io-client:polling-xhr xhr data null +2ms
engine.io-client:socket setting transport polling +61ms
socket.io-client:manager connect attempt will timeout after 20000 +66ms
socket.io-client:manager readyState opening +3ms
engine.io-client:socket socket error {"type":"TransportError","description":{"code":"ERR_CRYPTO_OPERATION_FAILED"}} +12ms
socket.io-client:manager connect_error +9ms
socket.io-client:manager cleanup +1ms
socket.io-client:manager will wait 1459ms before reconnect attempt +3ms
engine.io-client:socket socket close with reason: "transport error" +6ms
engine.io-client:polling transport not open - deferring close +74ms
socket.io-client:manager attempting reconnect +1s
...

搜索ERR_CRYPTO_OPERATION_FAILED错误,只会将我带到 只有以下描述的node.js 错误页面:

添加于:v15.0.0
加密操作因其他未指定的原因而失败。

我正在使用 Let's Encrypt 证书。

我不明白。如果是 SSL 问题,为什么只有少数客户端会出现此错误?也许我错过了什么nginx

任何帮助深表感谢。

标签: nginxhttpssocket.io

解决方案


两步

  1. 节点的版本必须是 14.x
  2. 连接时添加此配置 rejectUnauthorized: false

推荐阅读