Why HTTPS not working in AWS EC2 with nodejs? - node.js

I want to enable https in AWS EC2 windows instance.
I did the nodejs(my server side) config using the https://stackoverflow.com/questions/21397809/create-a-trusted-self-signed-ssl-cert-for-localhost-for-use-with-express-node.
My config file is as below,
[req]
distinguished_name = req_distinguished_name
x509_extensions = v3_req
prompt = no
[req_distinguished_name]
C = XX
ST = XX
L = XXXXXX
O = XXX
OU = XXXX
CN = XX.XX.XXX.XX:8080
[v3_req]
keyUsage = critical, digitalSignature, keyAgreement
extendedKeyUsage = serverAuth
subjectAltName = #alt_names
[alt_names]
DNS.1 = XX.XX.XXX.XX:8080
DNS.2 = XX.XX.XXX.XX:8080
DNS.3 = XX.XX.XXX.XX
Generated the certificate and key using the able config.
In AWS EC2 machine https//:localhost:8080 works as expected but https://XX.XX.XXX.XX:8080 not working. Also https://XX.XX.XXX.XX:8080 not able to access from outside internet. Early same IP with HTTP works fine in local and outside.
My AWS In bound rules as follows
Ports 8080 and 3306 already enabled in the EC2 instance.
Getting below error

Related

Unable to finish TLS handshake for my express webserver

Here's my webserver, most parts not included in favor of being concise.
server.js
const https = require('https');
const app = require('express')();
const port = 1000;
const options = {
key : getKey(),
cert: getCert(),
ciphers: getCiphers(),
passphrase: "abcd",
rejectUnauthorized: true,
requestCert: true
};
const server = https.createServer(options, app);
server.on('clientError', function (err) {
console.log('received client error');
console.log({err});
})
server.on('connection', function (err) {
console.log('client connected');
})
server.listen(port);
To test my server, I run a connection commands with openssl
openssl s_client -connect localhost:1000 \
-servername localhost \
-CAfile etc/root-cert/ca.cert.pem \
-cert etc/certs/client.cert.pem \
-key etc/private/client.key.pem
This returns the following output, which indicates that the TLS connection was successful (as far as I'm aware):
CONNECTED(00000005)
depth=2 C = US, ST = California, O = Hackysack, CN = Hackysack Root CA
verify return:1
depth=1 C = US, ST = California, O = Hackysack, CN = Hackysack Intermediate CA
verify return:1
depth=0 C = US, ST = California, O = Hackysack, CN = localhost
verify return:1
write W BLOCK
---
Certificate chain
0 s:/C=US/ST=California/O=Hackysack/CN=localhost
i:/C=US/ST=California/O=Hackysack/CN=Hackysack Intermediate CA
1 s:/C=US/ST=California/O=Hackysack/CN=Hackysack Intermediate CA
i:/C=US/ST=California/O=Hackysack/CN=Hackysack Root CA
---
Server certificate
-----BEGIN CERTIFICATE-----
[Long cert file here]
-----END CERTIFICATE-----
subject=/C=US/ST=California/O=Hackysack/CN=localhost
issuer=/C=US/ST=California/O=Hackysack/CN=Hackysack Intermediate CA
---
No client certificate CA names sent
Server Temp Key: ECDH, X25519, 253 bits
---
SSL handshake has read 3400 bytes and written 2061 bytes
---
New, TLSv1/SSLv3, Cipher is AEAD-AES128-GCM-SHA256
Server public key is 2048 bit
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
Protocol : TLSv1.3
Cipher : AEAD-AES128-GCM-SHA256
Session-ID:
Session-ID-ctx:
Master-Key:
Start Time: 1674855496
Timeout : 7200 (sec)
Verify return code: 0 (ok)
---
read:errno=0
However, in my server terminal logs I see that I receive a clientError when trying to make this call via HTTPS request.
{
err: Error: socket hang up
at connResetException (internal/errors.js:639:14)
at TLSSocket.onSocketClose (_tls_wrap.js:1063:23)
at TLSSocket.emit (events.js:412:35)
at net.js:686:12
at Socket.done (_tls_wrap.js:564:7)
at Object.onceWrapper (events.js:520:26)
at Socket.emit (events.js:400:28)
at TCP.<anonymous> (net.js:686:12) {
code: 'ECONNRESET'
}
}
Here's my client request:
const https = require('https');
const options = {
hostname: 'localhost',
port: 1000,
method: "POST",
path: "/test",
cert: getClientCert(),
key: getClientKey(),
passphrase: "abcd",
ciphers: getCiphers()
ca: getCA(),
}
const request = https.request(options);
I noticed this error only started happening when I included requestCert: true when I created the server. I think something must be going wrong with my client side for this to be the case. The main problem with debugging this is that I'm not receiving a good error when it fails the handshake.
How can I better debug this issue?

Yubico YubiHSM2 connector with HTTPS access

I use Win10 for my experiments.
I want to create HTTPS access between yubihsm-shell and yubihsm-connector.
Official guidelines are not very detailed but after a while I found some relevant information in https://github.com/Yubico/yubihsm-shell/issues/5
I used openssl and created private key (privkey.pem), certificate signing request (csr.csr) and certificate (hsm_cert.pem). The certificate is self signed.
I started yubihsm connector via:
yubihsm-connector.exe -d -l localhost:54321 --cert=hsm_cert.pem --key=privkey.pem
I open up my web browser and I type URL:
https://localhost:54321/connector/status
I get correct message:
status=OK
serial=*
version=3.0.1
pid=12920
address=localhost
port=54321
Next I tried yubishell via following:
yubihsm-shell.exe --connector=https://localhost:54321 --cacert=hsm_cert.pem
yubihsm> connect
Failed setting HTTPS CA
The certificate I gave to YubiHSM shell is the same self signed certificate I started connector with.
Certificate signing request was created with following configuration file:
[ req ]
default_bits = 2048
distinguished_name = req_distinguished_name
req_extensions = v3_req
[ req_distinguished_name ]
countryName = #deleted-due-to-privacy
countryName_default = #deleted-due-to-privacy
countryName_min = 2
countryName_max = 2
localityName = #deleted-due-to-privacy
organizationalUnitName = #deleted-due-to-privacy
commonName = localhost
commonName_max = 64
emailAddress = #deleted-due-to-privacy
emailAddress_max = 40
[ v3_req ]
basicConstraints = CA:TRUE
keyUsage = digitalSignature, keyCertSign
certificate extension file looks like:
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:TRUE
keyUsage = digitalSignature, nonRepudiation, keyCertSign, keyAgreement
My questions:
How shall I create the X509 certificate for YubiHSM connector?
How shall I give certificate to YubiHSM shell so that it can connect to connector via HTTPS?

Still receiving SSL error "CERT_HAS_EXPIRED" after setting NODE_EXTRA_CA_CERTS

Since I was getting SSL errors (CERT_HAS_EXPIRED) for domains like https://www.dampfer-board.de/ I was trying to add current CAs to my application with
NODE_EXTRA_CA_CERTS=/var/www/xxx/cacert.pem
cacert.pem is the following file: https://curl.haxx.se/ca/cacert.pem
The env variable seems to be set correctly (confirmed by console.log(process.env.NODE_EXTRA_CA_CERTS)), but I still receive the same ssl error.
The code snippet looks like this:
request.post({url: apiUrl, ecdhCurve: 'auto', headers: {
'User-Agent': config.userAgent
}});
Any idea whats wrong?
Running openssl s_client -connect dampfer-board.de:443 -showcerts | openssl pkcs8 in the terminal returns this output.
depth=1 C = SE, O = AddTrust AB, OU = AddTrust External TTP Network, CN = AddTrust External CA Root
verify error:num=10:certificate has expired
notAfter=May 30 10:48:38 2020 GMT
verify return:0
depth=1 C = SE, O = AddTrust AB, OU = AddTrust External TTP Network, CN = AddTrust External CA Root
verify error:num=10:certificate has expired
notAfter=May 30 10:48:38 2020 GMT
verify return:0
depth=3 C = SE, O = AddTrust AB, OU = AddTrust External TTP Network, CN = AddTrust External CA Root
verify error:num=10:certificate has expired
notAfter=May 30 10:48:38 2020 GMT
verify return:0
In the server certificate chain there is an expired certificate for AddTrust External CA Root.
I resolved this for openssl by removing the certificate from the list of certificates trusted by openssl.
I reckon that a similar fix can be applied for Node.
There is baked in the Node source this certificate as a trusted root. It's about time trust list got updated as the certificate expired since May 30, 2020.
NODE_EXTRA_CA_CERTS environment variable extends the trusted roots baked in the source whereas the ca option replaces it.
Modify your request to be
request.post({
url: apiUrl,
ecdhCurve: 'auto',
headers: {
'User-Agent': config.userAgent
},
agentOptions: {
ca: fs.readFileSync('./var/www/xxx/cacert.pem')
}
});

Self signed certificate only works with localhost, not 127.0.0.1

I'm trying to generate a self-signed certificate such that my local development environment uses HTTPS, but I'm having some trouble. The reason for this is that I want to test push notifications on my phone through my local network (through my local IP 192.168.1.155) and notifications only work via a secure context.
It only seems to work when I go to localhost:8080, and is still insecure when navigating to 127.0.0.1:8080. When I navigate to 127.0.0.1:8080 Chrome's Security Page says: This site is missing a valid, trusted certificate (net::ERR_CERT_COMMON_NAME_INVALID).
Here's my setup I use to generate the certificate:
req.cnf:
[req]
distinguished_name = req_distinguished_name
x509_extensions = v3_req
prompt = no
[req_distinguished_name]
C = US
ST = VA
L = SomeCity
O = MyCompany
OU = MyDivision
CN = 127.0.0.1
[v3_req]
keyUsage = critical, digitalSignature, keyAgreement
extendedKeyUsage = serverAuth
subjectAltName = #alt_names
[alt_names]
DNS.1 = localhost
DNS.2 = 127.0.0.1
DNS.3 = 192.168.1.155
openssl req -newkey rsa:2048 -x509 -nodes -keyout key.pem -new -out cert.pem -config req.cnf -sha256 -days 3650
I'd imagine perhaps my CN or alt_names is incorrect, but I'm not sure what to change them to such that the site will always work securely (either via localhost, 127.0.0.1, or 192.168.1.155)
In an unforseen case of rubber duck debugging, I seem to have finally solved this issue momentarily after posting it. Here's what I did:
req.cnf:
[req]
distinguished_name = req_distinguished_name
x509_extensions = v3_req
prompt = no
[req_distinguished_name]
C = US
ST = VA
L = SomeCity
O = MyCompany
OU = MyDivision
CN = localhost
[v3_req]
keyUsage = critical, digitalSignature, keyAgreement
extendedKeyUsage = serverAuth
subjectAltName = DNS:localhost,IP:192.168.1.155,IP:127.0.0.1
command prompt:
openssl req -newkey rsa:2048 -x509 -nodes -keyout key.pem -new -out cert.pem -config req.cnf -sha256 -days 3650
Then navigate to the page in Chrome, save the certificate (as it will still be invalid) as a DER file and then using mmc.exe, import it into the Trusted Root Certification Authorities on your machine (this is assuming you're using Windows)

Certificate SSL_ERROR_BAD_CERT_DOMAIN for localhost / 127.0.0.1

I am creating a local app that starts a webserver in the localhost:8080 address. I am trying to create a certificate for it so that I can access it using HTTPS, but I am having a hard time doing this.
First I created my own CA and then I created a certificate with the localhost:8080 common name. Then I added my CA to the trusted authorities on my computer (I am using Windows 10 by the way), however when I opened my site I got the BAD_CERT_DOMAIN error using Firefox and Chrome.
I also tried to created another certificate using 127.0.0.1:8080 as the common name, but it also didn't work.
What I am doing wrong? Do these browsers always reject certificates with localhost as the CN?
UPDATE
I created a configuration file like this:
[ req ]
default_bits = 2048
distinguished_name = req_distinguished_name
req_extensions = req_ext
[ req_distinguished_name ]
countryName = Country Name (2 letter code)
stateOrProvinceName = State or Province Name (full name)
localityName = Locality Name (eg, city)
organizationName = Organization Name (eg, company)
commonName = Common Name (e.g. server FQDN or YOUR name)
[ req_ext ]
subjectAltName = #alt_names
[ alt_names ]
DNS.1 = localhost
DNS.2 = localhost:8080
DNS.3 = localhost:12125
DNS.4 = localhost:12126
DNS.5 = 127.0.0.1:8080
DNS.6 = 127.0.0.1:12125
DNS.7 = 127.0.0.1:12126
DNS.8 = 127.0.0.1
IP.1 = 127.0.0.1
And these are the commands that I am using to generate my certificate:
Sign request: openssl req -out myrequest.csr -newkey rsa:2048 -nodes -keyout mykey.key -config myconfig.conf
When I ran this command, the CN = localhost 127.0.0.1
Signining with my CA: openssl x509 -req -in myrequest.csr -CA rootCA.pem -CAkey rootCA.key -CAcreateserial -out mycertificate.crt -days 36500 -sha256
However I am still getting the BAD_CERT_DOMAIN for both Firefox and Google Chrome, even after I tell them to trust my own CA.
I have followed #jww's advice and I re-wrote my config file as this:
[ req ]
default_bits = 2048
distinguished_name = req_distinguished_name
req_extensions = req_ext
[ req_distinguished_name ]
countryName = Country Name (2 letter code)
stateOrProvinceName = State or Province Name (full name)
localityName = Locality Name (eg, city)
organizationName = Organization Name (eg, company)
commonName = Common Name (e.g. server FQDN or YOUR name)
[ req_ext ]
subjectAltName = #alt_names
[ alt_names ]
DNS.1 = localhost
IP.1 = 127.0.0.1
Then I used this commands to generate my certificate.
Sign request: openssl req -out myrequest.csr -newkey rsa:2048 -nodes -keyout mykey.key -config myconfig.conf
Signining with my CA: openssl x509 -req -in myrequest.csr -CA rootCA.pem -CAkey rootCA.key -CAcreateserial -out mycertificate.crt -days 36500 -sha256
So the problem really was that I was adding the port numbers to the IP and DNS addresses of my certificate sign request.

Resources