Is there a way to serve two https sites on the same port from node alone (i.e. without something like nginx)?
I'm using the https module, for which SSL options (e.g. key/cert/ca) are passed into createServer. I tried creating two https servers, each listening to a different hostname, and each with SSL options specific to that hostname:
require('https').createServer(sslOptsForFoo, expressApp).listen(443, 'foo.com');
require('https').createServer(sslOptsForBar, expressApp).listen(443, 'bar.com');
But this throws an error:
Error: listen EADDRINUSE
Another idea is to create a single server rather than two, and to use different SSL options depending on the request's hostname, but I'm not sure if this is possible.
You can only do this with SNI so you may want to check for SNI support with various browsers first.
Here's one way to do SNI in node:
var https = require('https'),
fs = require('fs');
// default for non-matching requests
var serverOptions = {
key: fs.readFileSync('default.pem'),
cert: fs.readFileSync('default.crt')
};
var SNIContexts = {
'foo.com': {
key: fs.readFileSync('foo.com.pem'),
cert: fs.readFileSync('foo.com.crt')
},
'bar.com': {
key: fs.readFileSync('bar.com.pem'),
cert: fs.readFileSync('bar.com.crt')
}
};
var server = https.createServer(serverOptions, function(req, res) {
res.end('Hello world via ' + req.socket.cleartext.servername);
});
server.addContext('foo.com', SNIContexts['foo.com']);
server.addContext('bar.com', SNIContexts['bar.com']);
server.listen(443, function() {
console.log('Listening on 443');
});
Related
I am using Node and express.js to build my server and I setup my https server (essentially) like this:
const privateKey = fs.readFileSync('./credentials/rippal.key', 'utf8');
const certificate = fs.readFileSync('./credentials/rippal.crt', 'utf8');
const credentials = {key: privateKey, cert: certificate};
const app = express();
setup(app, config);
let httpsServer = https.createServer(credentials, app)
httpsServer.listen(3333, function () {
console.log("Server listening on port 3333...\n");
});
with self-signed certificates, it still works to http://localhost:3333 but when I tried to access https://localhost:3333, Chrome told me
This site can’t provide a secure connection
localhost sent an invalid response.
ERR_SSL_PROTOCOL_ERROR
how should I access https://localhost:3333?
Thanks!
Is it somehow possible to create a Node.js https server in cloud9 IDE?
Below is my example of simple https server setup in Node.js.
var https = require('https');
var fs = require('fs');
var app = require('./app');
// SSL Configuration
var ca_names = ['CERT-NAME_1', 'CERT-NAME_2', 'CERT-NAME_3'];
var options = {
key: fs.readFileSync('./folder/server.key'),
cert: fs.readFileSync('./folder/server.crt'),
ca: ca_names.map(function(n) {
return fs.readFileSync('./eid/ca/' + n + '.crt');
}),
//crl: ca_names.map(function(n) { return fs.readFileSync('/eid/ca/' + n + '.crl'); }),
requestCert: false,
rejectUnauthorized: false
};
var server = https.createServer(options, app);
server.listen(process.env.PORT || 8081, process.env.IP || "0.0.0.0");
console.log('server listening on port: ' + process.env.PORT);
when I try to connect to the server then I am getting following error:
"ECONNRESET: Request could not be proxied!"
I think the problem is you are trying to listen to both HTTP and HTTPS.
c9 works as a proxy so you only need to listen on HTTP even though you are trying to use HTTPS. Try not listening to HTTPS and it should work. (more info on this)
But, if you really need HTTPS, in that case you can use a proxy like Nginx to internally proxy requests over HTTPS.(more info on this)enter link description here
i'm having a problem here, this message is appearing when i test my SSL:
Certificate chain is incomplete.
I already create the http and the https server in my entry point file, and is running in some browsers without problem, but in others appear the message saying the site is not safe because the chain is incomplete.
How can i install properly the SSL to make the chain complete?
This is how i do:
SSL FOLDER
|- credentials.js
|- site.pem
|- site-cert.pem
|- site-ca.pem
In my credentials.js i have:
var fs = require('fs');
var credentials = {
key: fs.readFileSync(__dirname + '/mysite.pem', 'utf8'),
cert: fs.readFileSync(__dirname + '/mysite-cert.pem', 'utf8'),
ca: fs.readFileSync(__dirname + '/mysite-ca.pem', 'utf8'),
passphrase: 'secretphrase'
};
module.exports = credentials;
And in my entry point i have:
var app = require('../app');
var http = require('http');
var https = require('https');
var credentials = require('./ssl/credentials');
http.createServer(app).listen(3000, app.get('ip'), function() {
console.log('Running on port 3000, in ' + app.get('env') + ' mode.');
});
https.createServer(credentials, app).listen(443, app.get('ip'), function() {
console.log('Running on port 443, in ' + app.get('env') + ' mode.');
});
Maybe i forget something?
I'm not getting way the problem with the chain.
You may be required to add intermediate CA certificates that chain up to the root CA cert. See How to setup EV Certificate with nodejs server
Check your domain with an online SSL Test tool to see if all certificates in the chain are being sent by your server.
How to do socket.io implementation in Webrtc Video calling?
A little bit overload but it works: SocialVidRTC
I understand from your question that you already have a WebRTC project and some signalling mechanism in server.js , possibly websockets .
To replace this with socket.io or any other signalling as SIP / XHR / AJAX etc , you need to replace server.js with new socket.io based code for request and response .
Follow these steps :
create a https server ( since webrtc pages capture web cam input only from secure origins) for socket.io. Assign server to an variable say app.
var fs = require('fs');
var https = require('https');
var options = {
key: fs.readFileSync('ssl_certs/server.key'),
cert: fs.readFileSync('ssl_certs/server.crt'),
ca: fs.readFileSync('ssl_certs/ca.crt'),
requestCert: true,
rejectUnauthorized: false
};
var app = https.createServer(options, function(request, response){
request.addListener('end', function () {
file.serve(request, response);
}).resume();
});
app.listen(8081);
here server.key , server.crt and ca.crt are fake ssl certs and 8081 is the https port I have selected .
you can reuse the same https server for hosting the webpages also.
listen on this same port for socket.io using app defined earlier
var io = require('socket.io').listen(app, {
log: false,
origins: '*:*'
});
io.set('transports', [
'websocket'
]);
I choose only websocket but you can set other types of transport too such as
socket.set('transports', [
'websocket'
, 'flashsocket'
, 'htmlfile'
, 'xhr-polling'
, 'jsonp-polling'
]);
Now implement signalling specific functions and calls such as ,
io.sockets.on('connection', function (socket) {
...
socket.on('webrtc-joinchannel',function(data){
var resp=joinChannel(data);
socket.emit('resp-webrtc-joinchannel', resp);
});
...
});
Note : I am using socket.io v0.9 .
If yo want a example implementation you can view any sample projects such as here
I have a typical web application in Node that is utilizing the Express framework and the session middleware. I am also using Socket.io for certain dynamic parts of my application (currently, this is a chat mechanism, but that's tangential). I've been able to successfully set up sessions and socket.io on their own, but would like to combine them (EG: to associate socket chat messages with user accounts without hitting the database).
It should be noted (and I can see this being a possible issue point), I am running two express servers on different ports: one for regular HTTP traffic, and one for HTTPS traffic. However, I am having both servers undergo an idential configuration and share the same session store. Sessions do persist for me between http and https pages. The session is being set initially via a page served from HTTPS and the socket.io page is vanilla HTTP.
I'm following the guide located here to achieve what I am looking for regarding integrating socket.io and sessions. However, within the authorization function, data.headers.cookie is never set, despite the session-based portions of my application working as expected. What's more strange is that after setting a session, if I do a console.log(document.cookie) from within the browser, I get an empty string, but when I look at my cookies with the Firefox developer toolbar, there is an SID cookie for both express and connect.
Here is the relevant portion of the server code:
var config = {
ip : "127.0.0.1",
httpPort : 2031,
httpsPort : 2032
};
var utils = require("./utils"),
express = require('express'),
fs = require('fs'),
parseCookie = require('./node_modules/express/node_modules/connect').utils.parseCookie,
routes = require('./routes')(config);
var httpsOpts = {
key : fs.readFileSync("cert/server-key.pem").toString(),
cert: fs.readFileSync("cert/server-cert.pem").toString()
};
var app = express.createServer(),
https = express.createServer(httpsOpts),
io = require("socket.io").listen(app, { log: false}),
helpers = require("./helpers.js"),
session = new express.session.MemoryStore(),
sessionConfig = express.session({
store : session,
secret : 'secret',
key : 'express.sid',
cookie : {maxAge : 60 * 60 * 1000}
}); //share this across http and https
configServer(app);
configServer(https);
//get SID for using sessions with sockets
io.set('authorization', function(data, accept){
if(data.headers.cookie){
data.cookie = parseCookie(data.headers.cookie);
data.sessionID = data.cookie['express.sid'];
} else {
return accept("No cookie transmitted", false);
}
accept(null, true);
});
io.sockets.on('connection', function(socket){
//pull out session information in here
});
function configServer(server) {
server.configure(function(){
server.dynamicHelpers(helpers.dynamicHelpers);
server.helpers(helpers.staticHelpers);
server.set('view options', { layout: false });
server.set('view engine', 'mustache');
server.set('views', __dirname + '/views');
server.register(".mustache", require('stache'));
server.use(express.static(__dirname + '/public'));
server.use(express.bodyParser());
server.use(express.cookieParser());
server.use(sessionConfig);
});
}
And here's the relevant code on the client:
<script src="/socket.io/socket.io.js"></script>
<script type="text/javascript">
$(document).ready(function(){
var socket = io.connect('http://127.0.0.1'); //make sure this isn't localhost!
socket.on('server', function(data){
//socket logic is here
});
}
</script>
UPDATE
Even after setting a cookie manually (and not just a session variable) in the route for the page that is using SocketIO, the cookies portion of the request is still absent.
I never would have thought of this until told to look at the initialization on the client side. I changed the address from localhost to the explicit IP (127.0.0.1) and the cookies are now being sent with the header in Socket.IO. I'm not sure if this is obvious or not, as I assumed localhost was being mapped to 127.0.0.1 anyway.