6

I was using iojs and koa in my application and recently I decided to update iojs to nodejs v4.4.4. The update was very smooth and my application was running in no time. The problem is that I am using a self signed SSL certificate on my development machine, and after I updated to nodejs I receive the following message when I try to access the website:

This site can’t provide a secure connection

localhost uses an unsupported protocol.

ERR_SSL_VERSION_OR_CIPHER_MISMATCH

The client and server don't support a common SSL protocol version or cipher suite. This is likely to be caused when the server needs RC4, which is no longer considered secure.

I am using nvm so I tried switching to iojs and the website was working again.

After some reading I found out that I have to update the openssl to version 1.0.2g instead of the 1.0.1g that I used to create the .key and .crt files. So I updated openssl and generated new key and certificate files like this:

sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/apache2/ssl/apache.key -out /etc/apache2/ssl/apache.crt

Sadly this did not resolve the issue.

This is the code that I use to setup the https on the server:

let sslOptions = {
            key: fs.readFileSync('/etc/apache2/ssl/apache.key'),
            cert: fs.readFileSync('/etc/apache2/ssl/apache.crt')
                 };

let server = require('https').createServer(sslOptions, app.callback())

Am I doing something wrong? Why does it work with iojs and does not work with nodejs?

Community
  • 1
  • 1
Ivan Stoyanov
  • 5,412
  • 12
  • 55
  • 71
  • the error message is showing up into the browser, right ? Which one ? –  May 10 '16 at 13:24
  • It is shown in Chrome, but I receive an error message in Firefox as well. In Firefox it is `Error code: SSL_ERROR_INAPPROPRIATE_FALLBACK_ALERT` – Ivan Stoyanov May 10 '16 at 13:25
  • IF it only for dev purpose, i d suggest to add an exception. See comments here http://gaboesquivel.com/blog/2014/nodejs-https-and-ssl-certificate-for-development/ for chrome. IF it s a no go, have you thought about let s encrypt ? Or even more brutal [this](https://github.com/coolaj86/node-ssl-root-cas/wiki/Painless-Self-Signed-Certificates-in-node.js) –  May 10 '16 at 13:29
  • I have tried the first link. It is almost identical to what I described above. – Ivan Stoyanov May 10 '16 at 13:40
  • why not try **nginx** can help SSL cheap and not need buy SSL. – KingRider Jun 21 '16 at 13:51

4 Answers4

3

There will be a truststore (keystore) file, where all trusted certificates need to be registered. You will have to register this newly created certificate there. Client uses that truststore file to check whether a certificate can be trusted or not.

For more details you can take reference from below link :-

Creating Self Signed Certificates (openssl & keytool)

I hope it helps.

Neha Vari
  • 492
  • 3
  • 14
  • This may work in Java, but I don't think that there is a way to use keystores in Node.js to create a HTTPS server. Also I wasn't able to find the `openssl.cfg` (as described in the blog post). I installed openssl as an apt-get package so maybe this is the problem. – Ivan Stoyanov Jun 20 '16 at 14:03
  • Checlout this link to add trusted CA's to node js.. http://stackoverflow.com/questions/21004645/where-is-nodes-certificate-store That post was to make concept clear. – Neha Vari Jun 20 '16 at 14:12
  • run following command in openssl home dir :- find . -name "openssl.cfg" – Neha Vari Jun 20 '16 at 14:14
3

Judging by the error message there is nothing wrong with the self signed certificate. But the 'server' offering the ssl connection doesn't support a suitable combination of protocol version an cipher suite.

openssl s_client -connect localhost:443

or more verbose

openssl s_client -connect localhost:443 -debug

might tell you what's going wrong during the ssl handshake.

You can also find out what combinations are provided with a tool called sslscan

apt-get install sslscan
sslscan localhost:443
sslscan localhost:443 | grep Accepted

In the end you'll want to configure the ciphersuites your https server offers by providing more ssloptions.

See here https://certsimple.com/blog/a-plus-node-js-ssl

unR
  • 1,298
  • 14
  • 21
  • 1
    I tried the `openssl s_client` and I get the following messages `CONNECTED(00000003)` `139962603136672:error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure:s23_clnt.c:769:` `no peer certificate available` `No client certificate CA names sent` `New, (NONE), Cipher is (NONE) Secure Renegotiation IS NOT supported Compression: NONE Expansion: NONE No ALPN negotiated SSL-Session: Protocol : TLSv1.2 Cipher : 0000 Key-Arg : None PSK identity: None PSK identity hint: None SRP username: None Verify return code: 0 (ok)` – Ivan Stoyanov Jun 21 '16 at 12:01
  • I am not very knowledgeable in SSL, do you have any insight on what the problem is? – Ivan Stoyanov Jun 21 '16 at 12:02
  • The `sslscan` tool returned no `Accepted` ciphers – Ivan Stoyanov Jun 21 '16 at 12:05
  • In the site I linked the author defines another key in what would be your sslOptions Object. Seeing that it says `Cipher is (NONE)` copy the last version of that `ciphers: [...].join(':')` in you code and try if it helps. – unR Jun 21 '16 at 12:05
  • I tried adding ciphers before and it did not work. When I add it now and try the openssl command it still says `Cipher is (NONE)`. I am using `nvm` for version management. Can it be that when I switch from iojs to node the `tls.js` file is still the same, and the old ciphers are there? – Ivan Stoyanov Jun 21 '16 at 12:42
  • Are you sure you're actually connecting to the correct port. The output you provided is the same one would get when using plain http without ssl. What port do you bind to? Could you try to explicitly use the `server.listen(10443)` method and try the `openssl s_client -connect localhost:10443` again? – unR Jun 21 '16 at 12:55
  • I am quite sure. I am using port 3100 for development. When I switch to iojs and execute the openssl command I get quite a lot of data about the ssl certificate and the website is working. – Ivan Stoyanov Jun 21 '16 at 13:01
  • I'm sorry I'm at my wits end here. I just set up a simple https server with node myself and couldn't reproduce the error. Hope you'll find the solution though. good luck. – unR Jun 21 '16 at 13:21
  • Thx for the rep. Have you thought about using Nginx as a reverse proxy (proxy_pass) in front of your nodejs application. This way you could offer only http (internally) with node and leave the ssl stuff to Nginx. – unR Jun 22 '16 at 15:18
  • I am using a load balancer for production and I haveset it up like that. I need the https for development. I am not sure of itis a good idea to use nginx like that – Ivan Stoyanov Jun 23 '16 at 03:54
1

Thank you for the answers!

As I suspected, the problem were with something unrelated to openssl.

In my application I have a config.js file with the app configuration. Inside of it I am reading the certificate files and adding them to a javascript object.

The problem was, that I am using the lodash module to merge 2 javascript objects (one of which contained the certificate files).

I was using an older version of the lodash module and it appears that it used a Buffer to merge the files. The Buffer implementation in that version did not match the Buffer implementation in the new Node.js version. This led to incorrect merge of the certificate files and resulted in the ERR_SSL_VERSION_OR_CIPHER_MISMATCH error message.

Long story short, after updating the lodash module to the latest version, the certificate began to work as intended.

Ivan Stoyanov
  • 5,412
  • 12
  • 55
  • 71
0

I'm not a NodeJS expert. But seems like you need to disable RC4 on your node server. I think that's the issue.

Ruchira Randana
  • 4,021
  • 1
  • 27
  • 24