MQTT authorization error self signed certificate in certificate chain - node.js

Good day, everyone. I have a problem with MQTT authorization. I've created the certificate and uploaded it to the MQTT broker (Yandex-cloud). The certificate was generated by OpenSSL. But when I try to connect with it, I get the problem "self signed certificate in certificate chain". I've already tried a lot of StackOverflow fixes but they didn't help me.
const options = {
ca: fs.readFileSync('***/yandex.pem'),
};
const client = mqtt.connect('mqtts://mqtt.cloud.yandex.net:8883', options);
Error: self signed certificate in certificate chain
at TLSSocket.onConnectSecure (_tls_wrap.js:1497:34)
at TLSSocket.emit (events.js:315:20)
at TLSSocket._finishInit (_tls_wrap.js:932:8)
at TLSWrap.ssl.onhandshakedone (_tls_wrap.js:706:12) {
code: 'SELF_SIGNED_CERT_IN_CHAIN'
}
UPD: Certificate generation
$ openssl req -x509 \
-newkey rsa:4096 \
-keyout key.pem \
-out cert.pem \
-nodes \
-days 365 \
-subj '/CN=localhost'

Related

mosquitto mqtt broker tls problem. IP doesn not match certificate's altnames

I have provided the broker and the client with certificates. The broker is avaible at 172.27.224.1.
When I try to connect with the client, I get following error message:
Error [ERR_TLS_CERT_ALTNAME_INVALID]: Hostname/IP does not match certificate's altnames: IP: 172.27.224.1 is not in the cert's list:
at new NodeError (node:internal/errors:371:5)
at Object.checkServerIdentity (node:tls:297:12)
at TLSSocket.onConnectSecure (node:_tls_wrap:1540:27)
at TLSSocket.emit (node:events:390:28)
at TLSSocket._finishInit (node:_tls_wrap:944:8)
at TLSWrap.ssl.onhandshakedone (node:_tls_wrap:725:12) {
reason: "IP: 172.27.224.1 is not in the cert's list: ",
host: '172.27.224.1',
cert: {
subject: [Object: null prototype] {
C: 'AU',
ST: 'Some-State',
O: '',
OU: '',
CN: '172.27.224.1'
},
issuer: [Object: null prototype] {
C: 'DE',
ST: 'Some-State',
O: '',
OU: '',
CN: '172.27.224.1'
},
[...]
What's the error here? The ca.crt is a self signed cert with issued for 172.27.224.1 and issued from 172.27.224.1. The client.crt is issed from 172.27.224.1 and issued for "username".
should't this work?
Steps I used to generate the certificate:
openssl genrsa -des3 -out ca.key 2048
openssl req -new -x509 -days 1826 -key ca.key -out ca.crt
openssl genrsa -out client.key 2048
openssl req -new -out client.csr -key client.key
openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out client.crt -days 360
I use for the client node.js v16.13 and the mqtt library.
Assuming you are using OpenSSL to create the CA cert then you can do it as follows:
openssl req -x509 -nodes -newkey rsa:2048 -days 3650 -sha256 \
-keyout ca.key -out ca.crt -reqexts SAN -extensions SAN \
-subj '/CN=Broker Cert' \
-config <(cat /etc/pki/tls/openssl.cnf; printf "[SAN]\nsubjectAltName=IP:172.27.224.1")
This makes an assumption that you are using a openss.cnf file stored at /etc/pki/tls/openssl.cnf
But as a rule it's better to create a CA cert and then sign server certs with that as it makes changing things easier and you don't need to update all the clients when you want to change something. It also makes issuing client certificates a lot easier.
Please do still update the question with details of the programming language and client library you are using that is now enforcing the SAN rules.

So i have made a ssl certificate for my localhost, but the connection is refused,what should be done?

THIS PART OF THE CODE IS HOW I MADE AN SSL CERTIFICATE ===================
C:\Users\avivo\Documents\https_app\server\ssl>openssl genpkey -algorithm RS -pkeyopt rsa_keygen_bits:2048 -out ca.key
Algorithm RS not found
C:\Users\avivo\Documents\https_app\server\ssl>openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out ca.key
................................................+++
.....+++
C:\Users\avivo\Documents\https_app\server\ssl>openssl req -new -x509 -days 360 -key ca.key -subj "/CN=Test CA/O=AAAA Teat Organization" -out ca.crt
C:\Users\avivo\Documents\https_app\server\ssl>openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out server.key
......................................................................................................................................................+++
................................................+++
C:\Users\avivo\Documents\https_app\server\ssl>openssl req -new -key server.key -subj "/CN=localhost/O=AAAA Test Organization" -out server.csr
C:\Users\avivo\Documents\https_app\server\ssl>openssl x509 -days 360 -req -in server.csr -CAcreateserial -CA ca.crt -CAkey cs.key -out server.crt
Signature ok
subject=/CN=localhost/O=AAAA Test Organization
Getting CA Private Key
Error opening CA Private Key cs.key
14360:error:02001002:system library:fopen:No such file or directory:bss_file.c:406:fopen('cs.key','rb')
14360:error:20074002:BIO routines:FILE_CTRL:system lib:bss_file.c:408:
unable to load CA Private Key
unable to write 'random state'
//this the part of ssl ca and server certificate
erial -CA ca.crt -CAkey ca.key -out server.crt
Signature ok
subject=/CN=localhost/O=AAAA Test Organization
Getting CA Private Key
unable to write 'random state'
C:\Users\avivo\Documents\https_app\server\ssl>openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out client.key
.......+++
...................................+++
C:\Users\avivo\Documents\https_app\server\ssl>openssl req -new -key client.key -subj "/CN=Test User/O=AAAA Test Organization/UID=testuser1" -out client.csr
C:\Users\avivo\Documents\https_app\server\ssl>openssl x509 -days 360 -req -in client.csr -CAcreateserial -CA ca.crt -CAkey ca.key -out client.crt
Signature ok
subject=/CN=Test User/O=AAAA Test Organization/UID=testuser1
Getting CA Private Key
unable to write 'random state'
//this is the client side
MAIN CODE IN INDEX.JS====================================================
var express=require('express'),
fs=require('fs'),
https=require('https'),
path =require('path');
var app=express();
var directoryToServe='client';
var port=3443;
app.use('/',express.static(path.join(__dirname,"..",directoryToServe)))
var httpsOptions={
cert:fs.readFileSync(path.join(__dirname,'ssl','server.crt')),
key:fs.readFileSync(path.join(__dirname,'ssl','server.key'))
}
https.createServer(httpsOptions,app)
.listen(port,function(){
console.log('serving the'+directoryToServe+'/directory at https://localhost:3443')
})
ERROR=======================
C:\Users\avivo\Documents\https_app\server>node index .js
serving theclient/directory at https://localhost:3443
^C
C:\Users\avivo\Documents\https_app\server>node index .js
serving theclient/directory at https://localhost:3443
^C
C:\Users\avivo\Documents\https_app\server>curl -k https://localhost:3443
curl: (7) Failed to connect to localhost port 3443: Connection refused
C:\Users\avivo\Documents\https_app\server>node index .js
serving theclient/directory at https://localhost:3443
^C
//i have no idea as to why my isn't the server running,can anyone please help??
Your Node application quits as soon as you hit ctrl-c to run the curl command.
You either have to open a second terminal instance for curl or run the Node application as a process, by using something like PM2.

OpenSSL error - unable to get local issuer certificate

I have a simple chain setup and can successfully verify in this case:
$ openssl version
OpenSSL 1.0.2m 2 Nov 2017
$ openssl verify -CAfile chain.pem cert.pem
cert.pem: OK
However I get errors in these cases:
$ openssl verify -CAfile ca-cert.pem cert.pem
cert.pem: C = US...
error 2 at 1 depth lookup:unable to get issuer certificate
Specifically the unable to get issuer certificate.
Also get it here:
$ openssl verify chain.pem
chain.pem: C = US...
error 20 at 0 depth lookup:unable to get local issuer certificate
$ openssl verify cert.pem
cert.pem: C...
error 20 at 0 depth lookup:unable to get local issuer certificate
Finally, I get it in Node.js when I pass the keys to an HTTPS server:
events.js:193
throw er; // Unhandled 'error' event
^
Error: unable to get local issuer certificate
at TLSSocket.onConnectSecure (_tls_wrap.js:1036:34)
at emitNone (events.js:115:13)
at TLSSocket.emit (events.js:218:7)
at TLSSocket._finishInit (_tls_wrap.js:637:8)
I tried passing it with { key, cert, ca }, but still same error.
Wondering how to go about debugging this or what the fix is to get an HTTPS server running.
If I use a pfx file I get the following:
events.js:193
throw er; // Unhandled 'error' event
^
Error: self signed certificate in certificate chain
at TLSSocket.onConnectSecure (_tls_wrap.js:1036:34)
at emitNone (events.js:115:13)
at TLSSocket.emit (events.js:218:7)
at TLSSocket._finishInit (_tls_wrap.js:637:8)
If I leave only the cert.pem in the cert file, and make the ca attribute be the ca-cert.pem, it gives:
Error: unable to verify the first certificate
at TLSSocket.<anonymous> (_tls_wrap.js:1108:38)
at emitNone (events.js:105:13)
at TLSSocket.emit (events.js:207:7)
at TLSSocket._finishInit (_tls_wrap.js:638:8)
at TLSWrap.ssl.onhandshakedone (_tls_wrap.js:468:38)
Not sure what to do.
Here they say:
OpenSSL is unable to find a local certificate for the issuer (or the issuer of the first certificate in the chain received from the web server during the TLS handshake) with which to verify the signature(s).
Not sure what that means.
This error means the certificate path or chain is broken and you are missing certificate files.
-
https://wiki.zimbra.com/wiki/Fix_depth_lookup:unable_to_get_issuer_certificate
Update
Slightly more help:
This problem is usually indicated by log messages saying something like "unable to get local issuer certificate" or "self signed certificate". When a certificate is verified its root CA must be "trusted" by OpenSSL this typically means that the CA certificate must be placed in a directory or file and the relevant program configured to read it. The OpenSSL program 'verify' behaves in a similar way and issues similar error messages: check the verify(1) program manual page for more information.
https://www.openssl.org/docs/faq.html#USER6
But still doesn't help very much.
Looks like Node.js is using a 1.0.2l instead of 1.0.2m but doesn't seem like a big deal.
$ node -pe process.versions | grep openssl
openssl: '1.0.2l'
Update 2
Weird, I get this when I make a request from Node.js:
Uncaught Error: unable to verify the first certificate
at TLSSocket.onConnectSecure (_tls_wrap.js:1036:34)
at TLSSocket._finishInit (_tls_wrap.js:637:8)
But when I go to the browser, I don't see the "Proceed with caution" page, and can successfully log a request in Node.js. Maybe that helps somewhat. Please help :D
(This answer extracted from X509_verify_cert at crypto/x509/x509_vfy.c:204, in openssl-1.0.2m)
The OpenSSL verify application verifies a certificate in the following way: It builds the certificate chain starting with the target certificate, and tracing the issuer chain, searching any untrusted certificates supplied along with the target cert first. Upon failing to find an untrusted issuer cert, OpenSSL switches to the trusted certificate store and continues building the chain. This process stops when
an issuer is not found in the trusted store.
a self-signed certificate is encountered.
the max-verify depth is encountered.
At this point we have a chain that may end prematurely (if we failed to find an issuer, or if we exceeded the verify depth).
OpenSSL then scans over each trusted certificate on the chain looking for SSLv3 extensions that specify the purpose of the trusted certificate. If the trusted certificate has the right "trust" attributes for the "purpose" of the verification operation (or has the anyExtendedKeyUsage attribute) the chain is trusted. (Forgive the hand-wave on trust attributes, that part of the code was difficult to read.)
So lets test it out. First, let's repro the OP's error cases:
#
echo "Making Root CA..."
openssl req -newkey rsa:4096 -nodes -keyout ca-key.pem -sha384 -x509 -days 365 -out ca-crt.pem -subj /C=XX/ST=YY/O=RootCA
echo "Making Intermediate CA..."
openssl req -newkey rsa:3072 -nodes -keyout int-key.pem -new -sha384 -out int-csr.pem -subj /C=XX/ST=YY/O=IntermediateCA
openssl x509 -req -days 360 -in int-csr.pem -CA ca-crt.pem -CAkey ca-key.pem -CAcreateserial -out int-crt.pem
echo "Making User Cert..."
openssl req -newkey rsa:2048 -nodes -keyout usr-key.pem -new -sha256 -out usr-csr.pem -subj /C=XX/ST=YY/O=LockCmpXchg8b
openssl x509 -req -days 360 -in usr-csr.pem -CA int-crt.pem -CAkey int-key.pem -CAcreateserial -out usr-crt.pem
echo ""
echo "Making Chain..."
cat ca-crt.pem int-crt.pem > chain.pem
echo ""
echo "Verfying UserCert via RootCA..."
openssl verify -CAfile ca-crt.pem usr-crt.pem
echo ""
echo "Verfying UserCert via IntermediateCA..."
openssl verify -CAfile int-crt.pem usr-crt.pem
echo ""
echo "Verfying UserCert via chain..."
openssl verify -CAfile chain.pem usr-crt.pem
yields
[... Skipping OpenSSL KeyGen / CertGen verbosity ...]
Making Chain...
Verfying UserCert via RootCA...
usr-crt.pem: C = XX, ST = YY, O = LockCmpXchg8b
error 20 at 0 depth lookup:unable to get local issuer certificate
Verfying UserCert via IntermediateCA...
usr-crt.pem: C = XX, ST = YY, O = IntermediateCA
error 2 at 1 depth lookup:unable to get issuer certificate
Verfying UserCert via chain...
usr-crt.pem: OK
Now, lets use the -addtrust option of openssl x509 to make sure we have one of the acceptable trust attributes on the intermediate CA (call this one IntermediateCAWithTrust; we'll use it to sign AnotherUserCert.):
echo ""
echo "Alternate Intermedate CA (using -addtrust anyExtendedKeyUsage)"
echo ""
echo "Making IntermediateCAWithTrust..."
openssl req -newkey rsa:3072 -nodes -keyout int-key2.pem -new -sha384 -out int-csr2.pem -subj /C=XX/ST=YY/O=IntermediateCAWithTrust
openssl x509 -req -days 360 -in int-csr2.pem -CA ca-crt.pem -CAkey ca-key.pem -CAcreateserial -out int-crt2.pem -addtrust anyExtendedKeyUsage
echo "Making AnotherUser Cert..."
openssl req -newkey rsa:2048 -nodes -keyout usr-key2.pem -new -sha256 -out usr-csr2.pem -subj /C=XX/ST=YY/O=LockCmpXchg8b_2
openssl x509 -req -days 360 -in usr-csr2.pem -CA int-crt2.pem -CAkey int-key2.pem -CAcreateserial -out usr-crt2.pem
echo ""
echo "Verfying AnotherUserCert via IntermediateCAWithTrust..."
openssl verify -CAfile int-crt2.pem usr-crt2.pem
This yields
Alternate Intermedate CA (using -addtrust anyExtendedKeyUsage)
Making IntermediateCAWithTrust...
[... Snip more OpenSSL generation output ...]
Making AnotherUser Cert...
[... Snip more OpenSSL generation output ...]
Verfying AnotherUserCert via IntermediateCAWithTrust...
usr-crt2.pem: OK
Hey look! we just successfully verified AnotherUserCert via the IntermediateCAWithTrust, even though we didn't supply the whole chain. The key to this difference is that any one of the trusted certificates in the chain had an appropriate trust attribute for the verify operation.
Looking a little closer (via openssl x509 -in ca-crt.pem -noout -text), our CA certificate has
X509v3 Basic Constraints:
CA:TRUE
which I would imagine OpenSSL treats as a general "may verify for any purpose" extension. The new IntermediateCAWithTrust does not have X509v3 Basic Constraints, but instead has
Trusted Uses:
Any Extended Key Usage
No Rejected Uses.
For more info in the -addtrust option, and the types of trust attributes that can be added, see https://www.openssl.org/docs/manmaster/man1/x509.html#TRUST_SETTINGS
Near the bottom of that page is a concise summary of the preceding discussion:
The basicConstraints extension CA flag is used to determine whether
the certificate can be used as a CA. If the CA flag is true then it is
a CA, if the CA flag is false then it is not a CA. All CAs should have
the CA flag set to true.
If the basicConstraints extension is absent then the certificate is
considered to be a "possible CA" other extensions are checked
according to the intended use of the certificate. A warning is given
in this case because the certificate should really not be regarded as
a CA: however it is allowed to be a CA to work around some broken
software.
So, in short, make sure your intermediate CAs are properly CAs (in their X509v3 Basic Constraints). This seems an excellent tutorial (and it explicitly generates the intermediate CA as a CA): https://jamielinux.com/docs/openssl-certificate-authority/create-the-root-pair.html
As a backup plan, you can always supply the whole chain, or you can make your intermediate CAs with the -addtrust hack.
https://letsencrypt.org/ is really easy to use and free. Also, run node without SSL on a local HTTP port and use NGINX as a HTTPS proxy.
sudo apt-get install certbot nginx
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl default_server;
listen [::]:443 ssl default_server;
ssl on;
ssl_certificate /etc/letsencrypt/live/host.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/host.com/privkey.pem;
access_log /var/log/nginx/host.access.log;
error_log /var/log/nginx/host.error.log;
server_name _;
gzip on;
gzip_proxied any;
gzip_types text/css text/javascript text/xml text/plain application/javascript application/x-javascript application/json;
location / {
include /etc/nginx/proxy_params;
proxy_pass http://localhost:8080;
proxy_read_timeout 90s;
proxy_redirect http://localhost:8080 https://www.host.com;
}
}

x509: cannot validate certificate because it doesn't contain any IP SANs

I'm trying to implement an ELK stack while gathering information with Filebeat and MetricBeat on clients.
Installation went well, filebeat is runing OK on the client and sending information to logstash (thanks to 'insecure: true).
Metricbeats don't want to connect at all and show:
2017-02-08T15:57:36+01:00 ERR Connecting error publishing events (retrying): x509: cannot validate certificate for xxx.xxx.xxx.xxx because it doesn't contain any IP SANs
2017-02-08T15:57:37+01:00 ERR Connecting error publishing events (retrying): x509: cannot validate certificate for xxx.xxx.xxx.xxx because it doesn't contain any IP SANs
I looked around and tried:
1.using FQDN for creating the ssl certs:
sudo openssl req -subj '/CN=ec2xxxxeu-west-1.compute.amazonaws.com/' -x509 -days 3650 -batch -nodes -newkey rsa:2048 -keyout private/logstash-forwarder.key -out certs/logstash-forwarder.crt
This shows :
2017-02-08T15:47:22+01:00 ERR Connecting error publishing events (retrying): x509: certificate is valid for , not ec2-34-249-172-152.eu-west-1.compute.amazonaws.com
2.using ip certs by putting 'subjectAltName = IP: ELK_server_private_IP' in openssl configuration then using:
sudo openssl req -config /etc/ssl/openssl.cnf -x509 -days 3650 -batch -nodes -newkey rsa:2048 -keyout private/logstash-forwarder.key -out certs/logstash-forwarder.crt
I followed this tutorial for ELK / filebeat installation
https://www.digitalocean.com/community/tutorials/how-to-install-elasticsearch-logstash-and-kibana-elk-stack-on-ubuntu-16-04
That show the error msg in the title about SAN ips.
Do someone have an explanation of what's going on, do metrisbeats have a insecure:true to make it work?

NodeJS & SSL - "bad password read"

Node is failing to create a secure context for SSL communications.
Specifically, I'm trying to get remote notifications to work on iOS. I use a module, called node-apn which throws this error:
Error: error:0906A068:PEM routines:PEM_do_header:bad password read
at Error (native)
at Object.createSecureContext (_tls_common.js:108:19)
at Object.exports.connect (_tls_wrap.js:852:21)
at apnSocket (/home/Slurp/node_modules/apn/lib/socket.js:56:19)
at Connection.<anonymous> (/home/Slurp/node_modules/apn/lib/connection.js:188:17)
at _fulfilled (/home/Slurp/node_modules/apn/node_modules/q/q.js:834:54)
at self.promiseDispatch.done (/home/Slurp/node_modules/apn/node_modules/q/q.js:863:30)
at Promise.promise.promiseDispatch (/home/Slurp/node_modules/apn/node_modules/q/q.js:796:13)
This seems to be a generic error though, and isn't really related to APN specifically.
This is because you've specified a passphrase when generating the cert. This is a password that must be supplied by anyone wanting to use it.
Adding a passphrase field to the credentials solves the problem.
var credentials = {
key: fs.readFileSync('XXX.key', 'utf8'),
cert: fs.readFileSync('XXX.crt', 'utf8'),
passphrase: 'XXXX'
}
var httpsServer = https.createServer(credentials, app);
The following command will generate an unencrypted key, so you won't need to provide a passphrase:
openssl rsa -in yourKey.key -out newKey.key
This command will prompt you for the passphrase.
Use these to generate pem.
openssl genrsa -out server-key.pem 1024
openssl req -new -key server-key.pem -out server-csr.pem
openssl x509 -req -in server-csr.pem -signkey server-key.pem -out server-cert.pem

Resources