Introduction to MQTT Security Mechanisms

securityIn 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.

clientid_prefixes C1-

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.

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.

Mosquitto Configuration Tutorials

Related Tutorials and Resources:

Save

Save

Facebooktwittergoogle_plusredditpinterestlinkedinmail

14 comments

    1. 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

  1. 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

    1. 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

  2. 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?

      1. 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?

  3. 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.

    1. 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”)))

      The example publish and subscribe script I will make available on the downloads page.
      http://www.steves-internet-guide.com/downloads/
      http://www.steves-internet-guide.com/wp-content/uploads/publish-subscribe-payload-encrypt.7z

Leave a Reply

Your email address will not be published. Required fields are marked *