emqx / CocoaMQTT

MQTT 5.0 client library for iOS and macOS written in Swift
https://www.emqx.com/en
Other
1.57k stars 411 forks source link

TLS Support with Trusted Server Certificate #573

Open savejeff opened 5 months ago

savejeff commented 5 months ago

I'm trying to get a secure connection working through MQTT from a iOS App to a broker.

First, I tried using HiveMQ as it is the most popular Broker provider. Sadly CocoaMQTT for some reason does not work with HiveMQ Brokers (see) This seems to be a problem on CocoaMQTTs end, as all other MQTT clients work for HiveMQ without a problem

Then I set up a mosquitto server. I tried to use a publicly trusted certificate provided by my domain provider, but mosquitto servers seemingly only work with self-created CAs (see). So I created my own Certificate Authority and .crt file. With Python i can simply call self.client.tls_set("/path/to/ca.crt") and i connect securely to the mqtt server as the client can verify that the server is authentic

Unfortunately, it seems CocoaMQTT does not accept .crt files or i have not found any documentation for that. For server authentication, it is only recommended to allow untrusted CAs. it says right in the readme: mqtt.allowUntrustCACertificate = true only for client authentication, there is a way to use a p12 file. This seems questionable from a security standpoint, but even if i set mqtt.allowUntrustCACertificate = true i get an error on connection with the reason that a Apple security trust error occurred.

So: What is the recommended way to securely connect to a mqtt server with working server certificate authentication? I think there is a real need to provide a full example for this use case. Mosquitto has a test server with TLS encryption here: Mosquitto Test Server Read Me. They also provide a .crt file to give to the client IMHO It should be easily possible to connect to the most popular MQTT Server software without being an expert in certificate handling and TLS handshake

Please correct me if I have overlooked information or got something wrong.

savejeff commented 4 months ago

@JaylinYu Please correct me if i state something incorrect. I would like a statement in any way on this. TLS/encrypted transmissions on the internet are very important. If this library does not support TLS secured transmissions with certificate authentication, i think this should be stated clearly

afgarcia86 commented 4 months ago

I am also interested in this 🙏

afgarcia86 commented 4 months ago

@savejeff someone on their slack pointed me to this test that seems like it will help. https://github.com/emqx/CocoaMQTT/blob/ff7c07b8a212e2e724d93a91d165a899df546db0/CocoaMQTTTests/CocoaMQTTTests.swift#L298

Have you been able to get subscriptions working? it seems like once I try to .subscribe I get disconnected with not much of a useful error message.

afgarcia86 commented 4 months ago

Ok it was somewhat buried but I found that you need to implement the following:

  func mqtt5(_ mqtt: CocoaMQTT5, didReceive trust: SecTrust, completionHandler: @escaping (Bool) -> Void) {
     // TODO: Some validation
     completionHandler(true)
  }

The wrinkle I am struggling with is it seems to require that I use the same Intermediate CA for the server & my Users. I am hoping to use unique CA's for each that have the same Root CA. Otherwise I get Code=-9831 unknown Cert Authority

savejeff commented 4 months ago

@savejeff someone on their slack pointed me to this test that seems like it will help.

https://github.com/emqx/CocoaMQTT/blob/ff7c07b8a212e2e724d93a91d165a899df546db0/CocoaMQTTTests/CocoaMQTTTests.swift#L298

Have you been able to get subscriptions working? it seems like once I try to .subscribe I get disconnected with not much of a useful error message.

This only describes how client authentication is done. right at the start with mqtt.allowUntrustCACertificate = true all Server certificates are accepted making the connection not secure.

There is still no code example how to give CocoaMQTT a server certificate that is then used to authenticate the broker I'm trying to connect to.