TLS/SSL - MQTT Security Fundamentals
Welcome to the fifth part of the MQTT Security Fundamentals series. In the previous post, we looked at authentication in MQTT and authorization in MQTT on the application layer. In this post, we tackle Transport Encryption with TLS.
Join us as we explore why TLS / SSL is expedient for a secure MQTT solution and talk about best practices for transport encryption with MQTT.
What is TLS?
Transport Layer Security (TLS) and Secure Sockets Layer (SSL) provide a secure communication channel between a client and a server. At the core, TLS and SSL are cryptographic protocols which use a handshake mechanism to negotiate various parameters to create a secure connection between the client and the server. After the handshake is complete, an encrypted communication between client and server is established and no attacker can eavesdrop any part of the communication. Servers provide a X509 certificate (typically issued by a trusted authority) that clients use to verify the identity of the server.
A detailed description of how TLS and the TLS handshake work is beyond the scope of this blog post. However, a good starting point for learning about TLS is O’Reilly: High Performance Browser Networking / Chapter 4: Transport Layer Security (TLS).
Why is TLS important?
Imagine that you are sending a postcard. It’s clear who the recipient of the card is and the postman will make sure that the card arrives. But, nothing prevents the postman from reading the content of the card. In fact, everyone who is involved in delivering the postcard can read the content of your postcard. A malicious postal worker could even alter the content of your card!
The essence of this scenario is also true for computer networks in general and the Internet in particular. Use of plain TCP/IP is like sending the postcard. The TCP packet passes through many infrastructure components (routers, firewalls, Internet Exchange Points) before it reaches the target. Every participant along the way can read the content of the packet in clear text (and even modify it). This is not a fictitious scenario, recent history shows that Internet traffic is frequently wiretapped by intelligence agencies. While most attackers don’t have a lot of resources to eavesdrop your connection, it’s not difficult for sophisticated attackers to perform Man-In-The-Middle-Attacks.
TLS is all about providing a secure communication channel. TLS ensures that the content of your communication can not be read or altered by third parties*.
Assuming secure cipher suites are used and there are no undiscovered attacks on the TLS version used.
MQTT and TLS
MQTT relies on the TCP transport protocol. By default, TCP connections do not use an encrypted communication. To encrypt the whole MQTT communication, many MQTT brokers (such as HiveMQ) allow use of TLS instead of plain TCP. If you use the username and password fields of the MQTT CONNECT packet for authentication and authorization mechanisms, you should strongly consider using TLS.
Port 8883 is standardized for a secured MQTT connection. The standardized name at IANA is “secure-mqtt”. Port 8883 is exclusively reserved for MQTT over TLS.
There is a drawback to using MQTT over TLS: Security comes at a cost in terms of CPU usage and communication overhead. While the additional CPU usage is typically negligible on the broker, it can be a problem for very constrained devices which are not designed for computation-intensive tasks. Techniques such as Session Resumption can drastically improve the TLS performance.
The communication overhead of the TLS Handshake can be significant if the MQTT client connections are expected to be short-lived. While the amount of bandwidth the TLS handshake needs depends on many factors, some measurements show that establishing a new TLS connection can require up to a few kilobytes of bandwidth. Since every packet is encrypted in TLS, packets on the wire have additional overhead compared to the unencrypted packets.
If you use long-living TCP connections with MQTT (which you should!), the TLS overhead, especially the TLS Handshake overhead can be negligible. If you deal with many reconnects and you can’t use session resumption, then the overhead can be significant, especially if you are publishing very small MQTT messages. If every byte on the wire counts for your use case, TLS may not be the best option for you because of the overhead. Be sure to measure how much overhead TLS creates for your use case.
We mentioned TLS session resumption in regards to TLS Overhead. In a nutshell, TLS session resumption techniques allow the reuse of an already negotiated TLS session after reconnecting to the server. The client and server don’t need to repeat the full TLS handshake. It’s important to note that some TLS libraries do not implement all session resumption techniques. In fact, some TLS libraries don’t implement any session resumption mechanism at all.
There are two session resumption mechanisms:
- Session IDs: The server stores the secret state together with the session ID. When the client reconnects, it provides the session ID and the session can be resumed.
- Session Tickets: The secret state of the server is transmitted to the client and is encrypted with a secret key only the server knows. The client sends this ticket back to the server when reconnecting. If the server can decrypt the contents again, the session is resumed with the state contained in the secret ticket.
HiveMQ supports session IDs but does not support session tickets.
TLS on constrained devices
Sometimes, TLS is not feasible for constrained devices due to insufficient resources. Depending on the ciphers used, TLS can be very computation intensive and can require many kilobytes of memory. If TLS is not possible with your devices, think about using payload encryption for your PUBLISH messages and at least hash or encrypt the password in the CONNECT message of your client. More on that topic in one of our upcoming posts.
It may also be an option to look into TLS-PSK cipher suites. These suites avoid the CPU intensive public key operations. TLS-PSK ciphers are not widely adopted yet, so you need to double check if your TLS library supports them.
Should I always use TLS with MQTT?
Short answer: Yes, if you can. Long answer: If you can afford the overhead in CPU and bandwidth, then a secure communication channel is invaluable. If TLS is implemented properly on the client and server side, you ensure that no eavesdropper can intercept your communication and you get that additional layer of security that is important for application-level authentication and authorization.
Best practices for MQTT Security
Always use TLS if you can
Always use TLS with MQTT if you can afford the additional bandwidth and your clients have enough computing power and memory for TLS. As a rule of thumb, always use encrypted communication channels, also for other protocols like HTTP.
Use the highest available TLS version possible
While TLS 1.0, TLS 1.1 and TLS 1.2 are not broken in practice (at least until now), you should always use the highest TLS version that is feasible for your MQTT clients. There are well-known attacks against TLS 1.0 and 1.1, which can be mitigated. Some attacks are designed to exploit HTTP. For example, the CRIME attack. At the time of writing there are no practically-applicable attacks against TLS 1.2.
Don’t use SSLv3
Don’t use SSLv3 or any prior versions. The POODLE attack showed that SSLv3 must be considered broken. All other SSL versions are also considered broken and should not be used.
Always validate the X509 certificate chain
To prevent Man-In-The-Middle attacks, have your MQTT clients validate the X509 certificate from the MQTT broker. Some sloppy client implementations use an “allow-all” approach (often in combination with self-signed server certificates). Never do this! Going the extra mile to validate certificates is always worth the effort.
Use certificates from trusted CAs
Certificates from trusted CAs are worth the extra money they cost. Self-signed certificates don’t play well with many TLS implementations and often lead to sloppy code. For example, code that doesn’t validate certificates and opens the door for Man-In-The-Middle attacks. If your MQTT broker is public-facing, a trusted certificate is a must. If you use MQTT over websockets, self-signed certificates are not optimal. Most modern web browsers don’t allow websocket connections to resources with untrusted certificates.
Use other security mechanisms
In addition to TLS, it is always a good idea to use further security mechanisms such as payload encryption, payload signature verifications, and authorization mechanisms. In general, more security never hurts.
Only use secure cipher suites
There are many insecure cipher suites available for TLS. Make sure to only allow secure cipher suites for your communication. Many cipher suites are known to be broken and don’t a false sense of security.
We hope you enjoyed part five of the MQTT Security Fundamentals. In the next post, we’re going to discuss X509 client certificate authentication in conjunction with TLS. Subscribe to our newsletter or RSS feed to get updates from HiveMQ. If you think we missed some important information, please use the comments to tell us. We are always open to questions and suggestions.