In our previous article we have shown how to secure EMQ connection with SSL. In that article we’ve used self generated certificate for SSL to secure the connection between broker and clients. Self generated certificates are convenient for test and development. But it is uncool to use such certificates in production, especially when you are publishing your application over the Internet. People may see untruthful certificate warning when using your service.
Luckily, we have Let’s Encrypt,one great service from Linux Foundation Collaborative Projects. It can be accessed by anyone without cost or complex procedure.
The principle of Let’s Encrypt is that it offers Domain Validation (DV) certificates, but not Organization Validation (OV) or Extended Validation (EV). By only providing DV, Let’s Encrypt is quick and simple, and it also makes automatic (no human intervention) issuing and renewing of certificates possible.
Let's Encrypt follows ACME (Automatic Certificate Management Environment) protocol. To obtain a Let’s Encrypt certificate you will need an agent installed on the server than bind to the domain you claim to have control to. The agent on the server owns a RSA key pair, it interact with the Let’s Encrypt CA, identifies it self to the CA with its public key, and responses to the challenges from the CA to prove:
This is usually done by signed/encrypt a nonce sent from the CA and hanging this signed/encrypted nonce on a URI which starts with the claimed domain.
If you are interested to know more about Let’s Encrypt, please click this: How Let’s Encrypt works.
As mentioned above, you need an agent installed on the server to generate a RSA key pair and to interact with the Let’s Encrypt CA to request a certificate. Here we will us the certbot. certbot is a ACME client by Electronic Frontier Foundation (EFF), it can request and deploy certificates on your server, an easy to use automatic tool.
to obtain an server certificate for EMQ uses only a small part of certbot’s functions. Here we assume that on the server there is no web server running and we will have to run certbot in standalone mode. In standalone mode, certbot works also as a web server and put the response on its uri and for the CA to fetch.
The default key length used by certbot is 2048, change it if necessary (--rsa-key-size parameter).
certbot may be not included in the linux distribution, taken the ubuntu 16.04 as example, you will need to install is by adding a new ppa in the system before you install the certbot.
Do the following on the server that EMQ is deployed :
$ sudo apt-get update $ sudo apt-get install software-properties-common $ sudo add-apt-repository ppa:certbot/certbot $ sudo apt-get update $ sudo apt-get install certbot
certbot provides various certificate related functions, here we just want to
request server certificate from the Let’s Encrypt CA, the
certonly command is
all that we need.
We use the built-in web server from certbot, so the
--standalone parameter is
necessary. Otherwise you can also
--webroot to make use of an already running
web server instance.
To specify the domain, we use the
-d parameter, if there are multiple domains,
then use multiple
-d. Following command will generate the RSA key pair and
obtain the certificates for you (substitute the domains with the ones that you
$sudo certbot certonly --standalone -d example.com -d iot.example.com
by default, all the generated keys and certificates can be found in
/etc/letsencrypt/live/$domain . If you take a closer look into this folder,
you will find there are no phyiscal files, there are just symbol links to files
(always the latest version) in
/etc/letsencrypt/keys . The valid period of letsencrypt certificate is
relative short, certbot has a automatic mechanism to renew the certificates.
These symbol links make the management of certificate easier.
The files are:
## the issued certificate cert.pem ## the certificate with intermediate certificates fullchain.pem ## the cert chain between issued certificate and CA certificat ## intermediate certificates chain.pem ## Private key for the certificate
Verify the certificate with OpenSSL
openssl verify -CAfile /etc/letsencrypt/live/$domain/chain.pem /etc/letsencrypt/live/zhengyupan.de/cert.pem ## Should output /etc/letsencrypt/live/$domain/cert.pem: OK
For more details about certbot please visit: https://certbot.eff.org/
Here we use EMQ 2.3.3 as example.
The dashboard of EMQ is implemented as a plugin. The default https dashboard is
not enabled, we need to enable it by modifying its conf file. The config file of
emqttd_install_location/etc/plugins/emq_dashboard.conf if you
installed it by unzip a zip package or
if you used an installation package.
The directives for enabling the https connection are already there in the conf
file, we just need to remove some leading
# of the directives and modify them
to fit our case. they are:
dashboard.listener.https = 18084 dashboard.listener.https.access.1 = allow all dashboard.listener.https.acceptors = 2 dashboard.listener.https.max_clients = 512 dashboard.listener.https.access.1 = allow all ## subtitute the $domain with your one dashboard.listener.https.keyfile = /etc/letsencrypt/live/$domain/privkey.pem dashboard.listener.https.certfile = /etc/letsencrypt/live/$domain/fullchain.pem
After doing this modification we can now restart the EMQ and try connect to the dashboard using https protocol. After that, you can see the nice green lock in your browser, it is verified by Let’s Encrypt.
By default, the WSS is enable on port 8084, we can modify the configuration to
let it use the Let’s Encrypt certificates. Modify the
listener.wss.external.keyfile = /etc/letsencrypt/live/$domain/privkey.pem listener.wss.external.certfile = /etc/letsencrypt/live/$domain/fullchain.pem
Then restart the EMQ, start a WS client with SSL checked:
On the dashboard check the listeners, it shows one client is connected per wss on port 8084:
In the previous article we’ve talked about enabling MQTT/SSL using self signed certificate. On the EMQ side, this time we will do almost the same, only difference is that we will use Let’s Encrypt issued certificates this time.
listener.ssl.external.keyfile = /etc/letsencrypt/live/$domain/privkey.pem listener.ssl.external.certfile = /etc/letsencrypt/live/$domaion/fullchain.pem
This time we are still going to use the mosquitto client to verify the SSL
connection. I guess that you still remember in previous article we passed a
--cafile parameter to the mosquitto client to enable the SSL, the cafile is
the certificate of issuer of the domain certificate.
To verify the domain certificate, the mosquitto client need to have all the
intermediate certificates and the certificate of Root CA. As mentioned above,
chain.pem contains the intermediate certificates. But where is the
certificate of Root CA?
The domain certificate is issued by intermediate “Let’s Encrypt Authority X3”, this intermediate is cross-signed by “DST Root CA X3” (from IdenTrust). IdenTrust is widely trusted by most OSes and applications, we will “DST Root CA X3” as root CA.
You have good chance that you already have the ca certificate of “DST Root CA
X3” if you run a not-too-old OS and a not-too-old OpenSSL or Browser. Taking
Ubuntu 16.04 as example, check if this file exists:
Combining these two files together, then we have the cafile to verify the domain ceritificate sent by EMQ.
cat /etc/ssl/certs/DST_Root_CA_X3.pem /etc/letsencrypt/live/$domain/chain.pem > ca.pem
SSL Connection using the
mosquitto_sub -t abc -h $domain -p 8883 -d --cafile ~/ca.pem Client mosqsub/31415-hxxxxxxx. sending CONNECT Client mosqsub/31415-hxxxxxxx. received CONNACK Client mosqsub/31415-hxxxxxxx. sending SUBSCRIBE (Mid: 1, Topic: abc, QoS: 0) Client mosqsub/31415-hxxxxxxx. received SUBACK Subscribed (mid: 1): 0
Check the listeners on the dashboard:
I hope you like our article. If you have any questions, please visit EMQ X Website.
Or write to us: firstname.lastname@example.org