LabVIEW-Open-Source / MQTT-Client

A LabVIEW-based client for MQTT
Other
27 stars 5 forks source link

MQTT TLS Connection without Certificates #23

Closed dlsdud1714 closed 1 year ago

dlsdud1714 commented 1 year ago

We are required to publish data over MQTT to a broker configured on AWS (configuration is set up by someone external to our team). They have provided the following example python code to connect to the broker:

client.tls_set(ca_certs=ca_cert, certfile=client_cert, keyfile=client_key, cert_reqs=ssl.CERT_NONE, tls_version=ssl.PROTOCOL_TLSv1_2)

where the key thing to note is the presence of cert_reqs=ssl.CERT_NONE. Is there an easy way of specifying this flag using the LabVIEW MQTT-Client library?

For context:

We were using the LabVIEW MQTT Client libary to connect to the broker, and were successful until about 1 week ago. We explicitly used the Secured TCP Client to specify certificate details, and were successful in forming a connection and publishing to topics. TCPSecured All of a sudden, we began to get this error about a week ago:

LabVIEW: (Hex 0xFFF516D2) REMOTE HOST IDENTIFICATION HAS FAILED! Required peer hostname doesn't match hostname on peer's certificate. While negotiating a secure connection, the peer presented a certificate whose hostname differs from the hostname used to connect to the peer.

However, the python code still works (probably because it doesn't enforce checking of the certificates). We tried using the non TLS version of the MQTT libary and got error 66. Our assumption is that we need to use TLS but turn off the checking of certificates.

We also tried not using the Configure Secured TCP Client Certificate and Key. However, We still have the same erorr like the above. Can anyone validate our assumptions and help us to restablish connection?

francois-normandin commented 1 year ago

@dlsdud1714,

I have never used TLS for AWS without certificates, but from what I can tell, the code probably work but I believe you might need to change the Secured TCP Client instantiation so that there are no trusted entities in the private data, instead of a 1-element array of "empty path".

First, may I suggest you try to set the AWS Root Certificate even though your client does not need to authenticate? It is never a bad idea to authenticate that you are actually connecting to the right server. (Make sure no one redirected your connection to a phony server).

image

If it still does not work, it could be that there is a need for a slight change in the code:

When the TLS client is instantiated, I suggest you try to set the Trusted Entities to an empty array in case the X509 certificate is an empty path... Instead of this: image

Try this: image

When you do, the server will report Not Ready for SSL. Then proceed with the "Configure Connection" method without certificates, such that the Connection will leave you with ClientTLS? = False AND an empty list of trusted entities. Those two should skip the addition of both client and server certificates to the TLS nodes, which probably error out at the moment because the X509 certificate is empty. image

If this modification works for you, please report your findings and I will modify the code accordingly for the next release.

dlsdud1714 commented 1 year ago

@francois-normandin

I appreciate your suggestion, as it has proven invaluable. It turned out we could not establish a connection to the server without an AWS Root Certificate. In this case, the initial solution you provided was applied well. However, I had to add one specific detail to initiate TLS and bypass hostname verification. In this case, I had to send an empty string to the server's hostname input of "Start TLS" image image

Consequently, I explicitly provided an empty string as the Hostname input in the Secured TCP Client. image

Thank you so much for the detailed answer and your suggestion.