Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Self signed SSL certificate on private IP is invalid in Chrome

I want to create a Self Signed certificate for a nodejs server. I run it from macOS. I want to be able to visit pages rendered by that server over https from another device (Android) on the same wifi network through "https://192.9.200.77:8005" on Chrome. 192.9.200.77 being the IP of the server.

I managed to create a key and a certificate with OpenSSL with SAN. I installed the certificate on the Android device and on macOS.

On MacOS, the certificate is working on Safari, but not in Chrome 71.

On Android the certificate is not working either.

app.js (node server) :

const fs = require('fs');
const https = require('https');

const credentials = {
  key: fs.readFileSync('keys/priv_and_pub.pem'),
  cert: fs.readFileSync('keys/CA.crt')
};
const express = require('express');
const app = express();
const port = 3000;

app.get('/', (req, res) => res.send('Hello World!'));

const httpsServer = https.createServer(credentials, app);

httpsServer.listen(8005, () => console.log(`Example app listening on port 8005 in https!`));

To create the certificate, I use a configuration file :

ssl.conf

[ req ]
x509_extensions     = x509_ext
distinguished_name  = subject


[ subject ]
countryName         = Country Name (2 letter code)
countryName_default     = US

stateOrProvinceName     = State or Province Name (full name)
stateOrProvinceName_default = California

localityName            = Locality Name (eg, city)
localityName_default    = SF

organizationName         = Organization Name (eg, company)
organizationName_default    = my company

commonName          = Common Name (e.g. server FQDN or YOUR name)
commonName_default      = 192.9.200.77

emailAddress            = Email Address
emailAddress_default        = [email protected]

[ x509_ext ]
basicConstraints        = CA:TRUE
subjectAltName          = @alternate_names

[ alternate_names ]

DNS.1       = 192.9.200.77

And Openssl with these commands:

openssl genrsa -out priv_and_pub.key 2048

openssl req -config ssl.conf -new -x509 -sha256 -key priv_and_pub.key -subj "/C=US/ST=California/L=BSF/O=myCompany/OU=Prod/CN=192.9.200.77"  -out CA.crt 

Then I convert the certificate to the DER format for the Android device as recommended here:

openssl x509 -inform PEM -outform DER -in CA.crt -out CA.der.crt

And converted the priv_and_pub.key to a .pem for the node server :

cp priv_and_pub.key priv_and_pub.pem

The app.js is working fine. I installed the .cert in macOS and everything's fine on Safari (green lock and all), but doesn't work on Chrome : (net::ERR_CERT_COMMON_NAME_INVALID). In the browser console, in the Security tab, I get green signs for Connection (Connection - secure (strong TLS 1.2)) and Resources (Resources - all served securely), but red flag for Certificate (Certificate - missing) and this error : 'Can not verify on the server that this is the domain 192.9.200.77, because its security certificate comes from the domain 192.9.200.77. This may be due to a misconfiguration or a connection by your hacker.' (Google Traduction from French)

Any help appreciated, spent the day on the problem ! Thks !

like image 224
Pauline Contact Avatar asked Jan 07 '19 20:01

Pauline Contact


2 Answers

To clean up and reduce this solution to its core elements, the following is required to create an IP certificate that will be trusted by Chrome.

The ssl.conf file...

[ req ]
default_bits       = 4096
distinguished_name = req_distinguished_name
req_extensions     = req_ext
prompt             = no

[ req_distinguished_name ]
commonName                  = 192.168.1.10

[ req_ext ]
subjectAltName = IP:192.168.1.10

Where, of course 192.168.1.10 is the local network IP we want Chrome to trust.

Thus, the CA:True basic constraint is not required.

Create the certificate:

 openssl genrsa -out key1.pem
 openssl req -new -key key1.pem -out csr1.pem -config ssl.conf
 openssl x509 -req -days 9999 -in csr1.pem -signkey key1.pem -out cert1.pem -extensions req_ext -extfile ssl.conf
 rm csr1.pem

On Windows import the certificate into the Trusted Root Certificate Store on all client machines. On Android Phone or Tablet download the certificate to install it. Now Chrome will trust the certificate on windows and Android.

On windows dev box the best place to get openssl.exe is from "c:\Program Files\Git\usr\bin\openssl.exe"

like image 173
AQuirky Avatar answered Oct 03 '22 17:10

AQuirky


I resolved my problem by changing the subjectAltName in the ssl.conf file, by adding IP: in front of the IP adress :

ssl.conf file :

[ x509_ext ]
basicConstraints        = CA:TRUE
subjectAltName          = IP:192.9.200.77

and I also removed the [ alternate_names ] section.

like image 39
Pauline Contact Avatar answered Oct 01 '22 17:10

Pauline Contact