In this tutorial we look at how you can restrict access to a broker, and how you can protect your data using various security mechanisms.
It is important to note that these security mechanisms are initiated by the broker, and it s up to the client to comply with the mechanisms in place.
It is also important to realise that when planning security for your implementation that you must consider the capabilities of your MQTT clients as well as your broker.
This tutorial will use the free Open source Mosquitto broker, and the Paho Python MQTT client to illustrate these mechanisms.
Client Authentication
There are three ways that a Mosquitto broker can verify the identity of an MQTT client:
- Client ids
- Usernames and passwords.
- Client Certificates
Client ids
All MQTT clients must provide a client id.
When a client subscribes to a topic/topics the client id links the topic to the client and to the TCP connection.
With persistent connections the broker remembers the client id and the subscribed topics.
When configuring an MQTT client you will need to assign a name/id to the client generally that name is unimportant as long as it is unique.
However the Mosquitto Broker allows you to impose client id prefix restrictions on the client name, and this provides some basic client security.
You could,for example, choose a prefix of C1- for your client ids and so a client with client id of C1-python1 would be allowed but a client with id of python2 would not be allowed.
You will find this setting in the security settings section of the mosquitto.conf file.
Username and Password
An MQTT broker can require a valid username and password from a client before a connection is permitted.
The username/password combination is transmitted in clear text and is not secure without some form of transport encryption.
However it does provide an easy way of restricting access to a broker and is probably the most common form of identification used.
The username used for authentication can also used in restricting access to topics.
On the Mosquitto broker you need to configure two settings for this to work. Again you will find these settings in the security section of the mosquitto.conf file.
They are allow_anonymous and password_file. To require username/password then allow_anonymous should be false and password_file should contain a valid passwords file.Example settings
allow_anonymous false password_file c:\mosquitto\passwords.txt #Windows machine
To create the passwords you will need to use the mosquiito_passwd utility that comes with the Mosquitto broker.
See Exploring Username and Password Authentication – MQTT by example
x509 Client Certificates
This is the most secure method of client authentication but also the most difficult to implement because you will need to deploy and manage certificates on many clients.
This form of authentication is really only suited to a small number of clients that need a high level of security.
See SSL and SSL Certificates Explained
Restricting Access to topics
You can control which clients are able to subscribe and publish to topics.
The main control mechanism is the username. (note: password not required), but you can also use the client id.
Unless you are running an open broker then this type of restriction will be common. See Configuring and exploring Topic Restrictions on Mosquitto
Securing Data
To protect the contents of your MQTT messages you can use:
- TLS or SSL Security
- Payload encryption
TLS Security
TLS security or as it is more commonly known SSL security is the technology that is used on the web.
This security is part of the TCP/IP protocol and not MQTT.
TLS security will provide an encrypted pipe down which your MQTT messages can flow.
This will protect all parts of the MQTT message, and not just the message payload.
The problem with this is that it requires client support, and it is unlikely to available on simple clients.
Payload Encryption
This is done at the application level and not by the broker. This means that you can have encrypted data without having to configure the broker.
It also means that data is encrypted end to end and not just between the broker and the client.
MQTT is after all a messaging protocol.
However this type of encryption doesn’t protect passwords (if used) on the connection itself.
Because it doesn’t involve any broker configuration or support this is likely to be a very popular method of protecting data.
See Encrypting The MQTT Payload Python Example
Common Questions and Answers
Q- Can I use TLS with payload encryption?
A- Yes.
Q- To implement payload encryption do I need certificates?
A- No. You can use shared keys which is easier to implement.
Q- How do I know if the message is genuine and hasn’t been changed?
A- Digital signatures are the best way of doing this but they rely on a public/private key infrastructure and are unlikely to be implemented on constrained clients like sensors. However simple alternatives like HMAC are available see this hive security article.
Summary
There are several mechanisms available for securing MQTT connections.
Security restrictions are enforced by the MQTT broker, and the client must be configured accordingly.
Course Tutorials Home<<Prev….Next>>Using MQTT Over WebSockets
Mosquitto Configuration Tutorials
Related Tutorials and Resources:
- MQTT Basics for Beginners
- Username and Password Authentication – MQTT by example
- Hive MQTT Security Fundamentals
- JWT based authentication (Google paper)
Hi Steve thanks for sharing securing MQTT.
I would like to use username and password to authenticate the client and encrypt everything through CA signed server certificate, my question is: in this mode the credentials pass in clear text or are they protected by the ssl channel?
thanks in advice for support.
With SSL everything is encrypted including the username/password
Hi Steve great info sharing on securing MQTT.
In this statement “This will protect all parts of the MQTT message, and not just the message payload.”
Does that include Topic encryption as well when we use TLS? or are the topics visible in plaintext?
Looking forward to your response.
Yes it includes the topic
rgds
steve
Hi Steve,
Thanks for your tutorial. I want to implement home automation system using mqtt protocol on esp8266(tiny) I know the way forward. I will check whether there is an encryption library on arduino as well.
Ah, further digging brought me here: https://mosquitto.org/man/mosquitto-conf-5.html
This answers my questions (and more!) about SSL for client auth and securing data; would still be interested in (informed) opinions about magnitude of added latency when using SSL w/ MQTT.
Thanks,
Chris
Chris
Just did a quick test and found no great difference in the time taken to send/receive messages. If you know Python I can send you the scripts so you can run your own tests.
rgds
Steve
Hi Steve,
Are the “client authentication” vs “securing data” aspects of using SSL/TLS separable? Can one use x508 certs solely for client authentication without also encrypting the data? I’d like to securely limit who can subscribe but I’m not terribly concerned about third parties sniffing the data; my overriding goal is the fastest throughput possible, where milliseconds count, and I’m assuming there’s an added latency to encrypt/decrypt the message stream, and perhaps also an added latency if encrypted data are larger than unencrypted. I have little feel for the typical “costs” (in latency) of either of these relative to the total transit time from device through broker to client, so perhaps my concerns are misplaced (and I’d be glad to be set straight on that), but that’s where my question comes from…
Thanks so much for your fantastic suite of clear and concise resources on MQTT and related topics!
Chris
My understanding is that they are completely independent of each other but I have never tried using client certificates for authentication.
I’m also not sure about the effect of SSL on latency but expect that it has a cost.
I did start writing a Python script to test it but got side tracked. I will try to get around to finishing it.
Rgds
Steve
hello again steve,
can i load the paho python code to esp8266? is it possible?
Roy
Not familiar with esp8266 but I did a search and it seems that it uses micropython and has its own micropython mqtt client.
Take a look here
https://www.hackster.io/bucknalla/mqtt-micropython-044e77
rgds
steve
hello there steve, since TLS is not part of mqtt per se and its not advisable to low resource IoT device, is it possible to encrypt the ENTIRE mqtt message including the username and password using other encryption algorithm(lightweight)? is it possible?
Rey
Not as far as I know but you can encrypt the message. In fact I think this is the better option anyway as it is end to end and not client to broker. I did an tutorial demo using python here.
http://www.steves-internet-guide.com/encrypting-the-mqtt-payload-python-example/
thanks for you reply steve, do you have tutorials in how to used TLS in MQTT?
how TLS encrypt information from Publisher and how the subscriber decrypt it using TLS? How TSL encrypt the entire message or only the payload was encrypted by TLS?
TLS is a link encryption mechanism and only encrypts the link between client and broker. To have end to end encryption each link would need TLS.
Alternatively you can use message payload encryption for end to end encryption. see
http://www.steves-internet-guide.com/encrypting-the-mqtt-payload-python-example/
http://www.steves-internet-guide.com/mosquitto-tls/
I believe there is a typo in your description (above) of allow_anonymous. Should this not read that it should be set to FALSE, to require username / password authentication? The mosquitto.conf file comment indicates that allow_anonymous should work this way which contradicts this page.
Thanks,
Tom
>>They are allow_anonymous and password_file. To require username/password then allow_anonymous should >>be true and password_file should contain a valid passwords file.
Tom
Tks for spotting that I’ve corrected it
Rgds
Steve
Please give more detail how to do the Payload Encryption….
In python I’ve tried it using the cryptography package to do the encryption and decryption.
You take the message you are sending (the payload) encrypt it and then send it as normal.
cipher_key = Fernet.generate_key()
cipher = Fernet(cipher_key)
message = b’on’ #message to send
encrypted_message = cipher.encrypt(message)
out_message=encrypted_message.decode()# turn it into a string to send
client.publish(“house/bulb1”,out_message)#publish
in The on_message callback we decrypt
def on_message(client, userdata, message):
#time.sleep(1)
print(“payload “,message.payload)
if message.payload==encrypted_message: #check if the same
print(“same”)
decrypted_message = cipher.decrypt(message.payload) #decrypted_message = cipher.decrypt(encrypted_message)
print(“received message =”,str(decrypted_message.decode(“utf-8”)))