MQTT Security Fundamentals: TLS / SSL
Welcome to the fifth part of the MQTT Security Fundamentals series. After looking at authentication and authorization on the application layer in the last weeks posts, this week’s topic is Transport Encryption with TLS.
We will take a look why TLS / SSL is expedient for a secure MQTT solution and we will talk about best practices when using transport encryption with MQTT.
What is TLS?
TLS (Transport Layer Security) and SSL (Secure Sockets Layer) provide a secure communication channel between a client and a server. At its 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 completed, 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, which clients use to verify the identity of the server.
Details how TLS and the TLS Handshake work in detail would go far beyond the scope of this blog post. A good starting point for learning the nitty-gritties of TLS is this chapter of ‘High Performance Browser Networking’.
Why is TLS important?
Imagine 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. However, nothing prevents the postman to read the contents of the card, in fact everyone, who is involved delivering the postcard, can read the contents. If you have a malicious postman, he can even alter some contents of the card!
The idea of this illustration is also true for computer networks in general and the Internet in particular. If you are using plain TCP/IP, it’s like sending a postcard. The TCP packet is going to pass a lot of infrastructure components (routers, firewalls, Internet Exchange Points, etc.) before reaching the target. Every participant in between could now read the contents of your packet in clear text or even modify it. This is not a fictional scenario, recent history showed that Internet traffic is wiretapped all the time by intelligence agencies. While most attackers don’t have that much resources to eavesdrop your connection, it’s not too hard for sophisticated attackers to perform Man-In-The-Middle-Attacks.
So TLS is all about providing a secure communication channel. With TLS it’s safe to say that the communication contents can not be read or altered by third parties*.
*Assuming secure cipher suites were used and there are no yet unknown attacks on the TLS version used.
MQTT and TLS
MQTT relies on TCP as transport protocol, which means by default the connection does not use an encrypted communication. To encrypt the whole MQTT communication, most many MQTT brokers – like HiveMQ – allow to use TLS instead of plain TCP. If you are using 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” and port 8883 is exclusively reserved for MQTT over TLS.
However, as always, there is a drawback when 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 compute intensive tasks. Techniques like 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 it depends on many factors how much bandwidth the TLS handshake needs, some measurements showed, that establishing a new TLS connection can take up to a few kilobytes of bandwith. Since every packet is encrypted when using TLS, packets on the wire also have additional overhead compared to the unencrypted packets.
So if you are using long-living TCP connections with MQTT (which you should!), the TLS overhead, especially the TLS Handshake overhead may be negligible. If you are dealing with many reconnects and you can’t use session resumption, then the overhead may 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, so be sure to measure how much overhead TLS is for your use case.
We already heard about TLS Session Resumption in the previous paragraphs. In a nutshell, TLS session resumption techniques allow to reuse an already negotiated TLS session after reconnecting to the server, so the client and server don’t need to do the full TLS handshake again. It’s important to note, that not all TLS libraries implement all session resumption techniques, some don’t even implement any session resumption mechanism.
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 servers secret state 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 compute intensive and can take tens of kilobytes of memory. If TLS is not possible with your devices, you should think about using payload encryption for your PUBLISH messages and you should at least hash or encrypt the password in the CONNECT message of your client. More on that topic in one of the next blog posts.
It may also be an option to look into TLS-PSK cipher suites, since they 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 this.
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 make sure that no eavesdropper can intercept your communication and you get that additional layer of security that is important for application-level authentication and authorization.
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. In fact, there are well-known attacks against TLS 1.0 and 1.1, which can be mitigated and some are designed for HTTP exploits (like the CRIME attack). At the time of writing there is no practically applicable attack 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 nowadays. 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, it’s very important that 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 and validating certificates is always worth the effort.
Use certificates from trusted CAs
Using official certificates from trusted CAs are worth the extra money they cost, since self signed certificates don’t play too well with many TLS implementations and they often lead to sloppy code which e.g. doesn’t validate the certificate, causing possibilities for Man-In-The-Middle attacks. If your MQTT broker is public-facing, having a trusted certificate is a must. If you are using MQTT over websockets, self-signed certificates are not optimal, since most modern web browsers don’t allow websocket connections to resources with untrusted certificates.
Use other security mechanisms
It’s always a good idea to use additional security mechanisms like payload encryption, payload signature verifications and authorization mechanisms in addition to TLS. More security considerations usually don’t hurt.
Only use secure cipher suites
There are many insecure cipher suites available when using TLS. Make sure to only allow secure cipher suites for your communication, otherwise you might get a false sense of security since there are many cipher suites known to be broken.
We hope you enjoyed part five of the MQTT Security Fundamentals. Next week we are going to discuss X509 client certificate authentication in conjunction with TLS. If you want to get notified as soon as we publish the next post, you can subscribe to our newsletter or RSS feed. You think we have missed some important information? Please tell us, we are always open to questions and suggestions.