Post

Mosquitto with TLS using an AWS Broker

This post talks you through the steps of setting up an Mosquitto broker hosted on AWS then connecting to it with a Transport Layer Security (TLS) connection.

I am using just the standard Amazon Machine Image (AMI)

I followed the steps in https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/putty.html to get acces to the image via Putty and via WinSCP. I edited the Security Group inbound rules to allow All ICMP (for debugging) and TCP ports 1883-1886 for mosquitto.

The AMI image doesnt have the apt package manager, it uses YUM instead. In order to install mosquitto you also need to install the libsockets library.

1
2
3
4
5
wget http://download.opensuse.org/repositories/home:/oojah:/mqtt/CentOS_CentOS-7/home:oojah:mqtt.repo -O /etc/yum.repos.d/mqtt.repo
wget https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm -P /tmp
sudo yum install -y /tmp/epel-release-latest-7.noarch.rpm 
sudo yum install libwebsockets
sudo yum install mosquitto mosquitto-clients

 

Once the broker is running on AWS, its worth trying to connect to it without TLS to verify that the ports are open.

The next step is to create the keys & certificates for TLS authentication.

Im using OpenSSL in a Ubuntu VM. We need to create a Certification Authority (CA) certificate and then create some keys for the mqtt broker. Then we will create a Certificate Signing Request (CSR) which we will send to the CA to sign. Once the CA has signed the server keys and created a certificate, we can copy them over to the AWS machine and tweak mosquitto to use these credentials.

Create CA Certificate

1
openssl req -new -x509 -days 365 -extensions v3_ca -keyout ca.key -out ca.crt

Enter whatever information you want for the distinguishable name. I set the Common Name to “mqtt ca”.  This will create a “ca.crt” which is the certificate and a “ca.key” which is the private key.

Create Server Key & Certificate

Create a key for the server (mqtt broker). If you create a server key with encryption, you will have to enter the key passphrase everytime you start the broker.

With Encryption

1
openssl genrsa -des3 -out server.key 2048

 

Without Encryption

openssl genrsa -out server.key 2048

Now create a Certificate Signing Request (CSR). The most important step here is to use the server hostname as the Common Name, otherwise it wont work.

openssl req -out server.csr -key server.key

So my common name was “ec2-18-130-247-156.eu-west-2.compute.amazonaws.com”

Finally get the CA to sign the CSR

1
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 365

This will create a server.crt which is the certificate we can use on the AWS broker. Use WinSCP to copy over the ca.crt, server.key and server.crt to the AWS machine.

You can use the following command to verify that a certificate was signed by a CA certificate.

1
openssl verify -CAfile ca.crt server.crt

Once the files are on the AWS server, copy the default mosquitto configuration to the working directory

1
cp /etc/mosquitto/mosquitto.conf ~/aws_mosquitto.conf

At the bottom of the file, add the following items and make sure they point to the correct location

1
2
3
4
cafile /home/ec2-user/ca.crt
keyfile /home/ec2-user/server.key
certfile /home/ec2-user/server.crt
tls_version tlsv1

Start up the mosquitto broker with the following:

mosquitto -v -c aws_mosquitto.conf

On your client machine, you should be able to connect to the broker. I found two things i had to specify in order to get it working. You must explicitly specify the port number (even though im just using the default 1883) and also specify that you are using TLSv1 as by default mosquitto clients use a different version.

1
2
mosquitto_sub -h "ec2-18-130-247-156.eu-west-2.compute.amazonaws.com" -t "test" --cafile C:\Users\user\Desktop\AWS\ca.crt --tls-version tlsv1 -p 1883
mosquitto_pub -h "ec2-18-130-247-156.eu-west-2.compute.

And there we go! Thats a subscriber and publisher setup using TLS against a broker hosted on AWS.

You can also create some client keys and certificates and as long as they are signed by the same CA certificate, you can use them in a client connection.

Generate Client Keys

openssl genrsa -des3 -out client.key 2048 

Create CSR - make sure the information is not identical to the server (broker) certificate. Otherwise MQTT get confused and its difficult to debug. I kept the common name the same though (hostname).

openssl req -out client.csr -key client.key -new 

Request the Client Certificate

openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out client.crt -days 365

You can always use the verification command to check that the certificate was signed by the right CA record. Now on the client side you can use the –key and –cert arguments to reference the client certificates. You will have to enter a passphrase if you created the keys with encryption.

1
2
mosquitto_sub -h "ec2-18-130-247-156.eu-west-2.compute.amazonaws.com" -t "test" --tls-version tlsv1 -p 1883 --key C:\Users\user\Desktop\AWS\client.key --cert C:\Users\user\Desktop\AWS\client.crt --cafile C:\Users\user\Desktop\AWS\ca.crt
mosquitto_pub -d -h "ec2-18-130-247-156.eu-west-2.compute.amazonaws.com" -t "test" --tls-version tlsv1 -m "hi" -p 1883 --key C:\Users\user\Desktop\AWS\client.key --cert C:\Users\user\Desktop\AWS\client.crt --cafile C:\Users\user\Desktop\AWS\ca.crt

This post is licensed under CC BY 4.0 by the author.