NGINX + ssl_verify_client:socket.io保持连接

时间:2015-03-05 15:50:12

标签: ssl nginx socket.io

NGINX在相关部分看起来如此:

listen 9443 ssl;
server_name example.com;

ssl_certificate      mycert.crt;
ssl_certificate_key  mykey.key;
ssl_client_certificate myca.pem;
ssl_verify_client on;

proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_http_version 1.1;
proxy_pass http://127.0.0.1:8443/;

socketio / node.js应用程序如下所示:

var restify                         = require('restify');
var server                          = restify.createServer();
var io                              = require('socket.io')    (server.server);
server.listen(8443, function () {
console.log('socket.io server listening at %s', server.url);
});
io.sockets.on('connection', function (socket) {
console.log("Client connected in io.sockets.on.connection");
socket.on('testfunc', function () {
    console.log("this is testfunc");
});
socket.on('disconnect', function(){
    console.log("Client disconnected");
});
});

index.html看起来像这样:

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<script type="text/javascript" src="socket.io.js"></script>
<script>
$(document).ready(function() {
    var socket = io('https://example.com:9443', {secure: true});
    socket.on('connect', function () {
        socket.emit('testfunc');
    });
});
</script>

NGINX侦听端口9443。 端口8443上的Node.js。

如果这个指令: ssl_verify_client on;

在nginx.conf中删除

,那没问题。客户端连接后,它将在socket.io上调用“testfunc”。工作正常。

如果ssl_verify_client开启;在nginx.conf中会发生以下情况:

客户端似乎想连续连接到socket.io.不是无限循环。它将尝试每1秒连接一次。 emit(testunc)永远不会到达。不在客户端而不在服务器上。

我真的不明白问题是什么。我现在唯一可以看到的,也许是一个线索,就是每一秒 客户端尝试连接的URL具有不同的ID,如下所示:

https://example.com:9443/socket.io/?EIO=3&transport=polling&t=1425570178744-3&sid=A_HsCwcklo30ZlifAAAA
https://example.com:9443/socket.io/?EIO=3&transport=polling&t=1425570179958-5&sid=gU1Nlv6asTakgE0KAAAB
https://example.com:9443/socket.io/?EIO=3&transport=polling&t=1425570181232-11&sid=Oy6ZnW3PZbK8cojHAAAC
https://example.com:9443/socket.io/?EIO=3&transport=polling&t=1425570182456-15&sid=-uK6YnSkYUyjPdI9AAAD

新发现。问题是套接字请求没有发送客户端证书。此外,问题只存在于firefox中(我只对firefox和chrome感兴趣)。在Chrome中它可以工作。

只有在您指示请求发送客户端证书时,才能执行常规的ajax请求:

$.ajax({
        url: 'https://example.com:9443/test',
        type: 'GET',
        xhrFields: {'withCredentials': true}
    }).success(function (value) {
        console.log(value)
        console.log('success');
    }).error(function () {
        console.log(arguments);
        console.log('error');
    });

上述请求适用于两种浏览器。

现在,在进行套接字连接时,它会失败。它在Firefox中失败了。但它适用于Chrome。 我试图找出如何在socket.io上编写一个模仿ajax-request中的“withCredentials”-option的选项..但没有运气。 另外:在Chrome中进行套接字连接工作而不设置任何“withCredentials”选项。听起来Chrome默认发送客户端证书。

更有趣的是:两个浏览器在尝试建立套接字连接时使用了哪些协议?似乎两者都通过调用socket.io并使用轮询作为传输来进行一些测试。然后这两者都依赖于websocket。最后的工作可能是: firefox和chrome都使用websocket连接到服务器。但是,在chrome中,证书是默认发送的(?),而在Firefox中则不是。

0 个答案:

没有答案