MQTT-TLS could use Amazon IoT

Using the mini-config settings for free ram needs for the rest of the program. The certs seem to work as suggested by the output.

void callback(char* topic, byte* payload, unsigned int length) {
    char p[length + 1];
    memcpy(p, payload, length);
    p[length] = NULL;
    String message(p);
    Serial.println("callback contains:");
    Serial.println(message);
    delay(1000);
}

#define ONE_DAY_MILLIS (24 * 60 * 60 * 1000)
unsigned long lastSync = millis();
int counter = 0;
void setup() {
    if (millis() - lastSync > ONE_DAY_MILLIS) {
        Particle.syncTime();
        lastSync = millis();
    }

    if(!WiFi.ready()) {Serial.println("Error, wifi not connected");}
   
   
   
   int ret;
    // enable tls. set Root CA pem, private key file.
    if((ret = client.enableTls(amazonIoTRootCaPem, sizeof(amazonIoTRootCaPem),
                     clientKeyCrtPem, sizeof(clientKeyCrtPem),
                     clientKeyPem, sizeof(clientKeyPem)))<0){
                     Serial.printlnf("client.enableTls failed with code: %d", ret);
                     };

    Serial.println("tls enable");
    
    // connect to the server
    if ( (ret >= 0) && ((ret = client.connect(ClientID)) < 0) ) {    // if client enable tls succeeded, attempt connect.  Can block for up to 60 seconds
                Serial.printlnf("client.connect failed with code: %d", ret);
            }


    
    // publish/subscribe
    if (client.isConnected()) {
        Serial.println("client connected");
    }
    if (client.isConnected()) {
        int d_id =  1;
        float s_v = 50.500;
        float tp_v= -25.5; 
        char tm[] = "2019/6/20/14/30/59";
        char payload[255];
        snprintf(payload, sizeof(payload), "{ \"d_id\": %d, \"n_dat\": { \"s_v\": %.2f, \"tp_v\": %.2f, \"tm\": \"%s\"}}", d_id, s_v, tp_v, tm);
        Serial.println(payload);
        client.publish("Node_Data", payload);
        client.subscribe("Node_Data");
    }
}

void loop() {
    if (client.isConnected()) {
        client.loop();
    }
    delay(200);
}

And here is what I get in VS terminal using serial monitor:

Serial monitor opened successfully:
tls enable
hand shake start
Verify requested for (Depth 2):
cert. version     : 3
serial number     : 06:6C:9F:...no idea if this is identifying info.....36:5B:CA
issuer name       : C=US, O=Amazon, CN=Amazon Root CA 1
subject name      : C=US, O=Amazon, CN=Amazon Root CA 1
issued  on        : 2015-05-26 00:00:00
expires on        : 2038-01-17 00:00:00
signed using      : RSA with SHA-256
RSA key size      : 2048 bits
basic constraints : CA=true
key usage         : Digital Signature, Key Cert Sign, CRL Sign
  This certificate has no flags
Verify requested for (Depth 1):
cert. version     : 3
serial number     : 06:7F:94:57:...no idea if this is identifying info....:99:8B:56:0D
issuer name       : C=US, O=Amazon, CN=Amazon Root CA 1
subject name      : C=US, O=Amazon, OU=Server CA 1B, CN=Amazon
issued  on        : 2015-10-22 00:00:00
expires on        : 2025-10-19 00:00:00
signed using      : RSA with SHA-256
RSA key size      : 2048 bits
basic constraints : CA=true, max_pathlen=0
key usage         : Digital Signature, Key Cert Sign, CRL Sign
  This certificate has no flags
Verify requested for (Depth 0):
cert. version     : 3
serial number     : 0A:AC:B3... no idea if this is identifying info..... 3B:FB:C7
issuer name       : C=US, O=Amazon, OU=Server CA 1B, CN=Amazon
subject name      : CN=*.iot.us-east-2.amazonaws.com
issued  on        : 2019-05-07 00:00:00
expires on        : 2020-04-10 12:00:00
signed using      : RSA with SHA-256
RSA key size      : 2048 bits
basic constraints : CA=false
subject alt name  : *.iot.us-east-2.amazonaws.com, iot.us-east-2.amazonaws.com
key usage         : Digital Signature, Key Encipherment
ext key usage     : TLS Web Server Authentication, TLS Web Client Authentication
  This certificate has no flags
handshake done, ret = 0
tls connected
netWrite!!
MQTT connected.
client connected
{ "d_id": 1, "n_dat": { "s_v": 50.50, "tp_v": -25.50, "tm": "2019/6/20/14/30/59"}}
netWrite!!
netWrite!!
netWrite!!
netWrite!!
netWrite!!
netWrite!!
netWrite!!
netWrite!!
netWrite!!
netWrite!!
mqtt disconnected
netWrite!!
tls close
Serial connection closed.

If this is tied to the mini-config file, what should I recommend as a necessary step for the AWS team to get things working?

Thank you in advance,
Sincerely,
Bob

In here you probably want an else branch which deals with the case that the connection was lost by reconnecting :wink:

There may be plenty of reasons for a connection to get lost, but not dealing with that case is definetly not helping to alleviate the problem.

Well that seems like a derp kinda issue to have. :crazy_face:

How often would you expect that I would need to reconnect? Is multiple times per minute on a stable wifi network normal?

You would only try to reconnect once client.isConnected() == false.

You shouldnā€™t expect multiple disconnects per minute, but I also donā€™t know how your targeted server keeps connections alive when there is no actual transmission going on.

Iā€™d also not have a delay(1000) in the callback function.

2 Likes

Ok, nice. Iā€™ll run it for an hour and see what it gives me.

Having issues reconnecting:

netWrite!!
netWrite!!
mqtt disconnected
netWrite!!
tls close
netWrite!!
MQTT connection timeout.
mqtt disconnected
netWrite!!
netWrite!!
MQTT connection timeout.
mqtt disconnected
netWrite!!
netWrite!!
MQTT connection timeout.
mqtt disconnected
netWrite!!

Iā€™m assuming this is because TLS is closedā€¦ do I really have to run the TLS connection every time? I guess I would have hoped to avoid the processing power and battery drain.

void loop() {
    if (client.isConnected()) {
        client.loop();
    }
    else {
        client.connect(ClientID);
    }
    delay(200);
}

Hi, I will check the MQTT-TLS connection to the AWS IoT Server with Argon latest firmware(1.4.4).

1 Like

My Argon (firmware 1.4.4, MQTT-TLS 0.2.21, default config.h and a1-example.ino) can communicate with AWS IoT Core on WebIDE/VScode build.

Please check the firmware/lib version, your AWS IoT TLS RootCA/CRT/private key pem files.
You could check your TLS files setting and connectivity to AWS IoT Core with mosquitto_pub/sub(tls) command.

Thank you.

1 Like

Hi hirotakaster!

Thank you so much for your contribution to this community!

I am also running firmware 1.4.4. I cloned from your repository, which is only on MQTT-TLS 0.2.21, right?

The initial handshake is a success, and since I changed the loop as per ScruffRā€™s advice (thanks again!) to this:

void loop() {
    if (client.isConnected()) {
        client.loop();
    }
    else {
      int ret;
      if((ret = client.enableTls(amazonIoTRootCaPem, sizeof(amazonIoTRootCaPem),
                     clientKeyCrtPem, sizeof(clientKeyCrtPem),
                     clientKeyPem, sizeof(clientKeyPem)))<0){
                     Serial.printlnf("client.enableTls failed with code: %d", ret);
                     };

    Serial.println("tls enable");
    
    // connect to the server
    if ( (ret >= 0) && ((ret = client.connect(ClientID)) < 0) ) {    // if client enable tls succeeded, attempt connect.  Can block for up to 60 seconds
                Serial.printlnf("client.connect failed with code: %d", ret);
            }
    }
    delay(200);
}

I only get disconnects every 5 minutes or so vs. every 20-30 seconds.

Is an mqtt disconnect every 5 minutes or so normal? Is it normal to have to reopen TLS handshake every time? Since the TLS handshake can block for 60 seconds, is there any reason I shouldnā€™t delay for 60 seconds before attempting the reconnect?

Last question: Iā€™m using the mini-config, since we need the extra processing power to get data from multiple sensors. When using the mini-config, is there something that needs to be configured on the AWS side?

okay.

Is an mqtt disconnect every 5 minutes or so normal?

I think it's may be your network(wifi/router or upstream netwrok) problem.
Some router or upstream network will kill the TCP Keep-Alive connection in same interval time.
(My Argon MQTT-TLS with AWS IoT Core don't disconnect over an hour in my wifi network, even if there is nothing MQTT pub/sub)

For this case, use the MQTT_DEFAULT_KEEPALIVE setting,
default : MQTT_DEFAULT_KEEPALIVE 15
This keep alive timeout is ping-back on MQTT protocol, change this value to 10 or 5 maybe improved (or not) your disconnection.
But short keepalive time will become the problem on your network traffic and AWS cost.

Last question: Iā€™m using the mini-config,

I tested mini-config.h with AWS IoT Core(default setting), there is nothing special change on AWS side.

Thank you.

1 Like

Is it normal to have to reopen TLS handshake every time?

Yes. When client.connect fails or the connection drops / times out client.disconnect is called internally. This frees up all the allocated memory for the TLS buffers, and thus needs to be re-instated when the next connection attempt begins.

Since the TLS handshake can block for 60 seconds, is there any reason I shouldnā€™t delay for 60 seconds before attempting the reconnect?

client.connect is a blocking function so it doesn't matter how soon after you call it again (unless it impacts other user code operations). I'd assume you'd normally want to try again as soon as possible to reduce downtime.

Is an mqtt disconnect every 5 minutes or so normal?

No / but it depends. Across my fleet of devices it's not uncommon for a connection to be maintained for days (usually hours, but sometimes minutes). It depends on the reason why you are disconnecting. Some recommended debug steps are:

  • Add logging for the particle network connectivity change events. You should be able to correlate network changes with lost connection if your whole connection is dropping. Else, then it is either an issue with MQTT or your actual TCP connection, as hirotakaster mentioned.
  • Make sure you are using system_thread(ENABLED)
  • Check the server side configuration. If you are using AWS IoT it will not close the connection until 1.5x the configured client timeout. Else, it depends on the configuration of your broker.

Also helpful would be if you tell us how you are planning to use AWS IoT. For example, does the problem still exist if you are explicitly publishing data every 10 sec?

3 Likes

update MQTT-TLS 0.2.22, mbedTLS 2.16.0 to 2.16.3.

I am interested in making a GUI that allows my customer to claim argon devices, flash them with my MQTT-TLS build (unique certs for each argon), and prepare them for deployment.

Does anyone have insight on the best way to do the cert part of this?

Am I correct in assuming that it would not be possible to use the same cert set for all devices connecting to the same AWS server?

Hello Picsil,

Can you help me to figure out which Root CA to use. I can publish to AWS with E-series board, but the exact same code is not working with Boron. I believe it is a problem regarding the certificates. I tried VeriSign Class 3 Public Primary G5 root CA certificate, Amazon Root CA 1, Amazon Root CA 3, Starfield Root CA Certificate, Cross-signed Amazon Root CA 1, Cross-signed Amazon Root CA 3. Can you tell me which one was working for you?

Sorry for the late reply. Iā€™ve been out of town. Amazon Root CA 1 is what worked for me in region US-East-2. Iā€™m not sure if there are different certs for different regions, but I donā€™t believe so.

1 Like

thanks @ hirotakaster for a a great library :slight_smile:

Iā€™ve got things running on my end with package sizes of up to 4kb, which is much better than particle publish :slight_smile: When I go beyond this point however, to 6 or 8 kb, I canā€™t connect and things start to get uglyā€¦ I think I have like 20kb free of heapspace but of course on my Boron the stack is only 6kb. I can see that the actual buffer is stored in heapspace but Iā€™m wondering if during the send operation, the buffer is stored on the stack all at once? Anyways, something to think about, Iā€™d really like to send 10kb at at time, I realize this may be unrealistic though.

Thanks again, Colin

Hi,

All I am new to particle so please excuse any obvious mistakes.

I am having the same issue a number of people have had with trying to get the connection to work correctly.

#include "MQTT-TLS.h"

void callback(char* topic, byte* payload, unsigned int length);

#define AMAZON_IOT_ROOT_CA_PEM                                          \
"-----BEGIN CERTIFICATE-----\r\n"                                       \
"MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsF\r\n" 	\
"ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6\r\n" 	\
"b24gUm9vdCBDQSAxMB4XDTE1MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTEL\r\n" 	\
"MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv\r\n" 	\
"b3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJ4gHHKeNXj\r\n" 	\
"ca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgHFzZM\r\n" 	\
"9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qw\r\n" 	\
"IFAGbHrQgLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6\r\n" 	\
"VOujw5H5SNz/0egwLX0tdHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L\r\n" 	\
"93FcXmn/6pUCyziKrlA4b9v7LWIbxcceVOF34GfID5yHI9Y/QCB/IIDEgEw+OyQm\r\n" 	\
"jgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC\r\n" 	\
"AYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3DQEBCwUA\r\n" 	\
"A4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDI\r\n" 	\
"U5PMCCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUs\r\n" 	\
"N+gDS63pYaACbvXy8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vv\r\n" 	\
"o/ufQJVtMVT8QtPHRh8jrdkPSHCa2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU\r\n" 	\
"5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2xJNDd2ZhwLnoQdeXeGADbkpy\r\n" 	\
"rqXRfboQnoZsG4q5WTP468SQvvG5\r\n" 	\
"-----END CERTIFICATE-----"
const char amazonIoTRootCaPem[] = AMAZON_IOT_ROOT_CA_PEM;

#define CLIENT_KEY_CRT_PEM                                              \
"-----BEGIN CERTIFICATE-----\r\n"                                       \
"MIIDWjCCAkKgAwIBAgIVAMqWPHv9Od5y4Vj74xMImnD6tDC4MA0GCSqGSIb3DQEB\r\n"  \
..........
"vLDUQsdB0ogiu2DcUu0tRzb0Mosd4IiHIu95ZQ5v3a/zQKjZyXU2A5JLv5FlYQ==\r\n"  \
"-----END CERTIFICATE-----"
const char clientKeyCrtPem[] = CLIENT_KEY_CRT_PEM;

#define CLIENT_KEY_PEM                                                  \
"-----BEGIN RSA PRIVATE KEY-----\r\n"                                   \
"MIIEowIBAAKCAQEA2183f/KCgC5eSLgHIDqSXKY1el0IPTVfGQsHGQMy/0pZZno8\r\n"  \
.......
"Gi5vjS89XZ6XP3NSrviNZ8uJowU/Ww005r7rBcKIgtfdbEqc3tXG\r\n"  \
"-----END RSA PRIVATE KEY-----"
const char clientKeyPem[] = CLIENT_KEY_PEM;

/**
 * if want to use IP address,
 * byte server[] = { XXX,XXX,XXX,XXX };
 * MQTT client(server, 1883, callback);
 * want to use domain name,
 * MQTT client("www.sample.com", 1883, callback);
 **/
MQTT client("my-unique-url.iot.ap-southeast-2.amazonaws.com", 8883, callback);

// recieve message
void callback(char* topic, byte* payload, unsigned int length) {
    char p[length + 1];
    memcpy(p, payload, length);
    p[length] = NULL;
    String message(p);

    if (message.equals("RED"))
        RGB.color(255, 0, 0);
    else if (message.equals("GREEN"))
        RGB.color(0, 255, 0);
    else if (message.equals("BLUE"))
        RGB.color(0, 0, 255);
    else
        RGB.color(255, 255, 255);
    delay(1000);
}

#define ONE_DAY_MILLIS (24 * 60 * 60 * 1000)
unsigned long lastSync = millis();
int counter = 0;
void setup() {
    Serial.begin(9600);
    if (millis() - lastSync > ONE_DAY_MILLIS) {
        Particle.syncTime();
        lastSync = millis();
    }
    if(!WiFi.ready())
    {Serial.println("Error, wifi not connected");
    }
    RGB.control(true);
    int ret;
    // enable tls. set Root CA pem, private key file.
    if ( (ret = client.enableTls(amazonIoTRootCaPem, sizeof(amazonIoTRootCaPem),
                     clientKeyCrtPem, sizeof(clientKeyCrtPem),
                     clientKeyPem, sizeof(clientKeyPem)))>0)
                     {
                     Serial.printlnf("client.enableTls failed with code: %d", ret);
                   }
                   else
                   {
                     Serial.println("Certs ok");
                   }
    Serial.println("tls enable");

    // connect to the server
    //client.connect("MarkPhoton");
    if ( (ret >= 0) && ((ret = client.connect("MarkPhoton")) < 0) ) {    // if client enable tls succeeded, attempt connect.  Can block for up to 60 seconds
                Serial.printlnf("client.connect failed with code: %d", ret);
            }
            else
            {
              Serial.println("test");
              Serial.printlnf("client.connect with code: %d", ret);
            }
    // publish/subscribe

    int connect = client.isConnected();
    Serial.println(connect);
    if (client.isConnected()) {
        Serial.println("client connected");
        client.publish("/outTopic", "hello world");
        client.subscribe("inTopic/message");
    }
}

void loop() {
    if (client.isConnected()) {
      client.publish("/outTopic", "hello world photon");
        client.loop();
        delay(200);
    }
    delay(200);
}

I have added

#define debug_tls( fmt, ... ) \
    Serial.printf(fmt, __VA_ARGS__)

to the top of the mqtt-tls.cpp

but I donā€™t seem to get any error code output.

The Consol output show:
Certs ok
tls enabled
test
client.connect with code: 0
0

should I expect to get more in the serial console with the debug enabled?

In addition, my policy on AWS IOT is configured as follows:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "iot:*",
      "Resource": "*"
    }
  ]
}

Really not sure where Iā€™m going wrong, any assistance appreciated.

Thanks in advance.

Hi, my AWS IoT test Policy is this.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "iot:*"
      ],
      "Resource": "*"
    }
  ]
}

And you might want to test with mosquitto_pub/sub command with your certificate files for AWS IoT setting is right or not.

Thanks Hirotakaster, Looking forward to getting this great library working.

Thanks for that find, I corrected my policy, but still no luck.

I have used MQTT explorer to successfully connect to IoT Core on AWS with those Certs and Keys and was successful in connecting and seeing published messages to my topic.

I did try using Mosquito_sub, but got the following:
Client MarkPhoton sending CONNECT
Client MarkPhoton received CONNACK (0)
Client MarkPhoton sending SUBSCRIBE (Mid: 1, Topic: /outTopic, QoS: 0, Options: 0x00)
Client MarkPhoton received SUBACK
Subscribed (mid: 1): 0
Error: The connection was lost.

it repeatedly loses the connection, but as far as I can tell it allows the subscription?

Here is my command:
mosquitto_sub -t /outTopic -v -i MarkPhoton -W 60 -h personalurl.iot.ap-southeast-2.amazonaws.com -p 8883 --cafile AmazonRootCA1.pem --cert certificate.pem.crt --key private.pem.key --debug

Any other thoughts?

Ok got both Mosquitto_sub and Pub working with those certs and key, so I must be missing something.

Thanks again in advance, if you have any other thoughts about debugging that would be great.