While disabling host-name verification can, indeed, be a security foot-gun, it's annoying that the only way to make mosquito_[ps]ub speak to my broker with a broker-specific certificate given as --cafile is a flag named --insecure with klaxons and gongs and marching ants around its documentation. Looking at the code, mosquitto__server_certificate_verify is careful to honor preverify_ok flag from OpenSSL, which ensures that the signatures involved in the handshake and the certificate chain are all correct, so this use (--insecure --cafile $SERVER_CERT) is secure.
I'd like to suggest renaming the option to --no-verify-hostname or something similarly descriptive, tempering the documentation's alarm, deprecating --insecure for one release, and then removing --insecure in the next.
Thanks!
My feeling on this is that I've seen an awful lot of people disregard the importance of host name verification. For those people, using --insecure gives them a pretty big hint that they should consider things a bit more carefully. For the people who know what they are doing, the annoyance of typing --insecure is pretty minor.
Would you consider an option to specify an alternate host name? This could be used as the SNI hostname, and the client could validate against it. I believe this would be a more secure form of --insecure, and it might be valuable in a case where some client has to connect through an alternate host name or perhaps using an IP address.
@ralight Would you consider at least amending the documentation to say something like "While hostnames will not be checked, the TLS handshake and certificate path to any provided --cafile will be." ?
@ptjm I'd be OK with that, so long as attempting to speak SNI to a server that doesn't understand it doesn't abort (because otherwise I have to tell my broker about its multiple faces rather than just having many network paths that end up at the same port). Specifying the certificate X.509 DN and SNI strings separately might be nice, but that's perhaps overly much to ask for.
I'm fairly certain mosquitto client always sets the SNI extension. Normally, it's set to the host name that you're connecting to.
I have to agree with Roger's comment, though -- accepting just any host name is never a secure practice. I mean, if you fully control the CA, it would be hard for an attacker to get a valid certificate, but if you don't control the CA, then you're not secure against man-in-the-middle attacks unless you're validating the server certificate in some specific way.
Rad, that (SNI) suggests that the right thing happens.
As to the latter point... I'm afraid I must emphatically disagree. Accepting any host name but using a specific certificate (or, more generally, public key), regardless of one's control of the CA, is perfectly secure. The public key / certificate still uniquely identifies the remote endpoint. The erroneously-named --cafile option does not need to take a CA certificate as the root of the trust chain; any certificate will do just fine. (It's not mosquitto's fault that this option is named the way it is; TLS's use of X.509 strongly encourages the convention adopted; I just think it's an unfortunate convention.) This does, potentially, complicate certificate rotation (and the fact that TLS implementations have not historically offered a "public key validation" hook in parallel with their certificate validation hooks is a travesty), but that's readily handled out of band.
Identification by proof of control of a specific public key is exactly how, for example, client SSH keys function, and for all the failings of the SSH protocol, that isn't one of them.
Most helpful comment
My feeling on this is that I've seen an awful lot of people disregard the importance of host name verification. For those people, using
--insecuregives them a pretty big hint that they should consider things a bit more carefully. For the people who know what they are doing, the annoyance of typing--insecureis pretty minor.