admin管理员组

文章数量:1287579

As always I have searched my fingers bloody finding an answer to my issue, so I am reaching out to all you geniuses again! :)

I have set up a Node.js server with socket.io (using express) and it runs nice using port 8443. Well it runs :). Since many of my customer doesn't seem to allow traffic on port 8443 they are not able to use my services.

I am wondering how to setup Node.js on port 443 since the site using the Node-server is already using this port (Https). If I try to use port 443 on my Node-server i get: warn - error raised: Error: listen EACCES

Part of my Node-js code:

var fs = require('fs');
var https = require('https');
var express = require('express');
var socket = require('socket.io');
var port = 8443;

var sslOptions = {
  pfx: fs.readFileSync('mykey.pfx'),
     passphrase: ********
};

var app = express();

app.all('/*', function(req, res, next) {
  res.header("Access-Control-Allow-Origin", "*");
  res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
  res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, Content-Length, X-Requested-With, *');
  next();
});

var server = https.createServer(sslOptions, app);

var io = socket.listen(server, {
    "log level" : 1,
    "match origin protocol" : true,
    "transports" : ['websocket', 'flashsocket'
   , 'xhr-polling'
   , 'jsonp-polling']
});

//No need to list all my socket events I guess

server.listen(port);

Client code to connect to my Node server:

var socket = io.connect("https://www.*MYWEBSITE*", { secure: true, port: 8443});

As always I have searched my fingers bloody finding an answer to my issue, so I am reaching out to all you geniuses again! :)

I have set up a Node.js server with socket.io (using express) and it runs nice using port 8443. Well it runs :). Since many of my customer doesn't seem to allow traffic on port 8443 they are not able to use my services.

I am wondering how to setup Node.js on port 443 since the site using the Node-server is already using this port (Https). If I try to use port 443 on my Node-server i get: warn - error raised: Error: listen EACCES

Part of my Node-js code:

var fs = require('fs');
var https = require('https');
var express = require('express');
var socket = require('socket.io');
var port = 8443;

var sslOptions = {
  pfx: fs.readFileSync('mykey.pfx'),
     passphrase: ********
};

var app = express();

app.all('/*', function(req, res, next) {
  res.header("Access-Control-Allow-Origin", "*");
  res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
  res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, Content-Length, X-Requested-With, *');
  next();
});

var server = https.createServer(sslOptions, app);

var io = socket.listen(server, {
    "log level" : 1,
    "match origin protocol" : true,
    "transports" : ['websocket', 'flashsocket'
   , 'xhr-polling'
   , 'jsonp-polling']
});

//No need to list all my socket events I guess

server.listen(port);

Client code to connect to my Node server:

var socket = io.connect("https://www.*MYWEBSITE*.", { secure: true, port: 8443});
Share Improve this question edited Jun 19, 2014 at 6:48 Joakim M asked Jun 16, 2014 at 5:37 Joakim MJoakim M 1,8032 gold badges15 silver badges29 bronze badges 7
  • I would answer you cant, because only one service can listen on the same port, otherwise you don't know how should accept each call. So short of putting a proxy in-front of both, and understanding the different requests, and forwarding to the correct services on there own ports, but that ether requires their service to move to a different port, so the proxy can sit on 443. Or I could be wrong. – Simeon Pilgrim Commented Jun 16, 2014 at 5:45
  • But can one say that 443 is the "default" https port? Is there any other port that is considered to be "default" Node.js which all my customers firewalls will accept? – Joakim M Commented Jun 16, 2014 at 8:12
  • 1 I'm having the same issue. Is it possible to setup proxy in such a way that the request is received in 443 and then it is redirected to node server? I tried it once but when socket switches to ws:// instead of https:// I don't know what to do. – user1741851 Commented Jun 16, 2014 at 8:41
  • @JoakimM Do you have an access to webserver of the site listening 443 port? If so, you can proxy all requests starting with /socket.io to 8443 port. Doing so firewalls will "see" only 443 traffic, but some advanced webserver configuring might be required. Here is an example of proxying websocket traffic with nginx webserver – Oleg Commented Jun 22, 2014 at 16:19
  • Is there a way to use http-proxy in Node js to do this instead? nginx seems to plex for me (at first glance). – Joakim M Commented Jun 23, 2014 at 5:19
 |  Show 2 more ments

3 Answers 3

Reset to default 6 +50

I think you've asked a couple different questions here. I'll answer the first one on it's own and it should solve your original problem, but some others have brought up a couple handy deployment options that are worth knowing too.

First, you don't need to run the socket.io server on it's own port. You can just have the socket.io server bind itself to the express app. For example:

// ... require stuff
var app = express();

// ... set up your express middleware, etc

var server = https.createServer(sslOptions, app);
// attach your socket.io server to the express server
var io = require("socket.io").listen(server);
server.listen(port);

Regardless of how you set up your node application it's worth knowing how to set up nginx as a reverse proxy. This is nice because you don't have to be root to use ports < 1024 when running your node app and you can bind many applications to the same IP address through virtual hosts.

Here's an nginx server configuration block that will reverse proxy a node application (and supports websockets).

server {
    listen 80;
    server_name app. www.app. # a list of hosts for this application
    access_log /var/log/nginx/access/app.log; # you'll need to create /var/log/nginx/access
    error_log  /var/log/nginx/error/app.log; # and you'll need to create /var/log/nginx/error

    # prevents 502 bad gateway error
    large_client_header_buffers 8 32k;

    location / {

        proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;

        proxy_set_header Accept-Encoding "";
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-NginX-Proxy true;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;

        proxy_buffers 8 32k;
        proxy_buffer_size 64k;

        proxy_set_header X-Forwarded-Proto $scheme;

        proxy_pass http://127.0.0.1:8000; # put the port of your node app here
        proxy_redirect off;
    }
}

You get Error: listen EACCES because you cannot use "privileged ports" (ports < 1024) as non-root user. You could run your node process as root, but don't do that. Better have nginx (battle tested) handle the HTTPS and proxying for you.

See for some info http://nginx./blog/websocket-nginx/

As already mentioned:

  1. you can't have two services bound to the same port. If IIS (or apache or whatever) is listening on port 443, you must turn it off first.

  2. socket.io and your app listen on the same port.

  3. if you want to bind to a low numbered port (<1024) you need to start your app as root but then de-escalate privileges so that it runs with the least privileges necessary. This can be acplished using process.setuid:

This example was made using express 4 and socketio 1.0:

var debug = require('debug')('httpssetuid');
var app = require('../app');
var http = require('http');
var https = require('https');
var fs = require('fs');
var exec = require('child_process').exec;
var EventEmitter = require('events').EventEmitter;
var ioServer = require('socket.io');

var startupItems = [];
startupItems.httpServerReady = false;
startupItems.httpsServerReady = false;

var ee = new EventEmitter();

ee.on('ready', function(arg) {
  startupItems[arg] = true;
  if (startupItems.httpServerReady && startupItems.httpsServerReady) {
    var id = exec('id -u ' + process.env.SUDO_UID, function(error, stdout, stderr) {
      if(error || stderr) throw new Error(error || stderr);
      var uid = parseInt(stdout);
      process.setuid(uid);
      console.log('de-escalated privileges. now running as %d', uid);
      setInterval(function cb(){
        var rnd = Math.random();
        console.log('emitting update: %d', rnd);
        io.emit('update', rnd);
      }, 5000);
    });
  };
});

app.set('http_port', process.env.PORT || 80);
app.set('https_port', process.env.HTTPS_PORT || 443);

var httpServer = http.createServer(app);

var opts = {
  pfx: fs.readFileSync('httpssetuid.pfx')
};
var httpsServer = https.createServer(opts, app);

var io = new ioServer();

httpServer.listen(app.get('http_port'), function(){
  console.log('httpServer listening on port %d', app.get('http_port'));
  ee.emit('ready', 'httpServerReady');
});

httpsServer.listen(app.get('https_port'), function(){
  console.log('httpsServer listening on port %d', app.get('https_port'));
  ee.emit('ready', 'httpsServerReady');
});

io.attach(httpServer);
io.attach(httpsServer);

io.on('connection', function(socket){
  console.log('socket connected: %s', socket.id);
});

If stopping IIS is not an option, your best bet is to configure it as a reverse proxy for your node app.

本文标签: javascriptHow to configure Socketio to run on same port on httpsStack Overflow