Socket.io with Apache Proxy (Connection refused)

半世苍凉 提交于 2020-08-10 19:14:05

问题


I have been implementing Socket.io in a node.js server and SSL. I was first facing an SSL handshake error which I have resolved successfully.

I do not expose the node.js port directly to the internet and all socket connections are proxied through a public Apache HTTPS server.

The problem is that when trying to connect to the socket the browser will return the following error:

WebSocket connection to 'wss://domain.com:4923/socket.io/?EIO=3&transport=websocket' failed: Connection closed before receiving a handshake response

My Apache virtual host is:

<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  

        SSLProxyCheckPeerName false    

        # 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>

Then the node.js server implementation is the following:

const port = 4923;

const fs = require('fs');

var options = {
    key: fs.readFileSync('/etc/ssl/private/vunkers.com.key'),
    cert: fs.readFileSync('/etc/ssl/certs/vunkers.com.crt'),
};

var express = require('express');
var app = express();
app.set("trust proxy", '127.0.0.1');
app.use(function(req, res, next) {
    res.header("Access-Control-Allow-Origin", "*");
    res.header("Access-Control-Allow-Headers", "X-Requested-With");
    res.header("Access-Control-Allow-Headers", "Content-Type");
    res.header("Access-Control-Allow-Methods", "PUT, GET, POST, DELETE, OPTIONS");
    res.header("Access-Control-Allow-Credentials", "true");
    next();
});

var server = require('https').createServer(options, app);
var io = require('socket.io')(server, {
    path: '/socket',
    origins: '*:*'
});
server.listen(port);

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

io.on('connection', (socket) => {
    console.log("New socket connection: " + socket.id);

    socket.on('login-request', (username, password) => {
        console.log("Login request: ");
        console.log(" - Username: " + username);
        console.log(" - Password: " + password);
    });

});

Finally, my socket client is this:

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

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

function onWindowLoad() {
        createConnection();
}

window.onload = onWindowLoad;

I have been stuck with this and I would want to know what I am missing here.

Update

I have solved the current error by adding the SSL CA file in the virtual host:

SSLCertificateChainFile /etc/letsencrypt/live/domain1.com/cert.ca.pem

But now I have a connection refused error:

WebSocket connection to 'wss://domain.com:4923/socket.io/?EIO=3&transport=websocket' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED

来源:https://stackoverflow.com/questions/63292065/socket-io-with-apache-proxy-connection-refused

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!