【问题标题】:nginx, node.js + socket.io with SSL带有 SSL 的 nginx、node.js + socket.io
【发布时间】:2017-07-27 16:41:31
【问题描述】:

我在配置 nginx 和节点以通过 SSL 支持 socket.io 时遇到问题。

我的 nginx 配置:

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

server {
    listen 80;
    listen 443 ssl;
    listen [::]:80;
    listen [::]:443 ssl;

    access_log /var/log/nginx/livetest.log;
    server_name live-test.dev www.live-test.dev;

    ssl_certificate /etc/nginx/ssl/nginx.crt;
    ssl_certificate_key /etc/nginx/ssl/nginx.key;
    ssl_session_cache shared:SSL:50m;
    ssl_session_timeout 5m;

    if ($ssl_protocol = "") {
        rewrite ^ https://$host$request_uri? permanent;
    }

    location / {
        proxy_pass https://live_test;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
    }
}

live_test 是在端口 6020 上运行的 node.js 的上游。在 chrome 中进行测试时,它会在轮询(失败)状态时停止。使用wscat时:

wscat --connect wss://live-test.dev

我收到: error: Error: self signed certificate

我想知道这里可能出了什么问题?这是我的 node.js 应用程序:

var express = require('express');
var cookie = require('cookie');
var app = express();
var http = require('http').Server(app);
var socketIo = require('socket.io');
var redis = require('redis');
var redisClient = client = redis.createClient();

io.on('connection', function(socket){
    var cookies = cookie.parse(socket.handshake.headers.cookie);

    console.log(cookies);
});

http.listen(6020, function(){
    console.log('listening on 6020');
});

我感觉我的 node.js 应用程序中缺少一些东西。我以为既然 nginx 处理 SSL node.js 不再需要了,但也许我错了。

是的,我正在为 SSL 使用自签名证书。 node.js / socket.io 可以使用自签名证书吗?

@更新

阅读后我更改了我的 node.js 应用程序:

var express = require('express');
var cookie = require('cookie');
var fs = require('fs');
var app = express();
var https = require('https').Server(app, {
    key: fs.readFileSync('/etc/nginx/ssl/nginx.key'),
        cert: fs.readFileSync('/etc/nginx/ssl/nginx.crt'),  
});
var socketIo = require('socket.io');
var redis = require('redis');
var redisClient = client = redis.createClient();

var io = new socketIo(https);

io.on('connection', function(socket){
    var cookies = cookie.parse(socket.handshake.headers.cookie);

    console.log(cookies);
});

https.listen(6020, function(){
    console.log('listening on 6020');
});

@UPDATE2

abcdn 发表评论之后,我确实尝试了带有 -n 标志的 wscat,现在出现错误: error: Error: unexpected server response (502)

虽然 nginx error.log 包含: 2017/03/07 13:44:10 [error] 10556#10556: *140 upstream prematurely closed connection while reading response header from upstream

@更新 3

进一步阅读后,我将我的 app.js 转回了 http。

【问题讨论】:

  • 您是否尝试过wscat -n,即wscat --no-check - 跳过证书测试?
  • @abcdn 我刚刚尝试过,更新了我的问题
  • @abcdn 我相信这意味着 nginx 正确处理了请求并且它的节点失败了?
  • 是的,我认为这正是您所说的。我也不确定你是否需要使用https 两次,如果 live_test 正在同一台机器上运行。做什么的?你只需要在 Nginx 和外界之间使用https 即可。我不是网络拓扑专家,但在我看来,Nginx 和 node.js 本地端口之间的流量只在本地循环。
  • @abcdn 你是对的。我确实回到了http版本。更重要的是,我设法找到了问题所在。这是由于在我的实际代码中使用了子域 - 浏览器阻止它,直到我直接转到 URL 并打开不安全的连接。当切换到单域时,它工作得很好!谢谢你的帮助:)

标签: node.js ssl nginx socket.io


【解决方案1】:

var fs = require( 'fs' );
var app = require('express')();
var https        = require('https');
var io = require('socket.io')(https);
var HTTPSOptions = {
    cert: fs.readFileSync('path to ssl certificate file'),
    key: fs.readFileSync('path to ssl key file'),
    requestCert: false,
    rejectUnauthorized: false,
};
HTTPSOptions.agent = new https.Agent(HTTPSOptions);
var httpsServer = https.createServer(HTTPSOptions, app);
io = io.listen(httpsServer, {
    log: false
});

//io.sockets.on('connection', function (sock) {
//    console.log("CONNECTED");
//});

var Redis = require('ioredis');
var redis = new Redis();

redis.psubscribe('*', function () {});

redis.on('pmessage', function (subscribed, channel, message) {
    console.log("channel: " + channel);
    console.log("message: " + message);
    message = JSON.parse(message);
    io.emit(channel + ':' + message.event, message.data);
});

httpsServer.listen(6001, function(){
    console.log('Listening on Port 6001');
});

我花了 3 天的时间来寻找解决方案,这是我完美运行的最终版本。我希望它可以帮助像我一样被卡住的人:)

【讨论】:

  • 是的,你在最后一行有“~”,我认为这就是原因。很高兴您在这里发布您的解决方案。实际上,我确实让 nginx 处理了它正在为另一个应用程序处理的所有 SSL 相关内容。但我们希望有人会遇到这个问题并找到你的答案!
猜你喜欢
  • 2011-09-29
  • 2016-06-06
  • 2017-06-13
  • 2015-08-20
  • 2015-04-01
  • 2014-11-29
  • 2012-09-19
  • 1970-01-01
  • 2015-05-16
相关资源
最近更新 更多