9

I previously had a Socket.io script running fine over http, but upgrading to https has broken it. I have installed the cert on the server but no luck. The code for the server setup is:

var https = require('https'),
    fs =    require('fs');

var options = {
    key:    fs.readFileSync('/etc/nginx/ssl/default/54082/server.key'),
    cert:   fs.readFileSync('/etc/nginx/ssl/default/54082/server.crt')
};
var app = https.createServer(options);

var io = require('socket.io').listen(app);

However in the web browser the page fails to connect to it and the console shows a the server responded with a status of 502 (Bad Gateway) response.

Any ideas on if the script set up is wrong? Or perhaps something in the Nginx setup?

Many thanks

Edit: The front end code I'm using to connect:

<script type="text/javascript" src="https://socket.example.com/socket.io/socket.io.js"></script>
<script>
var io = io('https://socket.example.com', { secure: true });
</script>

Edit:: Nginx config:

# FORGE CONFIG (DOT NOT REMOVE!)
include forge-conf/socket.example.co.uk/before/*;

server {
    listen 443 ssl;
    server_name socket.example.co.uk;
    root /home/forge/socket.example.co.uk;

    # FORGE CONFIG (DOT NOT REMOVE!)
    include forge-conf/socket.example.co.uk/server/*;

    location / {    
        proxy_pass https://socket.example.co.uk:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
    }

}

# FORGE CONFIG (DOT NOT REMOVE!)
include forge-conf/socket.example.co.uk/after/*;
samiles
  • 3,768
  • 12
  • 44
  • 71
  • 1
    Are you passing {secure: true} while connecting to server ? http://stackoverflow.com/questions/6599470/node-js-socket-io-with-ssl – Mukesh Sharma Feb 29 '16 at 11:44
  • it is not necessary to proxy to node.js through nginx. the port is open, so connecting with `io.connect(':',{secure:true});` from the client is all you need to do to get up and running. it is not possible to proxy through nginx (and not necessary since node binds to all interfaces, and the domain is routed to your ip:port anyway due to DNS config). i literally upgraded my socket io to https yesterday without problems. – r3wt Feb 29 '16 at 13:54
  • @r3wt So you're saying the domain should be something different? What should it be? I am using the code `var io = io('https://socket.example.com/socketio/socketio.js', { secure: true });` – samiles Mar 02 '16 at 11:48
  • @MukeshSharma That isn't required as long as it a HTTPS url according to the docs. And it doesn't make a difference anyway. – samiles Mar 02 '16 at 15:06
  • i'm not saying that at all. just don't try and proxy to node.js with nginx. nginx will drop the connections every single time. you don't have to config anything on node.js or nginx, as long as node https server can read the valid cert and key for your domain name and its on the same box as node.js, it will work. the request will occur over ssl and end at the open port that your node.js process is using. – r3wt Mar 02 '16 at 16:16
  • @r3wt So just add the code in my question and it should work? It doesn't work though. Are you saying I should get rid of Nginx? Any ideas anyone? :\ – samiles Mar 02 '16 at 16:18
  • 2
    @r3wt :( No need for names. I'm trying my best and you don't have to help me. I'll post the front end code now... – samiles Mar 02 '16 at 16:23
  • 1
    the people who called me on my lack of effort are the ones who made me a better developer. instead of pardoning yourself for your incompetence, you should recognize this as a gift so that you can see the areas where you are deficient and need to improve in. – r3wt Mar 02 '16 at 16:26
  • @r3wt I get it, I'm just not used to being called a swear word, but it's fine, thank you for your help. What effort am I not exerting, what else do I need to do? Happy to put in any effort needed - I've been working on this for 2 days. – samiles Mar 02 '16 at 16:29
  • you are not even suplying a port to connect with. why? your https server also isn't listening on any port? – r3wt Mar 02 '16 at 16:41
  • @r2wt OK I will look into the port. It worked without a port just fine on http which is why I'm confused. I'll try adding a port. – samiles Mar 02 '16 at 17:08
  • Can you see are the ssl files are being read? Can you debug 'options' variable?, also tell me the command how are you lifting your application on server side? – J Bourne Mar 04 '16 at 13:06
  • Have you checked this one? http://stackoverflow.com/questions/30317831/socket-io-nodejs-nginx-ssl Especially the part in location/ { } stating 'upgrade' ? – CherryNerd Mar 07 '16 at 01:33
  • @CreasolDev Yes I have that line in my Nginx config. – samiles Mar 07 '16 at 11:50
  • @Sai That is in the question, do you need something else? – samiles Mar 07 '16 at 11:50
  • yes, may be those cert values are readable or not, since they are in /etc your app should have sudo permissions or something else. 502 bad gateway means nginx received an invalid response from the node application, also can you paste nginx configuration, it will be helpful to debug – J Bourne Mar 07 '16 at 12:47
  • @Sai Would the script run if they weren't readable? As the script is running and receiving events and outputting them on the command line as expected - it's just the front end that won't connect. Do you have any idea how I'd check if the certs were being read correctly? – samiles Mar 07 '16 at 12:55
  • @Sai I have added Nginx config – samiles Mar 07 '16 at 12:58
  • Even Im not sure, if it throws an error, but we too had a similar scenario( not socket.io but with express), we made nginx https while running the express on http, and configure. If you can paste nginx configuration, it will be helpful – J Bourne Mar 07 '16 at 13:11
  • I see it now, your proxy_pass is wrong, the moment you say https, your default port becomes 443, while you are running two things on same port one of the your node app would have got killed on your nginx won't read it. so what you can do is you can run the socket.io on http, since your nginx has https, it will take care of the encryption. – J Bourne Mar 07 '16 at 13:15
  • @Sai OK I will look into that. The reason I tried to set up HTTPS is that Chrome was refusing to load over HTTP citing security concerns. I will look into it further though... – samiles Mar 07 '16 at 14:26
  • @Sai Yeah the problem with this is that as the webpage is SSL, Chrome/Safari won't load the script over HTTP and the console gives a warning about refusing to load scripts over HTTP. Has to be SSL I guess. – samiles Mar 07 '16 at 15:14
  • You can try cors npm module for that problem accessing http over https. It worked for us. – J Bourne Mar 07 '16 at 17:07
  • I'll look into that module @Sai thank you. For now I have taken the coward's way out and am just using Pusher... Took about 15 minutes to set up! – samiles Mar 07 '16 at 17:17
  • Has this been solved? Looks like @samiles used a different solution, I am having the exact same problem however I do not have access to the server or the config files. – Cham Jun 27 '19 at 04:48

3 Answers3

5
  1. make sure that your domain points to your server.
  2. make sure that an nginx server block is running for your domain with ssl enabled.
  3. remove any location blocks from your nginx config attempting to proxy to the port you are running your socket.io server on.
  4. make sure your ssl certificate is valid.
  5. connect with io.connect() instead of the way you are doing. leave out the protocol portion of the url (https://).
  6. use sudo killall -9 node from the commandline to kill any zombie processes that might be lingering and bound to your port. this sometimes happens with socket.io when it fails to shutdown properly.

example from my own code:

var socket = io.connect('dev.somedomain.com:3000',{secure:true});

server example from my own domain:

var fs = require('fs'),
    https = require('https'),
    config = JSON.parse(fs.readFileSync('./config.json','utf-8')),
    serverOpts = {
        key: fs.readFileSync(config.server.key),
        cert: fs.readFileSync(config.server.cert)
    },
    server = https.createServer(serverOpts,function(req,res){}),
    io = require('socket.io').listen(server);

io.on('connection', function(socket){
   console.log('houston, we have lift off');
});

server.listen(config.port, function(){
    log('listening on *:%d',config.port);
});

obviously i'm reading the path to my certificate and key file from a config.json file but you should get the idea right?

r3wt
  • 4,642
  • 2
  • 33
  • 55
  • Not had any luck with any of this. Thanks anyway for your help. Maybe there's something else in my setup somewhere breaking something... I'm just giving up now... – samiles Mar 03 '16 at 10:26
3

The 502 (Bad Gateway) indicates that the nginx service tried to contact the proxy server but failed. The line in the nginx config

 proxy_pass https://socket.example.co.uk:3000;

seems to be the issue. Could not see from your nodejs code that the port 3000 is being used.

Anil Kumar
  • 104
  • 6
-4

I've same issue but with apache2, I solve it by add this line to my vhost config

SSLProxyEngine on SSLProxyVerify none SSLProxyCheckPeerCN off SSLProxyCheckPeerName off SSLProxyCheckPeerExpire off

Ipoel
  • 1
  • 1