Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TLS Client on node.js hangs forever if certificate is invalid or revoked #1776

Closed
mvuckovic opened this issue Jan 11, 2024 · 4 comments
Closed

Comments

@mvuckovic
Copy link

Hi,

I'm running into a problem that seems to be similar to this issue.

My setup is following:

  • Node.js 20.10.0
  • MQTT.js 5.3.3
  • AWS IoT Core
  • TLS cert/key

While certificate is valid and client is allowed to connect, everything is working as expected. For example bringing the network interface down and back up again will trigger a successful reconnect.

But if certificate is invalid OR revoked from AWS IoT Core side connectAsync will just "hang" forever. It will never throw nor trigger any of the callbacks from the sample code below:

    async connect() {
        try {
            mqttLogger.info('Trying to connect');
            
            const client = await mqtt.connectAsync({
                protocol: 'mqtts',
                protocolVersion: 5,
                reconnectPeriod: 30000,
                clientId: 'some-client-id',
                port: 8883,
                host: "example-prefix-ats.iot.eu-central-1.amazonaws.com",
                ca: "read-from-file",
                cert: "read-from-file",
                key: "read-from-file",
            });

            client.on('error', (err) => {
                console.error(err);
            });

            client.on('connect', () => {
                mqttLogger.info('Connected successfully');
            });

            client.on('reconnect', () => {
                mqttLogger.info('Reconnecting ...');
            });

            client.on('offline', () => {
                mqttLogger.info('Went offline');
            });

            client.on('close', () => {
                mqttLogger.info('Disconnected');
            });
        } catch (err) {
            mqttLogger.error(err);

            throw new Error('MQTT_CONNECT_FAILED');
        }
    }

When I run it with DEBUG='mqttjs*' following output is shown (and retries forever):

  mqttjs connecting to an MQTT broker... +0ms
  mqttjs:client MqttClient :: options.protocol mqtts +0ms
  mqttjs:client MqttClient :: options.protocolVersion 5 +0ms
  mqttjs:client MqttClient :: options.username undefined +0ms
  mqttjs:client MqttClient :: options.keepalive 60 +0ms
  mqttjs:client MqttClient :: options.reconnectPeriod 30000 +0ms
  mqttjs:client MqttClient :: options.rejectUnauthorized undefined +0ms
  mqttjs:client MqttClient :: options.properties.topicAliasMaximum undefined +0ms
  mqttjs:client MqttClient :: clientId some-client-id +0ms
  mqttjs:client MqttClient :: setting up stream +1ms
  mqttjs:client connect :: calling method to clear reconnect +1ms
  mqttjs:client _clearReconnect : clearing reconnect timer +0ms
  mqttjs:client connect :: using streamBuilder provided to client to create stream +0ms
  mqttjs calling streambuilder for mqtts +3ms
  mqttjs:tls port 8883 host example-prefix-ats.iot.eu-central-1.amazonaws.com rejectUnauthorized %b true +0ms
  mqttjs:client connect :: pipe stream to writable stream +58ms
  mqttjs:client connect: sending packet `connect` +0ms
  mqttjs:client _writePacket :: packet: {
  mqttjs:client   cmd: 'connect',
  mqttjs:client   protocolId: 'MQTT',
  mqttjs:client   protocolVersion: 5,
  mqttjs:client   clean: true,
  mqttjs:client   clientId: 'some-client-id,
  mqttjs:client   keepalive: 60,
  mqttjs:client   username: undefined,
  mqttjs:client   password: undefined,
  mqttjs:client   properties: undefined
  mqttjs:client } +0ms
  mqttjs:client _writePacket :: emitting `packetsend` +1ms
  mqttjs:client _writePacket :: writing to stream +0ms
  mqttjs:client _writePacket :: writeToStream result true +16ms
  mqttjs:client (some-client-id)stream :: on close +227ms
  mqttjs:client _flushVolatile :: deleting volatile messages from the queue and setting their callbacks as error function +0ms
  mqttjs:client stream: emit close to MqttClient +0ms
  mqttjs:client close :: connected set to `false` +0ms
  mqttjs:client close :: clearing connackTimer +0ms
  mqttjs:client close :: clearing ping timer +0ms
  mqttjs:client close :: calling _setupReconnect +0ms
  mqttjs:client _setupReconnect :: emit `offline` state +1ms
  mqttjs:client _setupReconnect :: set `reconnecting` to `true` +0ms
  mqttjs:client _setupReconnect :: setting reconnectTimer for 30000 ms +0ms
  mqttjs:client reconnectTimer :: reconnect triggered! +30s
  mqttjs:client _reconnect: emitting reconnect to client +0ms
  mqttjs:client _reconnect: calling connect +0ms
  mqttjs:client connect :: calling method to clear reconnect +0ms
  mqttjs:client _clearReconnect : clearing reconnect timer +0ms
  mqttjs:client connect :: using streamBuilder provided to client to create stream +0ms
  mqttjs calling streambuilder for mqtts +30s
  mqttjs:tls port 8883 host example-prefix-ats.iot.eu-central-1.amazonaws.com rejectUnauthorized %b true +30s

I tried the same scenario with connect instead of connectAsync and following callbacks will trigger: offline, close, reconnect but no error is thrown or any type of indication what went wrong.

@robertsLando
Copy link
Member

If you use the normal connect instead of the connectAsync and add a listener to error event, do you get that event?

@mvuckovic
Copy link
Author

Hi Daniel,

I tried that as well (wrote it below the log output)

I tried the same scenario with connect instead of connectAsync and following callbacks will trigger: offline, close, reconnect but no error is thrown or any type of indication what went wrong.

@robertsLando
Copy link
Member

robertsLando commented Jan 11, 2024

Sorry, missed that part. By checking your logs it seems it get stucked after this line:

debug(
'port %d host %s rejectUnauthorized %b',
opts.port,
opts.host,
opts.rejectUnauthorized,
)

I suggest you to try debugging code to see if you find the reason why that hangs, there are error listeners stetup there and I don't know why them are not triggered

@robertsLando
Copy link
Member

May be fixed by #1779 , try 5.3.5 and feel free to re-open in case

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants