BUG: Enabling SSL/TLS requires definition of certfile and keyfile
mosquitto version 1.6.12 OS Ubuntu 18.04 (actually Linux Mint)
The mosquitto.conf documentation specifies that cafile or capath are required to enable TLS. It does not say that a certfile or keyfile are required, but in order to enable TLS it seems they are required.
Steps to reproduce:
- Create a config file in /etc/mosquitto/test.conf with the following content:
listener 8883
capath /etc/ssl/certs
- Send a message with mosquitto_sub without enabling encryption:
mosquitto_pub -h "<broker hostname> " -t "test" -m "test" -p 8883
This should fail as mosquitto_pub is not using TLS, but it succeeds.
- Send a message with an mqtt client with TLS enabled, but server validation off. This fails.
I used mqtt-explorer to do this step as the mosquitto_pub client is exhibiting a separate bug with it's
--insecureflag not working in conjunction with the--capathflag. That is, this command fails in all cases, but that's a separate problem:
mosquitto_pub -h "<broker hostname> " -t "test" -m "test" -p 8883 --capath "/etc/ssl/certs" --insecure
- Add "certfile" and "keyfile" to the config file and observe the inverse behavior of steps 2 and 3.
Perhaps this is not actually a bug and mosquitto does not support unauthenticated TLS, but in that case, it seems like the fall-back to no encryption shouldn't be happening and/or the documentation should be clarified to specify that TLS is only supported in "server auth" or "mutual auth" configurations and explicitly state that "certfile" and "keyfile" are also required to enable TLS.
You're quite right, and happily I had already pushed a change to how this works and is documented just over a week before your report: https://github.com/eclipse/mosquitto/commit/54b95715165f5d15f5911f9a9653ba70d52fee93
The intention of this originally was to say that cafile/capath are the options that are required to have that listener go into TLS mode. The missing requirement for certfile and keyfile was because of the incorrect assumption that "everybody" would know you need a certificate and key for the server.
I am not sure if that would be a new feature for consideration, but I my findings are the following:
- If according to current state of art not all three options (
certfile,keyfile,cafile), mosquitto does not enable TLS on port 8883. One would expect that mosquitto at least complains in the log file that for example "certfile was specified but keyfile is missing: SSL is disabled", or even fail because necessary file is not specified. - If the option
require_certificateis not provided I see no reason whycafileis a must. It should be obligatory only ifrequire_certificateistrue. This should be clearly reported to log file. - Very often (at least many application servers I know) support combined cert+key file in one file which has the following structure:
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
-----BEGIN RSA PRIVATE KEY-----
...
-----END RSA PRIVATE KEY-----
which makes the option keyfile also optional.
- Client that tries to initialize SSL connection for non-SSL-enabled port, is reported as
Client <unknown> disconnected due to protocol errorto the log file. This is confusing as it looks like that the client succeeded TLS negotiation but misbehaves with respect to MQTT protocol. Would be nice if mosquitto could detect the attempt to enable SSL for the port with is not configured for that and report to log something like "The client tries to start SSL on the port which is not SSL enabled".
Altogether:
- mosquitto should check that provided
certfilefile is a combined file. If not, thenkeyfileshould be required. - mosquitto should check that
cafileis accesible/readable only ifrequire_certificateistrue. - mosquitto should fail when SSL is intended to be enabled, but on some reason it is not.
Thanks-- this is extremely helpful!
I do think we should implement @dmak suggestion about not allowing cafile without certfile, and ensuring that the broker doesn't start with invalid configuration. Or at least have the important aspects of the configuration be in the log at a debug level. Connecting via TLS to a non-TLS listener produces a protocol error message that is impossible to figure out unless you attach a debugger
The broker now produces an error for invalid combinations of cafile/capath/certfile/keyfile.
Connecting via TLS to a non-TLS listener produces a protocol error message that is impossible to figure out unless you attach a debugger
I am not an expert, but TLS follows a specific handshake pattern and starts with a ClientHello message. A packet might look like this:
16 03 03 ...
where
16 → Handshake Protocol (0x16)
03 03 → TLS 1.2 (0x0303)
More details in Illustrated TLS 1.2 Connection.
mosquitto can capture this pattern on non-TLS port.