本文介绍了将Socket.IO与Apache,Node.js,SSL和CloudFlare(HTTP 500)结合使用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在创建一个网站,该网站将连接到Node.js Socket.IO WebSocket.该节点服务器在端口4923上运行,并且Socket.IO节点在端点/socket上配置.我不想通过https://domain1.com:4932/socket进行连接,而是通过https://domain1.com/socket.io进行连接,该连接指向我的Apache服务器.防火墙阻止端口4932以便阻止https://domain1.com:4932/socket.

I am creating a website that will connect to a Node.js Socket.IO WebSocket. This node server is running on the port 4923 and the Socket.IO node is configured on the endpoint /socket. I do not want to connect via https://domain1.com:4932/socket but instead from https://domain1.com/socket.io which points to my Apache Server. The firewall blocks the port 4932 in order to block https://domain1.com:4932/socket.

Apache服务器应代理从https://domain1.com/socket.iohttps://localhost:4932/socket SSL的所有连接. SSL证书是让我们加密"的证书.

The Apache Server should proxy all connections from https://domain1.com/socket.io to https://localhost:4932/socket SSL included. The SSL cert is a cert from Let's Encrypt.

创建新连接后,Apache和Node.JS服务器之间的SSL握手失败.

When a new connection is created the SSL handshake between the Apache and Node.JS servers fails.

我的网站流量通过Cloudflare激活了完全通用SSL.

My website traffic goes through Cloudflare with the Full universal SSL activated.

在apache虚拟主机中,我具有以下配置:

In the apache virtual host, I have the following configuration:

<VirtualHost  *:443>
        ...

        SSLEngine On
        SSLProxyEngine On

        SSLCertificateFile /etc/letsencrypt/live/domain1.com/fullchain.pem
        SSLCertificateKeyFile /etc/letsencrypt/live/domain1.com/privkey.pem
        Include /etc/letsencrypt/options-ssl-apache.conf

        # Handle wss proxy connections
        RewriteEngine On
        RewriteCond %{REQUEST_URI}  ^/socket.io             [NC]
        RewriteCond %{QUERY_STRING} transport=websocket     [NC]
        RewriteRule /(.*)           ws://localhost:4923/$1 [P,L]

        # Autogenerated ProxyPass
        ProxyPass        /socket.io http://localhost:4923/socket
        ProxyPassReverse /socket.io http://localhost:4923/socket

        ...
</VirtualHost>

我的通过HTTPS的node.js服务器:

My node.js server via HTTPS:

const port = 4923;

const fs = require('fs');

var options = {
    key: fs.readFileSync('/etc/letsencrypt/live/domain1.com/privkey.pem'),
    cert: fs.readFileSync('/etc/letsencrypt/live/domain1.com/fullchain.pem'),
};

var app = require('https').createServer(options);
var io = require('socket.io')(app, {
    path: '/socket',
    serveClient: false,
    pingInterval: 10000,
    pingTimeout: 5000,
    cookie: false
});

app.listen(port);

io.httpServer.on('listening', function () {
    console.log("Listening on", port);
});

io.on('connect', (socket) => {
    console.log("Socket connected: " + socket.id);
    socket.on('disconnect', () => {
        console.log("Socket disconnected: " + socket.id);
    });
    socket.on('download-request', (id) => {
        onDownloadRequest(socket, id);
    });
});

function onDownloadRequest(socket, id) {
    console.log("Request from " + socket.id + " and video id: " + id);
}

与此同时,在客户端,我在窗口加载时创建了一个新的WebSocket连接,然后在单击按钮时发送了消息.

Meanwhile, on the client-side, I create a new WebSocket connection on window load, and then I send the message when a button is clicked.

...
const websocketOptions = {
        server : {
                protocol : 'https://',
                host     : 'domain1.com',
                port     : 443,
                endpoint : '/socket.io'
        }
};

function requestDownload() {
        if (isAnySelected() || socket !== null) {
                console.log(document.getElementsByClassName("download-input-box")[0].value);
                socket.emit('download-request', {id: document.getElementsByClassName("download-input-box")[0].value});
        }
}

function createConnection() {
        console.log("Creating websocket connection!");
        socket = io.connect(websocketOptions.server.protocol
                        + websocketOptions.server.host
                        + ':'
                        + websocketOptions.server.port
                        + websocketOptions.server.endpoint,
                        {transport: 'websocket'});
}

function onWindowLoad() {
        createConnection();
}

window.onload = onWindowLoad;

这将导致响应代码500以及apache错误日志中的以下错误消息:

This results in a response code 500 and this error message in the apache error log:

AH00898: Error during SSL Handshake with remote server returned by /socket.io/, referer: https://domain1.com/

我做错了什么?感谢您的帮助.

What am I doing wrong? Any help is appreciated.

现在SSL握手问题已解决,我遇到了一个新问题.您可以在此处查看.

Now that the SSL handshake problem has been solved a new problem has been happening to me. You can view it here.

推荐答案

您无法SSL本地主机",因此有三个选项:

You can't SSL "localhost", so there is three options:

  • 使用一个可以请求SSL的域

  • Use one domain that you can request an SSL

使用"localhost"使用HTTP(不是s)

Use "localhost" with HTTP ( not s )

使用"localhost"使用SSL,但禁用"SSLProxyCheckPeerName";进入Apache2配置. (请参见参考)

Use "localhost" with SSL but disabling "SSLProxyCheckPeerName" into Apache2 configuration. ( See this reference )

关闭SSLProxyCheckPeerName

SSLProxyCheckPeerName off

这篇关于将Socket.IO与Apache,Node.js,SSL和CloudFlare(HTTP 500)结合使用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-11 12:47