I have set up a mosquitto MQTT server and created everything to encrypt the communication. The certificates are created with this script here. Everything works fine. The certificates check out with openssl verify -CAfile ca.crt cool-server.crt
as "ok".
But I do not understand why on different clients differently.
The broker runs on an Ubuntu 18 server. Config here:
root@cool-server:~# cat /etc/mosquitto/conf.d/default.conf
allow_anonymous false
password_file /etc/mosquitto/passwd
listener 1883 localhost
listener 8883
cafile /etc/mosquitto/ca_certificates/ca.crt
certfile /etc/mosquitto/certs/cool-server.crt
keyfile /etc/mosquitto/certs/cool-server.key
require_certificate true
#require_certificate false # tried this too
tls_version tlsv1.2
root@cool-server:~# cat /etc/mosquitto/mosquitto.conf
# Place your local configuration in /etc/mosquitto/conf.d/
#
# A full description of the configuration file is at
# /usr/share/doc/mosquitto/examples/mosquitto.conf.example
pid_file /var/run/mosquitto.pid
persistence true
persistence_location /var/lib/mosquitto/
log_type all
log_dest file /var/log/mosquitto/mosquitto.log
include_dir /etc/mosquitto/conf.d
I can connect to it via
The questions are:
1. Why is it, that some clients need a certificate of fingerprint and others not?
According to my knowledge, TLS/SSL can secure the connection with only a certificate on the server side, but I am not sure. The Android app connects to my broker without any certificate or fingerprint, while mosquitto_pub
only works with a cacert. Even if I configure the broker with require_certificate false
the client still needs to specify the cacert. --insecure
does not solve this. On the other hand, my ESP8266 only need a short fingerprint.
2. Are all my connections (especially the Android one) secure/encrypted?
ESP8266 / Arduino
const uint8_t mqttCertFingerprint[] = {0xA6, 0x4D, 0x9F, 0x43B, 0x80, 0xB7, 0xB2, 0x9A, 0x9D, 0xCB, 0xC9, 0xF7, 0xAA, 0xCC, 0x30, 0xEF, 0xF4, 0xFC, 0xD3, 0x31};
mqttClient_.setSecure(true);
mqttClient_.addServerFingerprint(mqttCertFingerprint);
Bash
mosquitto_pub -h cool-server.com -p 8883 -u user -P Password -t "topic/name" -m "hello" --cafile path/to/ca.crt
Android
if (serverUri.contains("ssl")) {
class TrustEveryoneManager implements X509TrustManager {
public void checkClientTrusted(X509Certificate[] arg0, String arg1){}
public void checkServerTrusted(X509Certificate[] arg0, String arg1){}
public X509Certificate[] getAcceptedIssuers() {
return null;
}
}
SSLContext sslContext = SSLContext.getInstance("tls");
sslContext.init(null, new TrustManager[]{new TrustEveryoneManager()}, new SecureRandom());
mqttConnectOptions.setSocketFactory(sslContext.getSocketFactory());
}
Assuming you are not using self signed certs.
Both mosquitto_pub/sub and the PubSubClient Library require a CA certificate because they do not have a baked in trust store that contains a list of trusted certificates from the Certificate Authorities.
On Android there is a baked Trust Store.
On Linux you can normally point the mosquitto tools at /etc/ssl/certs/
to use the Trust Store CA certs that ship with the OS.
Update:
The certificate fingerprint is enough to verify that brokers certificate as long as the broker presents the full certificate chain when the client connects. The client can check that the broker certificate is signed by the CA cert and that the CA cert fingerprint matches the supplied one.
No, you Android client is not secure. You have explicitly told Android to trust any certificate presented by the broker, this means that anybody can run a man in the middle attack against your android application and you will never be able to tell.