Skip to content

Instantly share code, notes, and snippets.

@shigeki
Created November 14, 2014 06:04
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save shigeki/986c53242f5bd3d78609 to your computer and use it in GitHub Desktop.
Save shigeki/986c53242f5bd3d78609 to your computer and use it in GitHub Desktop.
HTTPS Server to get A+ from SSL Labs Server Test
require('tls').CLIENT_RENEG_LIMIT = 0; // disable renegatiation from client
var https = require('https');
var http = require('http');
var fs = require('fs');
var ip = 'XXX.XXX.XXX.XXX';
var port = 443;
var rfc2560 = require('asn1.js-rfc2560');
var OCSPResponse = rfc2560.OCSPResponse;
var BasicOCSPResponse = rfc2560.BasicOCSPResponse;
var ocsp_uri = 'http://ocsp2.globalsign.com/gsorganizationvalsha2g2';
var ocsp_dst = require('url').parse(ocsp_uri);
// ocsp_request.der can be generated beforehand by using openssl
// openssl ocsp -issuer /home/ohtsu/tmp/cert/ca.pem -cert /home/ohtsu/tmp/cert/server.pem -reqout req.der
var ocsp_request_der = fs.readFileSync('./ocsp_request.der');
var ocsp_req_timeout = 3 * 1000;
var ocsp_cache = {nextUpdate: 0, der: null, lock: false};
var opts = {
// See Cipher List in https://community.qualys.com/blogs/securitylabs/2013/08/05/configuring-apache-nginx-and-openssl-for-forward-secrecy
ciphers: 'EECDH+ECDSA+AESGCM:EECDH+aRSA+AESGCM:EECDH+ECDSA+SHA384:EECDH+ECDSA+SHA256:EECDH+aRSA+SHA384:EECDH+aRSA+SHA256:EECDH+aRSA+RC4:EECDH:EDH+aRSA:RC4:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS',
honorCipherOrder: true,
secureOptions: require('constants').SSL_OP_NO_SSLv3, // against POODLE attack
key: fs.readFileSync('/home/ohtsu/tmp/cert/server.key'),
cert: fs.readFileSync('/home/ohtsu/tmp/cert/server.cert'),
ca: fs.readFileSync('/home/ohtsu/tmp/cert/server.ca'),
dhparam: fs.readFileSync('./dhparam.pem') // generated by openssl dhparam 2048 -out dhparam.pem
};
var hello = '<html><head></head><body>Hello TLS</body></html>';
var session_cache = {};
var session_id_list = [];
var session_cache_max = 100;
var server = https.createServer(opts, function(req, res) {
res.writeHead(200, {'content-type': 'text/html',
'strict-transport-security': 'max-age=15552000; includeSubDomains',
'content-length': Buffer.byteLength(hello)});
res.end(hello);
});
server.on('newSession', function(sessionId, sessionData, cb) {
if (session_id_list.length > session_cache_max) {
delete session_cache[session_id_list.shift()];
}
session_id_list.push(sessionId);
session_cache[sessionId] = sessionData;
cb(null, sessionData);
});
server.on('resumeSession', function(sessionId, cb) {
cb(null, session_cache[sessionId]);
});
server.on('OCSPRequest', function(cert, issuer, cb) {
var now = Date.now();
if (now > ocsp_cache.nextUpdate && !ocsp_cache.lock) {
ocsp_cache.lock = true;
ocsp_cache.der = null;
HandleOCSPrequest(cb);
} else {
cb(null, ocsp_cache.der);
}
});
server.listen(port, ip, function() {
});
function HandleOCSPrequest(cb) {
var opts = {
host: ocsp_dst.host,
method: 'POST',
path: ocsp_dst.path,
headers: {'content-type': 'application/ocsp-request',
'content-length': ocsp_request_der.length}
};
var req = http.request(opts, function(res) {
var buflist = [];
res.on('data', function(chunk) {
buflist.push(chunk);
});
res.on('end', function() {
var der = Buffer.concat(buflist);
var ocsp_res = OCSPResponse.decode(der, 'der');
var b_res = BasicOCSPResponse.decode(ocsp_res.responseBytes.response, 'der');
var res = b_res.tbsResponseData.responses[0];
ocsp_cache = {nextUpdate: res.nextUpdate, der: der, lock: false};
cb(null, der);
});
});
// Error and Timeout to OCSP server terminate OCSP stapling
req.setTimeout(ocsp_req_timeout, function() {
req.abort();
req.emit('error', new Error('timeout'));
});
req.on('error', function(e) {
if (ocsp_cache.lock === null) {
ocsp_cache = {nextUpdate: Infinity, der: null, lock: null};
cb(null, null);
}
});
req.end(ocsp_request_der);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment