Skip to main content

Tutorial: Use TLS in Python for MQTT

If you are familiar with the Python Paho MQTT library, implementing TLS is simple.

Prerequisites
  • Ensure you have a server certificate file created and configured on the FairCom server.Tutorial: Create certificates using OpenSSL

    You must create a separate server certificate for each computer that runs a FairCom server. Each FairCom server must be configured to use the appropriate server certificate for the computer on which it runs

  • Ensure you have client certificate file created and ready to use in this Python program.Tutorial: Create certificates using OpenSSL

    The client certificate file allows the Python program to identify itself to the FairCom server. Each Python program that wants to use a certificate must be configured to send the certificate to the server. When the FairCom server is not configured with the CA certificate, do not use a client certificate in a Python program.

Ensure you meet the prerequisites before this procedure.

  1. Configure the MQTTS listener in the services.json file to use your CA certificate, server certificate, and private key.

  2. Ensure the "enabled" property is set to true.

  3. Update the "tls" object:

    • Update the "certificateFilename" property value to the certificate you obtained for this FairCom server.

    • Add a "privateKeyFilename" property and set it to the private key for this FairCom server.

    • Add a "certificateAuthoritiesFilename" property and set it to the path and filename containing CA certificate.

      Note

      This is the certificate from the CA that signed the server certificate.

  4. Save any changes.

  5. Restart the server for the changes to take effect.

Example 1. MQTTS listener
{
  "serviceName": "mqtts8883",
  "description": "Port 8883 using TLS-secured MQTTS protocol for the MQTT broker on all TCP/IP addresses bound to this server",
  "port": 8883,
  "protocol": "mqtts",
  "enabled": true,
  "tls": {
    "certificateAuthoritiesFilename": "C:/Certificates/ca.crt",
    "certificateFilename":            "C:/Certificates/server.crt",
    "privateKeyFilename":             "C:/Certificates/server.key"
  }
},


Example 2. MQTTWSS listener
{
  "serviceName": "mqttwss9002",
  "description": "Port 9002 using TLS-secured WebSocket protocol for the MQTT broker on all TCP/IP addresses bound to this server",
  "port": 9002,
  "protocol": "mqttwss",
  "enabled": true,
  "tls": {
    "certificateAuthoritiesFilename": "C:/Certificates/ca.crt",
    "certificateFilename":            "C:/Certificates/server.crt",
    "privateKeyFilename":             "C:/Certificates/server.key"
  }
}


Ensure you meet the prerequisites before this procedure.

Make the following updates to your MQTT code:
  1. Update the "port" property value to the TLS port used by your broker.

  2. Call tls_set() on your paho.mqtt.client class object with the following parameters (see Example program):

    1. ca_certs

    2. certfile

    3. keyfile

Ensure you meet the prerequisites before this procedure.

Build an MQTT project:
  1. Create a callback function that will print any messages received using the following code:

    def message_callback( message_client, userdata, message ):
      print( message.payload.decode( 'utf8' ) )
  2. Define a client using the following code:

    Note

    To use a secure WebSocket, this call only needs the additional parameter of transport = 'websockets'.

    mqtts_client = mqtt.Client( client_id = "MQTTS Client ID" )
  3. Enable TLS by calling tls_set() on the newly created client using the following code:

    mqtts_client.tls_set( ca_certs = "/Certificates/ca.crt", 
                          certfile = "/Certificates/client.crt", 
                          keyfile = "/Certificates/client.key" )
  4. Assign the message callback to the client using the following code:

    Note

    There are many callbacks in the Paho library, including on_connect, on_connect_fail, on_disconnect, on_message, on_publish, on_subscribe, on_unsubscribe, on_log, on_socket_open, on_socket_close, on_socket_register_write, on_socket_unregister_write.

    mqtts_client.on_message = message_callback
  5. Call loop_start() on the client to begin processing MQTT events using the following code:

    mqtts_client.loop_start()
  6. Connect the client and server using the following code:

    Note

    The port is set to 8883. This must match the port configured in services.json. The broker address must also match the address in its certificate.

    mqtts_client.connect( "MyServer.local", port = 8883 )
  7. Wait a few seconds or use the on_connect callback as a guide to when the connection has been made.

    Note

    The connection will appear instantaneously, but work is happening in the background.

  8. Subscribe to a topic of your choice using the following code:

    mqtts_client.subscribe( "test/MqttsTopic" )
  9. Publish to your chosen topic using the following code:

    mqtts_client.publish( "test/MqttsTopic", "Simple MQTTS message" )
  10. Implement a simple non-blocking delay using the following code:

    Note

    Do this step because even though the message will arrive in a few milliseconds, your code could finish before the message arrives.

    count = 0while count < 5:  time.sleep( 1 )  count += 1
  11. Observe the message:

    Note

    Receiving the message means your client was able to subscribe and publish to your broker using TLS for encryption and authentication.

    Simple MQTTS message
  12. Close the connection using the following code:

    mqtts_client.unsubscribe( "test/MqttsTopic" )
    mqtts_client.disconnect()
    mqtts_client.loop_stop()
    
import time
import paho.mqtt.client as mqtt


def message_callback( message_client, userdata, message ):
  print( message.payload.decode( 'utf8' ) )


if __name__ == "__main__":
  mqtts_client = mqtt.Client( client_id = "MQTTS Client ID" )
  mqtts_client.tls_set( ca_certs = "/Certificates/ca.crt", 
                        certfile = "/Certificates/client.crt", 
                        keyfile = "/Certificates/client.key" )
  mqtts_client.on_message = message_callback
  mqtts_client.loop_start()

  mqtts_client.connect( "MyServer.local", port = 8883 )
  time.sleep( 2 )

  mqtts_client.subscribe( "test/MqttsTopic" )
  mqtts_client.publish( "test/MqttsTopic", "Simple MQTTS message" )

  count = 0
  while count < 5:
    time.sleep( 1 )
    count += 1
  mqtts_client.unsubscribe( "test/MqttsTopic" )
  mqtts_client.disconnect()
  mqtts_client.loop_stop()
import time
import paho.mqtt.client as mqtt


def message_callback( message_client, userdata, message ):
  print( message.payload.decode( 'utf8' ) )


if __name__ == "__main__":
  mqtts_client = mqtt.Client( client_id = "MQTTS Client ID", transport = 'websockets' )
  mqtts_client.tls_set( ca_certs = "/Certificates/ca.crt",
                        certfile = "/Certificates/client.crt",
                        keyfile = "/Certificates/client.key" )
  mqtts_client.on_message = message_callback
  mqtts_client.loop_start()

  mqtts_client.connect( "MyServer.local", port = 9002 )
  time.sleep( 2 )

  mqtts_client.subscribe( "test/MqttWssTopic" )
  mqtts_client.publish( "test/MqttWssTopic", "Simple MQTT WSS message" )

  count = 0
  while count < 5:
    time.sleep( 1 )
    count += 1
  mqtts_client.unsubscribe( "test/MqttWssTopic" )
  mqtts_client.disconnect()
  mqtts_client.loop_stop()