Merge branch 'master' of github.com:coolaj86/node-ssl-root-cas
This commit is contained in:
		
						commit
						fc60d1cd03
					
				
							
								
								
									
										181
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										181
									
								
								README.md
									
									
									
									
									
								
							@ -119,3 +119,184 @@ The same dissolution from the terminal would be
 | 
			
		||||
export NODE_TLS_REJECT_UNAUTHORIZED="0"
 | 
			
		||||
node my-service.js
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
# Index
 | 
			
		||||
 | 
			
		||||
Other information you might want to know while you're here.
 | 
			
		||||
 | 
			
		||||
## Generating an SSL Cert
 | 
			
		||||
 | 
			
		||||
Just in case you didn't know, here's how you do it:
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
openssl req -new -newkey rsa:2048 -nodes -keyout server.key -out server.csr
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
**DO NOT FILL OUT** email address, challenge password, or optional company name
 | 
			
		||||
 | 
			
		||||
However, you *should* fill out country name, FULL state name, locality name, organization name.
 | 
			
		||||
 | 
			
		||||
*organizational unit* is optional.
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
cat server.csr
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
That creates a sha-1 hash.
 | 
			
		||||
 | 
			
		||||
When you submit that to the likes of RapidSSL you'll get back an X.509 that you should call `server.crt` (at least for the purposes of this mini-tutorial).
 | 
			
		||||
 | 
			
		||||
You cannot use "bundled" certificates (`.pem`) with node.js.
 | 
			
		||||
 | 
			
		||||
### A single HTTPS server
 | 
			
		||||
 | 
			
		||||
Here's a complete working example:
 | 
			
		||||
 | 
			
		||||
```javascript
 | 
			
		||||
'use strict';
 | 
			
		||||
 | 
			
		||||
var https = require('https')
 | 
			
		||||
  , fs = require('fs')
 | 
			
		||||
  , connect = require('connect')
 | 
			
		||||
  , app = connect()
 | 
			
		||||
  , sslOptions
 | 
			
		||||
  , server
 | 
			
		||||
  , port = 4080
 | 
			
		||||
  ;
 | 
			
		||||
 | 
			
		||||
require('ssl-root-cas/latest')
 | 
			
		||||
  .inject()
 | 
			
		||||
  .addFile(__dirname + '/ssl/Geotrust Cross Root CA.txt')
 | 
			
		||||
  .addFile(__dirname + '/ssl/Rapid SSL CA.txt')
 | 
			
		||||
  ;
 | 
			
		||||
 | 
			
		||||
sslOptions = {
 | 
			
		||||
  key: fs.readFileSync('./ssl/server.key')
 | 
			
		||||
, cert: fs.readFileSync('./ssl/server.crt')
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
app.use('/', function (req, res) {
 | 
			
		||||
  res.end('<html><body><h1>Hello World</h1></body></html>');
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
server = https.createServer(sslOptions, app).listen(port, function(){
 | 
			
		||||
  console.log('Listening on https://' + server.address().address + ':' + server.address().port);
 | 
			
		||||
});
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### Multiple HTTPS servers using SNI
 | 
			
		||||
 | 
			
		||||
I know this works - because I just bought two SSL certs from RapidSSL (through name.com),
 | 
			
		||||
a Digital Ocean VPS,
 | 
			
		||||
and played around for an hour until it did.
 | 
			
		||||
 | 
			
		||||
:-)
 | 
			
		||||
 | 
			
		||||
File hierarchy:
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
webapps/
 | 
			
		||||
└── vhosts
 | 
			
		||||
    ├── aj.the.dj
 | 
			
		||||
    │   └── ssl
 | 
			
		||||
    │       ├── server.crt
 | 
			
		||||
    │       └── server.key
 | 
			
		||||
    ├── ballprovo.com
 | 
			
		||||
    │   └── ssl
 | 
			
		||||
    │       ├── server.crt
 | 
			
		||||
    │       └── server.key
 | 
			
		||||
    ├── server.js
 | 
			
		||||
    └── ssl
 | 
			
		||||
        ├── Geotrust Cross Root CA.txt
 | 
			
		||||
        └── Rapid SSL CA.txt
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#### `server.js`
 | 
			
		||||
 | 
			
		||||
```javascript
 | 
			
		||||
'use strict';
 | 
			
		||||
 | 
			
		||||
var https = require('https')
 | 
			
		||||
  , http = require('http')
 | 
			
		||||
  , fs = require('fs')
 | 
			
		||||
  , crypto = require('crypto')
 | 
			
		||||
  , connect = require('connect')
 | 
			
		||||
  , vhost = require('vhost')
 | 
			
		||||
 | 
			
		||||
  // connect / express app
 | 
			
		||||
  , app = connect()
 | 
			
		||||
 | 
			
		||||
  // SSL Server
 | 
			
		||||
  , secureContexts = {}
 | 
			
		||||
  , secureOpts
 | 
			
		||||
  , secureServer
 | 
			
		||||
  , securePort = 4443
 | 
			
		||||
 | 
			
		||||
  // force SSL upgrade server
 | 
			
		||||
  , server
 | 
			
		||||
  , port = 4080
 | 
			
		||||
 | 
			
		||||
  // the ssl domains I have
 | 
			
		||||
  , domains = ['aj.the.dj', 'ballprovo.com']
 | 
			
		||||
  ;
 | 
			
		||||
 | 
			
		||||
require('ssl-root-cas/latest')
 | 
			
		||||
  .inject()
 | 
			
		||||
  .addFile(__dirname + '/ssl/Geotrust Cross Root CA.txt')
 | 
			
		||||
  .addFile(__dirname + '/ssl/Rapid SSL CA.txt')
 | 
			
		||||
  ;
 | 
			
		||||
 | 
			
		||||
function getAppContext(domain) {
 | 
			
		||||
  // Really you'd want to do this:
 | 
			
		||||
  // return require(__dirname + '/' + domain + '/app.js');
 | 
			
		||||
 | 
			
		||||
  // But for this demo we'll do this:
 | 
			
		||||
  return connect().use('/', function (req, res) {
 | 
			
		||||
    console.log('req.vhost', JSON.stringify(req.vhost));
 | 
			
		||||
    res.end('<html><body><h1>Welcome to ' + domain + '!</h1></body></html>');
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
domains.forEach(function (domain) {
 | 
			
		||||
  secureContexts[domain] = crypto.createCredentials({
 | 
			
		||||
    key:  fs.readFileSync(__dirname + '/' + domain + '/ssl/server.key')
 | 
			
		||||
  , cert: fs.readFileSync(__dirname + '/' + domain + '/ssl/server.crt')
 | 
			
		||||
  }).context;
 | 
			
		||||
 | 
			
		||||
  app.use(vhost('*.' + domain, getAppContext(domain)));
 | 
			
		||||
  app.use(vhost(domain, getAppContext(domain)));
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
// fallback / default domain
 | 
			
		||||
app.use('/', function (req, res) {
 | 
			
		||||
  res.end('<html><body><h1>Hello World</h1></body></html>');
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
//provide a SNICallback when you create the options for the https server
 | 
			
		||||
secureOpts = {
 | 
			
		||||
  //SNICallback is passed the domain name, see NodeJS docs on TLS
 | 
			
		||||
  SNICallback: function (domain) {
 | 
			
		||||
    console.log('SNI:', domain);
 | 
			
		||||
    return secureContexts[domain];
 | 
			
		||||
  }
 | 
			
		||||
  // fallback / default domain
 | 
			
		||||
  , key:  fs.readFileSync(__dirname + '/aj.the.dj/ssl/server.key')
 | 
			
		||||
  , cert: fs.readFileSync(__dirname + '/aj.the.dj/ssl/server.crt')
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
secureServer = https.createServer(secureOpts, app).listen(securePort, function(){
 | 
			
		||||
  console.log("Listening on https://localhost:" + secureServer.address().port);
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
server = http.createServer(function (req, res) {
 | 
			
		||||
  res.setHeader(
 | 
			
		||||
    'Location'
 | 
			
		||||
  , 'https://' + req.headers.host.replace(/:\d+/, ':' + securePort)
 | 
			
		||||
  );
 | 
			
		||||
  res.statusCode = 302;
 | 
			
		||||
  res.end();
 | 
			
		||||
}).listen(port, function(){
 | 
			
		||||
  console.log("Listening on http://localhost:" + server.address().port);
 | 
			
		||||
});
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user