1

I'm trying to create a TLS connection to AdafruitIO using paho C++. I can connect and interact with it using 1883 non TLS, but when trying to get TLS going on 8883, it fails to connect. I was able to do this in C++ using the mosquitto C++ library, but that's been deprecated, so I'm trying to move my code over. I suspect I'm just not telling the Paho library enough about the lack of certs, but I can't find API's other than below which might do that. Or, can I use a cert or store on a standard RPi image to connect with? The mosquitto library didn't require me to use certs, it just worked dumb. Below is the code which works for 1883, but not 8883. It's a small test app using a callback class to try to mimic better the final design. I get that I'm not really using it correctly here, but mostly, I'm just trying to fix connections so I can publish, then I can go back and clean up the design.

Can I use system cert files somehow? I confess I'm not that familiar with how TLS/SSL works, so I'm not sure how I could use the system to help me solve this problem, if that's possible. Honestly, based on the PAHO debug log, it connects, but fails somewhere on the server side it looks like, though I don't see where or why. Maybe just a rejection without a reason?

Any thoughts on the best way to do this? I plan to run this on an RPi project I'm building, but am testing on Ubuntu 19.04 desktop for now. I use cmake, and C++17 as well. Doubt that makes a difference, but I'll add it.

main.cpp

#define AIO_USERNAME    "yyy"
#define AIO_KEY         "xxx"
#define AIO_PORT        "8883"
#define TEST_FEED       "default/feeds/test"

void connected()
{
    std::cout << __FUNCTION__ << ": successful connection established" << std::endl;
}

void connectionLost(const std::string &cause)
{
    std::cout << __FUNCTION__ << ": Lost connection: " << cause << std::endl;
}

int main(int argc, char **argv) {
    mqtt::async_client client("tcp://io.adafruit.com:8883", "tls_test_client");
    mqtt::connect_options connopts(AIO_USERNAME, AIO_KEY);
    mqtt::ssl_options sslopts;
    LocalMQTTCallback callback(client, connopts);
    nlohmann::json json;

    json["value"] = 199;

    callback.setConnectedCallback(connected);
    callback.setConnectionLostCallback(connectionLost);
    sslopts.set_verify(false);
    sslopts.set_enable_server_cert_auth(false);
    client.set_callback(callback);
    connopts.set_ssl(sslopts);
    mqtt::token_ptr conntok;

    std::cout << __FUNCTION__ << "Connecting..." << std::endl;
    try {
        conntok = client.connect(connopts);
        conntok->wait();
        std::cout << __FUNCTION__ << ": connected..." << std::endl;
    }
    catch (const mqtt::exception& exc) {
        std::cerr << __FUNCTION__ << ": " << exc.what() << std::endl;
        return 1;
    }

    auto msg = mqtt::make_message(TEST_FEED, json.dump().c_str(), 0);
    client.publish(msg)->wait_for(std::chrono::seconds(10));
    std::cout << __FUNCTION__ << ": published message to AIO" << std::endl;

    while (1)
        std::this_thread::sleep_for(std::chrono::seconds(1));

    return 0;
}

localmqttcallback.h

#ifndef MQTTCLIENT_H
#define MQTTCLIENT_H

#include <iostream>
#include <fstream>
#include <cstdlib>
#include <string>
#include <chrono>
#include <cstring>
#include <functional>
#include <mqtt/async_client.h>

class LocalMQTTCallback : public virtual mqtt::callback, public virtual mqtt::iaction_listener
{
public:
    LocalMQTTCallback(mqtt::async_client& cli, mqtt::connect_options& connOpts);

    void setMessageCallback(std::function<void(std::string, std::string)> cbk) { m_messageCallback = cbk; }
    void setConnectionLostCallback(std::function<void(const std::string&)> cbk) { m_connectionLostCallback = cbk; }
    void setConnectedCallback(std::function<void()> cbk) { m_connectedCallback = cbk; }

private:
    void connection_lost(const std::string& cause) override;
    void message_arrived(mqtt::const_message_ptr msg) override;
    void delivery_complete(mqtt::delivery_token_ptr tok) override;
    void connected(const std::string &cause) override;

    void on_failure(const mqtt::token& tok) override {
        std::cout << "Connection attempt failed: " << tok.get_reason_code() << std::endl;
    }

    // (Re)connection success
    // Either this or connected() can be used for callbacks.
    void on_success(const mqtt::token& tok) override {
        std::cout << "Connection attempt suceeded: " << tok.get_reason_code() << std::endl;
    }

    std::function<void(std::string, std::string)> m_messageCallback;
    std::function<void(const std::string&)> m_connectionLostCallback;
    std::function<void()> m_connectedCallback;

    // Counter for the number of connection retries
    int m_retries;
    // The MQTT client
    mqtt::async_client& m_client;
    // Options to use if we need to reconnect
    mqtt::connect_options& m_clientConnOpts;
};

localmqttcallback.cpp

#include "localmqttcallback.h"

LocalMQTTCallback::LocalMQTTCallback(mqtt::async_client& cli, mqtt::connect_options& connOpts) : 
    m_retries(0), m_client(cli), m_clientConnOpts(connOpts)
{
}

void LocalMQTTCallback::connection_lost(const std::string &cause)
{
    try {
        m_connectionLostCallback(cause);
    }
    catch (std::exception &e) {
        std::cout << __FUNCTION__ << ": Error trying to call the lost connection callback: " << e.what();
    }
}

void LocalMQTTCallback::connected(const std::string &cause)
{
    try {
        m_connectedCallback();
    }
    catch (std::exception &e) {
        std::cout << __FUNCTION__ << ": Error trying to call the connected callback: " << e.what();
    }
}

void LocalMQTTCallback::delivery_complete(mqtt::delivery_token_ptr tok)
{
}

void LocalMQTTCallback::message_arrived(mqtt::const_message_ptr msg)
{
    std::cout << __FUNCTION__ << ": Incoming message for topic " << msg->get_topic() << std::endl;
    try {
        m_messageCallback(msg->get_topic(), msg->get_payload_str());
    }
    catch (std::exception &e) {
        std::cout << __FUNCTION__ << ": Error trying to call the lost connection callback: " << e.what();
    }
}

Success sees the following

mainConnecting...
connected: successful connection established
main: connected...
main: published message to AIO

Failure sees this

mainConnecting...
main: MQTT error [-1]: TCP connect completion failure

And a snippet of the MQTT console debug output

=========================================================
                   Trace Output
Product name: Eclipse Paho Asynchronous MQTT C Client Library
Version: 1.3.1
Build level: 2020-03-21T13:29:16Z
OpenSSL version: OpenSSL 1.1.1c  28 May 2019
OpenSSL flags: compiler: gcc -fPIC -pthread -m64 -Wa,--noexecstack -Wall -Wa,--noexecstack -g -O2 -fdebug-prefix-map=/build/openssl-D7S1fy/openssl-1.1.1c=. -fstack-protector-strong -Wformat -Werror=format-security -DOPENSSL_USE_NODELETE -DL_ENDIAN -DOPENSSL_PIC -DOPENSSL_CPUID_OBJ -DOPENSSL_IA32_SSE2 -DOPENSSL_BN_ASM_MONT -DOPENSSL_BN_ASM_MONT5 -DOPENSSL_BN_ASM_GF2m -DSHA1_ASM -DSHA256_ASM -DSHA512_ASM -DKECCAK1600_ASM -DRC4_ASM -DMD5_ASM -DAES_ASM -DVPAES_ASM -DBSAES_ASM -DGHASH_ASM -DECP_NISTZ256_ASM -DX
OpenSSL build timestamp: built on: Tue Aug 20 11:46:33 2019 UTC
OpenSSL platform: platform: debian-amd64
OpenSSL directory: OPENSSLDIR: "/usr/lib/ssl"
/proc/version: Linux version 5.3.0-7629-generic (buildd@lgw01-amd64-033) (gcc version 9.2.1 20191008 (Ubuntu 9.2.1-9ubuntu2)) #31~1581628825~19.10~f90b7d5-Ubuntu SMP Fri Feb 14 19:56:45 UTC 

=========================================================
19691231 180000.000 (2241132352)  (1)> Socket_outInitialize:131
19691231 180000.000 (2241132352)   (2)> SocketBuffer_initialize:94
19691231 180000.000 (2241132352)   (2)< SocketBuffer_initialize:98
19691231 180000.000 (2241132352)  (1)< Socket_outInitialize:144
19691231 180000.000 (2241132352)  (1)> SSLSocket_initialize:446
19691231 180000.000 (2241132352)   (2)> SSL_create_mutex:346
19691231 180000.000 (2241132352)   (2)< SSL_create_mutex:352 (0)
19691231 180000.000 (2241132352)   (2)> SSL_create_mutex:346
19691231 180000.000 (2241132352)   (2)< SSL_create_mutex:352 (0)
19691231 180000.000 (2241132352)  (1)< SSLSocket_initialize:492 (1)
19691231 180000.000 (2241132352)  (1)> MQTTStrncpy:851
19691231 180000.000 (2241132352)  (1)< MQTTStrncpy:861
19691231 180000.000 (2241132352)  (1)> MQTTStrncpy:851
19691231 180000.000 (2241132352)  (1)< MQTTStrncpy:861
19691231 180000.000 (2241132352)  (1)> MQTTPersistence_create:52
19691231 180000.000 (2241132352)  (1)< MQTTPersistence_create:98 (0)
19691231 180000.000 (2241132352)  (1)> MQTTPersistence_initialize:113
19691231 180000.000 (2241132352)  (1)< MQTTPersistence_initialize:121 (0)
19691231 180000.000 (2241132352)  (1)> MQTTAsync_restoreCommands:1002
20200321 094455.202 0 commands restored for client pbuelow-tls_test_client
20200321 094455.202 (2241132352)  (1)< MQTTAsync_restoreCommands:1040 (0)
20200321 094455.202 (2241132352)  (1)> MQTTPersistence_restoreMessageQueue:719
20200321 094455.202 0 queued messages restored for client pbuelow-tls_test_client
20200321 094455.202 (2241132352)  (1)< MQTTPersistence_restoreMessageQueue:758 (0)
20200321 094455.202 (2241132352) (0)< MQTTAsync_createWithOptions:654 (0)
20200321 094455.202 (2241132352) (0)> MQTTAsync_setConnected:2614
20200321 094455.202 (2241132352) (0)< MQTTAsync_setConnected:2626 (0)
20200321 094455.202 (2241132352) (0)> MQTTAsync_setCallbacks:2500
20200321 094455.202 (2241132352) (0)< MQTTAsync_setCallbacks:2514 (0)
mainConnecting...
20200321 094455.202 (2241132352) (0)> MQTTAsync_connect:2812
20200321 094455.202 (2241132352)  (1)> UTF8_validateString:157
20200321 094455.202 (2241132352)   (2)> UTF8_validate:131
20200321 094455.202 (2241132352)   (2)< UTF8_validate:143 (1)
20200321 094455.202 (2241132352)  (1)< UTF8_validateString:159 (1)
20200321 094455.202 (2241132352)  (1)> Thread_start:69
20200321 094455.202 (2241132352)  (1)< Thread_start:79
20200321 094455.202 (2241132352)  (1)> Thread_start:69
20200321 094455.202 (2241132352)  (1)< Thread_start:79
20200321 094455.202 (2232735488) (0)> MQTTAsync_receiveThread:2138
20200321 094455.203 (2232735488)  (1)> MQTTAsync_cycle:3742
20200321 094455.203 (2232735488)   (2)> Socket_getReadySocket:237
20200321 094455.203 (2232735488)   (2)< Socket_getReadySocket:309 (0)
20200321 094455.203 (2232735488)   (2)> MQTTAsync_sleep:440
20200321 094455.203 (2241128192) (0)> MQTTAsync_sendThread:1858
20200321 094455.203 (2241128192)  (1)> Thread_wait_cond:413
20200321 094455.203 (2241132352)  (1)> MQTTStrncpy:851
20200321 094455.203 (2241132352)  (1)< MQTTStrncpy:861
20200321 094455.203 (2241132352)  (1)> MQTTAsync_addCommand:1050
20200321 094455.203 (2241132352)   (2)> Thread_signal_cond:395
20200321 094455.203 (2241132352)   (2)< Thread_signal_cond:400 (0)
20200321 094455.203 (2241132352)  (1)< MQTTAsync_addCommand:1084 (0)
20200321 094455.203 (2241132352) (0)< MQTTAsync_connect:3119 (0)
20200321 094455.203 (2241132352) (0)> MQTTProperties_free:366
20200321 094455.203 (2241132352) (0)< MQTTProperties_free:389
20200321 094455.203 (2241132352) (0)> MQTTProperties_free:366
20200321 094455.203 (2241132352) (0)< MQTTProperties_free:389
20200321 094455.203 (2241128192)  (1)< Thread_wait_cond:421 (0)
20200321 094455.203 (2241128192)  (1)> MQTTAsync_checkTimeouts:1804
20200321 094455.203 (2241128192)  (1)< MQTTAsync_checkTimeouts:1852
20200321 094455.203 (2241128192)  (1)> MQTTAsync_processCommand:1398
20200321 094455.203 Connecting to serverURI io.adafruit.com:8883 with MQTT version 4
20200321 094455.203 (2241128192)   (2)> MQTTProtocol_connect:114
20200321 094455.203 (2241128192)    (3)> MQTTProtocol_addressPort:58
20200321 094455.203 (2241128192)    (3)< MQTTProtocol_addressPort:90
20200321 094455.203 (2241128192)    (3)> Socket_new:668
20200321 094455.203 New socket 3 for io.adafruit.com:8883, port 8883
20200321 094455.203 (2241128192)     (4)> Socket_addSocket:173
20200321 094455.203 (2241128192)      (5)> Socket_setnonblocking:85
20200321 094455.203 (2241128192)      (5)< Socket_setnonblocking:90 (0)
20200321 094455.203 (2241128192)     (4)< Socket_addSocket:196 (0)
20200321 094455.203 Connect pending
20200321 094455.203 (2241128192)    (3)< Socket_new:785 (115)
20200321 094455.203 (2241128192)   (2)< MQTTProtocol_connect:156 (115)
20200321 094455.203 (2241128192)   (2)> MQTTProperties_free:366
20200321 094455.203 (2241128192)   (2)< MQTTProperties_free:389
20200321 094455.203 (2241128192)  (1)< MQTTAsync_processCommand:1734 (1)
20200321 094455.203 (2241128192)  (1)> Thread_wait_cond:413
20200321 094455.203 (2232735488)   (2)< MQTTAsync_sleep:446
20200321 094455.203 (2232735488)   (2)> MQTTAsync_retry:3575
20200321 094455.303 (2232735488)    (3)> MQTTProtocol_keepalive:608
20200321 094455.303 (2232735488)    (3)< MQTTProtocol_keepalive:644
20200321 094455.303 (2232735488)    (3)> MQTTProtocol_retry:730
20200321 094455.303 (2232735488)    (3)< MQTTProtocol_retry:749
20200321 094455.303 (2232735488)   (2)< MQTTAsync_retry:3585
20200321 094455.303 (2232735488)  (1)< MQTTAsync_cycle:3893 (-1)
20200321 094455.303 (2232735488)  (1)> MQTTAsync_cycle:3742
20200321 094455.303 (2232735488)   (2)> Socket_getReadySocket:237
20200321 094455.303 (2232735488)    (3)> Socket_continueWrites:928
20200321 094455.303 (2232735488)    (3)< Socket_continueWrites:952 (0)
20200321 094455.303 (2232735488)    (3)> isReady:213
20200321 094455.303 (2232735488)    (3)< isReady:218 (1)
20200321 094455.303 (2232735488)   (2)< Socket_getReadySocket:309 (3)
20200321 094455.303 m->c->connect_state = 1
20200321 094455.303 (2232735488)   (2)> MQTTAsync_connecting:3593
20200321 094455.303 (2232735488)    (3)> MQTTPacket_send_connect:55
20200321 094455.303 (2232735488)     (4)> MQTTPacket_send:187
20200321 094455.303 (2232735488)      (5)> MQTTPacket_encode:281
20200321 094455.303 (2232735488)      (5)< MQTTPacket_encode:291 (1)
20200321 094455.303 (2232735488)      (5)> WebSocket_putdatas:782
20200321 094455.304 (2232735488)       (6)> Socket_putdatas:502
20200321 094455.304 (2232735488)        (7)> Socket_writev:426
20200321 094455.304 (2232735488)        (7)< Socket_writev:478 (80)
20200321 094455.304 (2232735488)       (6)< Socket_putdatas:550 (0)
20200321 094455.304 (2232735488)      (5)< WebSocket_putdatas:814 (0)
20200321 094455.304 (2232735488)     (4)< MQTTPacket_send:216 (0)
20200321 094455.304 3 pbuelow-tls_test_client -> CONNECT version 4 clean: 1 (0)
20200321 094455.304 (2232735488)    (3)< MQTTPacket_send_connect:126 (0)
20200321 094455.304 (2232735488)   (2)< MQTTAsync_connecting:3732 (0)
20200321 094455.304 (2232735488)   (2)> MQTTAsync_retry:3575
20200321 094455.304 (2232735488)    (3)> MQTTProtocol_retry:730
20200321 094455.304 (2232735488)    (3)< MQTTProtocol_retry:749
20200321 094455.304 (2232735488)   (2)< MQTTAsync_retry:3585
20200321 094455.304 (2232735488)  (1)< MQTTAsync_cycle:3893 (0)
20200321 094455.304 (2232735488)  (1)> MQTTAsync_cycle:3742
20200321 094455.304 (2232735488)   (2)> Socket_getReadySocket:237
20200321 094455.304 (2232735488)    (3)> Socket_continueWrites:928
20200321 094455.304 (2232735488)    (3)< Socket_continueWrites:952 (0)
20200321 094455.304 (2232735488)    (3)> isReady:213
20200321 094455.304 (2232735488)    (3)< isReady:218 (1)
20200321 094455.340 (2232735488)   (2)< Socket_getReadySocket:309 (3)
20200321 094455.340 m->c->connect_state = 4
20200321 094455.340 (2232735488)   (2)> MQTTPacket_Factory:111
20200321 094455.340 (2232735488)    (3)> WebSocket_getch:476
20200321 094455.340 (2232735488)     (4)> Socket_getch:324
20200321 094455.340 (2232735488)      (5)> SocketBuffer_getQueuedChar:203
20200321 094455.340 (2232735488)      (5)< SocketBuffer_getQueuedChar:222 (-22)
20200321 094455.340 (2232735488)     (4)< Socket_getch:345 (-1)
20200321 094455.340 (2232735488)    (3)< WebSocket_getch:513 (-1)
20200321 094455.340 (2232735488)   (2)< MQTTPacket_Factory:164 (-1)
20200321 094455.340 CONNECT sent but MQTTPacket_Factory has returned SOCKET_ERROR
4

1 回答 1

1

我遇到了类似的问题。问题似乎是客户端没有尝试尝试 TLS 握手。就我而言,在 URL 前加上 ssl:// 似乎会强制客户端这样做。

在您的 main.cpp 中,尝试从 更改mqtt::async_client client("tcp://io.adafruit.com:8883", "tls_test_client");mqtt::async_client client("ssl://io.adafruit.com:8883", "tls_test_client");.

于 2020-11-16T18:06:04.943 回答