Mosquitto with SSL and wildcard certificate does not work without --capath option - ssl

I have a MQTT server and wanted to start using SSL instead of plain MQTT. I configured the server correctly to use my wildcard certificate but it won't work without the --capath /etc/ssl/certs option. Additionally, my ZwaveJS2MQTT instance will not work over SSL (probably because of the missing certification path). I am using the wildcard certificate on multiple servers (Debian, OpenVPN...) and have never encountered such issue.
On the subscriber side:
pi#raspi1:~ $ mosquitto_sub -d -h apollo.hostname.com -u "ha" -p 8883 -P "password" -t "zwave"
Client mosqsub|29009-raspi1.sm sending CONNECT
Client mosqsub|29009-raspi1.sm sending CONNECT
Client mosqsub|29009-raspi1.sm sending CONNECT
Client mosqsub|29009-raspi1.sm sending CONNECT
Client mosqsub|29009-raspi1.sm sending CONNECT
^C
pi#raspi1:~ $ mosquitto_sub -d -h apollo.hostname.com -u "ha" -p 8883 -P "password" -t "zwave" --capath /etc/ssl/certs
Client mosqsub|29078-raspi1.sm sending CONNECT
Client mosqsub|29078-raspi1.sm received CONNACK (0)
Client mosqsub|29078-raspi1.sm sending SUBSCRIBE (Mid: 1, Topic: zwave, QoS: 0)
Client mosqsub|29078-raspi1.sm received SUBACK
Subscribed (mid: 1): 0
Client mosqsub|29078-raspi1.sm received PUBLISH (d0, q0, r0, m0, 'zwave', ... (4 bytes))
test
^C
On the publisher side:
pi#raspi1:~ $ mosquitto_pub -d -h apollo.hostname.com -u "ha" -p 8883 -P "password" -t "zwave" -m "test"
Client mosqpub|29067-raspi1.sm sending CONNECT
Error: The connection was lost.
pi#raspi1:~ $ mosquitto_pub -d -h apollo.hostname.com -u "ha" -p 8883 -P "password" -t "zwave" -m "test" --capath /etc/ssl/certs
Client mosqpub|29069-raspi1.sm sending CONNECT
Client mosqpub|29069-raspi1.sm received CONNACK (0)
Client mosqpub|29069-raspi1.sm sending PUBLISH (d0, q0, r0, m1, 'zwave', ... (4 bytes))
Client mosqpub|29069-raspi1.sm sending DISCONNECT
When running a test on my wildcare certificate, I see the following errors:
Certificates provided 3 (3600 bytes)
Chain issues Incorrect order, Contains anchor
#2
Subject GlobalSign Root CA In trust store
...
Valid until Fri, 28 Jan 2028 12:00:00 UTC (expires in 6 years and 5 months)
Key RSA 2048 bits (e 65537)
Issuer GlobalSign Root CA Self-signed
Signature algorithm SHA1withRSA Weak, but no impact on root certificate
#3
Subject AlphaSSL CA - SHA256 - G2
...
Valid until Tue, 20 Feb 2024 10:00:00 UTC (expires in 2 years and 6 months)
Key RSA 2048 bits (e 65537)
Issuer GlobalSign Root CA
Signature algorithm SHA256withRSA
The certification path shows this:
Path #1: Trusted
1 Sent by server *.hostname.com
...
RSA 2048 bits (e 65537) / SHA256withRSA
2 Sent by server AlphaSSL CA - SHA256 - G2
...
RSA 2048 bits (e 65537) / SHA256withRSA
3 Sent by server
In trust store GlobalSign Root CA Self-signed
...
RSA 2048 bits (e 65537) / SHA1withRSA
Weak or insecure signature, but no impact on root certificate

From the moquitto_pub/mosquitto_sub man page:
To enable TLS connections when using x509 certificates, one of either
--cafile or --capath must be provided as an option.
The mosquitto command line tools do not have a default CA certificate source, so to enable TLS based connections you MUST provide a path to either a CA cert file or a directory of CA cert files.
And if providing a path to a directory of CA certs it must be prepared with the following:
For --capath to work correctly, the certificate files must have ".crt"
as the file ending and you must run "openssl rehash "
each time you add/remove a certificate.

Related

MQTT MTLS connection with different CA

I am trying mtls authentication in MQTT. I am using mosquitto to achieve this. When I created a server and client certificate from the same CA then the connection was successful. But if I use a different CA for creating a client certificate then it's failing with the below message
Client null sending CONNECT
OpenSSL Error[0]: error:14094418:SSL routines:ssl3_read_bytes:tlsv1 alert unknown ca
Error: The connection was lost.
Is it mandatory to use the same CA for both client and server certificates in mtls?
Mosquitto.conf
listener 8883
certfile C:\\server.crt
keyfile C:\\server.key
require_certificate true
cafile C:\mqtt-ssl-demo\ca.crt
allow_anonymous true
Running broker using
mosquitto -c "C:\Program Files\mosquitto\mosquitto.conf"
Subscribe with a client with a certificate signed by server cert ca [SUCCESS]
mosquitto_sub --cafile C:\mqtt-ssl-demo\ca.crt -t test -d -h Computername -p 8883 --cert C:\mqtt-ssl-demo\client.crt --key C:\mqtt-ssl-demo\client.key
Subscribe with a client with a certificate signed by other ca [FAILURE]
mosquitto_sub --cafile C:\mqtt-ssl-demo\ca.crt -t test -d -h Computername -p 8883 --cert C:\mqtt-ssl-demo\otherclient.crt --key C:\mqtt-ssl-demo\otherclient.key
Created certificate using Mosquitto SSL Configuration -MQTT TLS Security
The important thing to realise here is that the CA file passed to the broker as part of it's config is used to verify the certificate of any connecting clients.
Where as the CA file passed to the client (mosquitto_sub) is used to verify the certificate the broker presents.
So if you are using different CAs then these files need to be different, it's not clear from what you've posted which CA certs you are using where.

CA certificate for TLS connection node02.myqtthub.com/8883

I'm playing with mqtthub and ESP32 CHIP. I would like to connect in most secure way so i thought maybe try with TLS connection at the beginning and later i could also encrypt data which is sent to broker(mqtthub).
I successfully managed to connect with mosquitto on linux using /etc/ssl/certs path to CA certificates.
I would like now to copy the certificate I need into flash memory that my app written in C can use it while it connects to broker on port 8883. How can i guess which one public CA certificate is the right one i need to copy from /etc/ssl/certs ?
PS: i found this on mqtthub forum:
https://decoder.link/sslchecker/node02.myqtthub.com/8883
might it be helpful?
Looking at the certificate chain returned from your server I see the root certificate has a common name DST Root CA X3:
$ openssl s_client -showcerts -connect node02.myqtthub.com:8883
depth=2 O = Digital Signature Trust Co., CN = DST Root CA X3
verify return:1
depth=1 C = US, O = Let's Encrypt, CN = Let's Encrypt Authority X3
verify return:1
depth=0 CN = node02.myqtthub.com
verify return:1
The directory /etc/ssl/certs in my host happens to contain a cert named DST_Root_CA_X3.pem. This would be a good candidate to try.
ok, i found the solution. Instead of pointing to entire directiory
mosquitto_sub -h node02.myqtthub.com -p 8883 --capath /etc/mosquitto/certs -i linux_machine -u nariox -P myPassword -t test/connection -q 2
i run the command with cafile instead of capath
mosquitto_sub -h node02.myqtthub.com -p 8883 --cafile /etc/mosquitto/certs/DST_Root_CA_X3.crt -i linux_machine -u nariox -P myPassword -t test/connection -q 2
what solved my problem. If anyone could explain it to my why i will be grateful

Kafka, why do I need to pass the certificate chain and not only the root ca when testing with kafka-console-producer (or Kafkcat)

I have a Kafka cluster which is configured to be used over ssl on port 9093.
In order for me successfully send data on port 9093 I need to pass the certificate chain (intermediate + root CA) (all these are self signed stuff)
echo "Hello" | kafkacat -P -b localhost:9095 -t my-topic \
-X security.protocol=ssl \
-X ssl.key.location=cert-key.pem \
-X ssl.ca.location=chain.crt
(chain.crt is a file with the rootCA and intermediate cert)
My question is why do I need to issue the full chain and not just the root CA in the ssl.ca.location param ?
ssl.key.location is the client's certificate for authenticating to the broker.
ssl.ca.location is used by the client to verify the broker's certificate.

Mosquitto TLS, works with MQTTfx but not mosquitto_pub (tlsv1 alert unknown ca)

Quite strange issue
I have mosquitto broker working with TLS
It is correctly accessible by an MQTTfx client set up for 'Enable SSL/TLS, TLSv1.2, CA certificate file'
The same ca.crt file is used by a openwrt mosquitto client issuing
# mosquitto_pub -h x.x.x.x -p 8883 --cafile /etc/mosquitto/certs/ca.crt -i 1.1.1.1 -t test -m 123 -d
it returns
Client 1.1.1.1 sending CONNECT
Error: A TLS error occurred.
At the orher end, the broker, shows
OpenSSL Error: error:14094418:SSL routines:SSL3_READ_BYTES:tlsv1 alert unknown ca
OpenSSL Error: error:140940E5:SSL routines:SSL3_READ_BYTES:ssl handshake failure
Socket error on client (null), disconnecting.
What is messing me up is the fact that the MQTTfx client instead is accepted, and it's using the same certificate..!
New connection from y.y.y.y on port 8883.
New client connected from y.y.y.y as 180ce1c04c1944e1964608221efbcf0a (c1, k60).
Sending CONNACK to 180ce1c04c1944e1964608221efbcf0a (0)
Should mean that the certificate is valid and trusted... isn't it?
What's wrong then with the other client using the exact same certificate file ?!?!
...at the end using --insecure option did the job.
Means verification of the server hostname in the server certificate.
Well it works, although using this option in a production environment potentially invalidates the use of encryption.

client certificate not found

What can I do to troubleshoot/fix why my curl command cannot find my certificate when referencing to it by its nickname
I am trying to get a secure connection to a bank server, that is handling our online payments, using curl. The server is using NSS protocol. I installed the certificate from the bank into the nssdb with a nickname "foo" using:
certutil -A -d sql:/etc/pki/nssdb -i ccapi.pem -n "foo" -t "P,P,P"
Listing the cert to check that it has been created, I use
certutil -L -d sql:/etc/pki/nssdb/
with the output confirming a nickname "foo" for the cert.:
Certificate Nickname Trust Attributes
SSL,S/MIME,JAR/XPI
foo P,P,P
When I am trying to connect using curl referencing to the nickname foo for the certificate like this:
curl -k -v --cert "foo" https://ccapi.client.qvalent.com/payway/ccapi
This is PART of the output:
Connected to proxy.ourdomain.com.au (172.21.0.58) port 3128 (#0)
Establish HTTP proxy tunnel to ccapi.client.qvalent.com:443
CONNECT ccapi.client.qvalent.com:443 HTTP/1.1
Host: ccapi.client.qvalent.com:443
User-Agent: curl/7.37.0
Proxy-Connection: Keep-Alive
HTTP/1.1 200 Connection established
Proxy replied OK to CONNECT request
Initializing NSS with certpath: sql:/etc/pki/nssdb
skipping SSL peer certificate verification
NSS: client certificate not found: foo
The last line: certificate not found: foo, is my problem. I seem to be doing everything right when creating the cert in the nssdb with a nickname but when using a curl command to connect it cannot find the certificate. If I link to the actual cert like this and not the nickname:
curl -k -v --cert "./ccapi.pem" https://ccapi.client.qvalent.com/payway/ccapi
Then the certificate is recognized but I cannot connect to bank server. This could be because I need to use NSS but this is irrelevant for what I am trying to get an answer to. I have found similar questions on stackoverflow eg. CURL NSS client certificate not found myCert but they fall short of answering the question. I do not have/use PKCS #12 certificate.
What can I do to troubleshoot/fix why my curl command cannot find my certificate when referencing to it by its nickname.
Appreciate any help
-M