sslopensslmqtt

MQTT client cannot publish to brocker using MQTTS : certificats are valid in port 443 but not in port 8883


I want to publish data on a privately MQTT server (brand new, but i have not so much information about it) and I need to use TLS (port 8883).

  1. Removing the certificat validation on client side allow me to publish & subscribe (rejectUnauthorized:false below)
  2. the client (MQTTJS) with the following options
sync function testMqtt() {
  var options = {
    port: 8883,
    protocol: 'mqtts',
    username: 'username',
    password: 'password',
    rejectUnauthorized: true
  };

return an error :

node:internal/process/promises:289
            triggerUncaughtException(err, true /* fromPromise */);
            ^

Error: unable to verify the first certificate
    at TLSSocket.onConnectSecure (node:_tls_wrap:1674:34)
    at TLSSocket.emit (node:events:519:28)
    at TLSSocket._finishInit (node:_tls_wrap:1085:8)
    at ssl.onhandshakedone (node:_tls_wrap:871:12) {
  code: 'UNABLE_TO_VERIFY_LEAF_SIGNATURE'
}
  1. I checked the certificats in use using the following commands :

openssl s_client -connect server:443 | openssl.exe x509 > server443.cert return OK (certificat is valid) openssl s_client -connect server:8883 | openssl.exe x509 > server8883.cert return KO (verify error:num=20:unable to get local issuer certificate) but when i compare server8883.cert and server443.cert files are stricly identique.

the error return by the second line on port 8883 seems similar to this question, but certificat is valid if requested with port 443.

now the questions : is the problem is on server side or on the client side, and what's the best way to solve it ?

I could put a copy of the certificat server in the client (like in this question, but that means every time the server update the certificat i need to update it in the client. On the other hand, installing server certificate is not required when a browser is using https, right ? Thanks in advance !


Solution

  • As hashed out in the comments.

    The broker is not returning the intermediate certificate as part of the TLS handshake.

    The usual solution for this is to concatenate the server certificate with the intermediate certificate (order is important, the server cert must come before the intermediate cert).

    I assume that the concatenation has already been done for the HTTP server, so you may be able to reuse that file (or symlink them so you only need to update one location)

    If using certs from LetsEncrypt you can switch to using the fullchain.pem rather than the cert.pem files.