Configure https agent to allow only TLS1.2 for outgoing requests
Asked Answered
W

3

17

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?

Worrell answered 19/6, 2017 at 11:22 Comment(3)
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 WebSocketsPin
Thus is for outgoing requests.Worrell
Does this answer your question? How do I use a specific TLS version with `node-fetch` like TLS v1.2?Legume
R
34

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()
Reachmedown answered 19/6, 2017 at 16:18 Comment(7)
Brilliant answer, this worked great. Really helpful, thanks!Worrell
adding the test for success: openssl s_client -connect example.com:443 -tls1 - should fail openssl s_client -connect example.com:443 -tls1_2 should notSaltation
@Reachmedown the link is openssl link is broken. Possibly, the new link is openssl.cs.utah.edu/docs/ssl/…Barefaced
@Barefaced thanks for letting me know. I did a bit of spelunking and found the correct link on openssl.org. stackoverflow.com/revisions/44635449/2Reachmedown
Did you figure out how to do this with a HTTPs agent?Outmaneuver
What's the default value node uses?Dewain
I still don't understand why axios and fetch does not support tlsv.12 out of box. :sadPlumper
M
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

Marduk answered 27/5, 2020 at 19:50 Comment(0)
L
0

You can use the tls library:

const tls = require('tls');

tls.DEFAULT_MIN_VERSION = 'TLSv1.2';
Legume answered 30/9, 2023 at 15:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.