Eclipse Mosquitto: Leveraging Certificates for Encryption, Identification, and ACLs
This blog post delves into the sophisticated use of TLS certificates with Mosquitto, transcending their conventional role as encryption tools to serve as pivotal elements in client authentication and authorization.
We’ll explore how certificates, typically recognized for their role in securing communications, can be ingeniously repurposed for client identification through their Common Name (CN) attribute. This approach not only enhances the security posture of your MQTT ecosystem but also simplifies the authentication process. Furthermore, we will discuss how Access Control Lists (ACLs) can be seamlessly integrated with this identification mechanism, enabling precise control over who can publish or subscribe to specific topics. This synergy of encryption, identification, and access control not only fortifies the security of MQTT communications but also paves the way for more streamlined and manageable client permissions.
To implement the security measures discussed, we need to configure Mosquitto appropriately. Let’s break down the essential elements of the configuration:
# This line tells Mosquitto to listen for MQTT connections on port 8883
# (the standard port for MQTT over TLS) and to accept connections from any IP address.
listener 8883 0.0.0.0
# These specify the paths to the CA certificate, the server's certificate,
# and the server's private key, respectively.
cafile /mosquitto/certs/ca.pem
certfile /mosquitto/certs/server.pem
keyfile /mosquitto/certs/server.key
# By setting require_certificate to true, a client connecting to this listener must
# provide a valid certificate in order for the network connection to proceed.
# This allows access to the broker to be controlled outside of the mechanisms provided by MQTT.
require_certificate true
# If require_certificate is true, you may set use_identity_as_username to true
# to use the CN value from the client certificate as a username.
use_identity_as_username true
# This points to the Access Control List (ACL) file, which contains rules defining the
# permissions for different users, based on their usernames - in our case,
# the identities derived from their certificates.
acl_file /mosquitto/acl/acl.acl
Generating Certificates
To secure our Mosquitto setup, we’ll generate our own root Certificate Authority (CA), server certificates, and client certificates.
Note: Use PEM format and .pem file extension, to avoid certificate validation issues.
Here’s how this is done:
Root Certificate Authority Generation
Generate CA Private Key:
This command generates a 2048-bit RSA private key for our CA and saves it to ca.key.
openssl genrsa -out ca.key 2048
Create CA Certificate:
Here, we’re creating a self-signed root CA certificate using the previously generated private key. The -x509 flag indicates this is a self-signed certificate, -sha256 specifies the use of SHA-256 hashing algorithm, and -days 1024 sets the certificate to be valid for 1024 days.
Generate Server Private Key:
This generates the server’s 2048-bit RSA private key.
openssl genrsa -out server.key 2048
Create a Certificate Signing Request (CSR) for the Server:
The CSR contains information like the organization’s name and the server’s domain name (Common Name). As a good practice,
provide the domain name or a logical name to the “Common Name” section.
openssl req -new -key server.key -out server.csr
Sign the Server CSR with the CA:
This command uses the root CA to sign the server’s CSR, generating the server.pem certificate valid for 500 days.
In scenarios where we have multiple devices communicating via MQTT, it’s crucial to enforce fine-grained access control. A common approach is to generate unique client certificates for each device, using the device ID as part of the certificate’s Common Name (CN), combined with the server configuration use_identity_as_username true (see above). This setup allows us to restrict each device to specific topics in the Mosquitto broker using ACLs.
Generate Device Private Key:
openssl genrsa -out Device123.key 2048
Create a CSR for the Device:
When prompted for the ‘Common Name’, use the device’s unique identifier (e.g., Device123).
With the client certificates in place, we can now configure Mosquitto’s ACL file to restrict access based on the device ID. Here’s how to set up the ACL:
Edit the ACL File (/mosquitto/acl/acl.acl):
In this configuration, %u will be replaced by the username of the connecting client (i.e., the device ID as per the client certificate’s CN). For instance, if a device with the CN Device123 connects, %u will be replaced with Device123, effectively allowing the device to access topics under /device/Device123/#.
user Device123
topic readwrite /device/%u/#
By leveraging dynamic placeholders like %u in our ACL file, we achieve a flexible yet secure way of managing topic access across a multitude of devices. This method not only reinforces the security of our MQTT communications but also introduces scalability and ease of management in complex IoT environments
By using the device’s ID in both the certificate and the ACL configuration, we create a secure and straightforward way to ensure that each device can only access its designated topics. This method enhances the security and integrity of our MQTT communication.
Final Steps: Verifying Your Secure MQTT Setup
After configuring Mosquitto and generating the necessary certificates, it’s important to verify that the setup works as expected. Let’s go through a couple of verification steps to ensure that our MQTT environment is secure and functional.
Verifying TLS Communication with OpenSSL
To test the TLS handshake and verify that the server is correctly using the provided certificates, we can use the openssl s_client command:
Look for messages indicating a successful TLS handshake. This will confirm that the client can establish a secure connection with the MQTT broker using the provided certificates.
Testing MQTT Connection with Mosquitto Client
Finally, let’s test the MQTT publish functionality using mosquitto_pub:
Successful execution of this command will publish the message “22.5” to the specified topic, demonstrating that your MQTT client can securely communicate with the broker using TLS.
Wrapping Up
By following the steps in this guide, you’ve set
up a secure MQTT environment using Mosquitto, where communication is encrypted, and clients are authenticated and authorized using TLS certificates. This approach not only enhances the security of your MQTT communication but also provides a scalable way to manage client access through ACLs.
Remember, regular maintenance and updates to your Mosquitto setup and certificates are essential to keep your IoT environment secure.