问题
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