16

I'm making HTTPS connections from a node app, using a client certificate:

var options = { 
    hostname: 'https://my-server.com', 
    port: 443, 
    path: '/', 
    method: 'GET', 
    key: fs.readFileSync('client1-key.pem'), 
    cert: fs.readFileSync('client1-crt.pem'), 
    ca: fs.readFileSync('ca-crt.pem') }; 

var req = https.request(options, res => { 
    [...]
}); 

Everything is working fine, however I want to add code to ensure only TLS 1.2 connections are allowed. I cannot find any way to configure this in the https.agent options, or elsewhere. Is it possible to configure this, or do I have to make a connection and then query the protocol version, with something like:

res.socket.getProtocol() === 'TLSv1.2'

and abort the connection if the protocol is not satisfactory?

JHH
  • 8,567
  • 8
  • 47
  • 91
  • alternatively you can use nginx as a reverse proxy to terminate your TLS traffic so shielding nodejs from having to deal with https yet communicate with outside world via https ... removing the complexity of asking nodejs to handle any TLS related matters entirely ... nginx is config driven, no need to code security logic ... nginx also handles WebSockets – Scott Stensland Jun 19 '17 at 16:25
  • Thus is for outgoing requests. – JHH Jun 19 '17 at 16:32

2 Answers2

32

First I found the docs on making HTTPS requests. It mentions that you can pass additional options to tls.connect() which includes something called secureProtocol. Digging into tls.connect(), I found the secureContext option which mentions tls.createSecureContext(). And there it finally mentions secureProtocol which can be specified with a string from an OpenSSL page. I picked a string that looked reasonable (TLSv1_2_method) and passed the secureProtocol option directly into https.request.

This prints SSL Version: TLS 1.2 with the given secureProtocol and SSL Version: TLS 1.1 with secureProtocol: "TLSv1_1_method". The error handler at the end will get called if a connection cannot be established with the given TLS version.

var https = require('https')

var options = {
    hostname: 'www.howsmyssl.com',
    port: 443,
    path: '/a/check',
    method: 'GET',
    secureProtocol: "TLSv1_2_method"
}

https.request(options, res => {
  let body = ''
  res.on('data', d => body += d)
  res.on('end', () => {
    data = JSON.parse(body)
    console.log('SSL Version: ' + data.tls_version)
  })
}).on('error', err => {
  // This gets called if a connection cannot be established.
  console.warn(err)
}).end()
supersam654
  • 3,126
  • 33
  • 34
9

Just an update about this solution, a couple of years have passed and some things have changed.

Node docs now recommends to use minVersion and maxVersion instead secureProtocol since this last option has become the legacy mechanism to select the TLS protocol version, so you can get the same result by using minVersion: "TLSv1.2":

var https = require('https')

var options = {
    hostname: 'www.howsmyssl.com',
    port: 443,
    path: '/a/check',
    method: 'GET',
    minVersion: "TLSv1.2",
    maxVersion: "TLSv1.2"
}
...

References: Node docs: tls_tls_createsecurecontext_options

vgharz
  • 101
  • 1
  • 2