Openwrt based router mosquitto bridge fails to connect using TLS - lib(20) us unable to get local issuer certificate

Hi

I am working with a new device to simplify the deployment of Losant.
It is an openwrt modem/router with some hardware I/O

I can successfully connect it in bridge mode to losant but unsecure. I am trying to establish a TLS connection. However I get the following error.

1570665206: Connecting bridge Losant (broker.losant.com:8883)
1570665206: Bridge 5c80629330bca9000848e855 sending CONNECT
1570665207: OpenSSL Error: error:14090086:lib(20):func(144):reason(134)
1570665207: Socket error on client local.5c80629330bca9000848e855, disconnecting.

error lib(20) us unable to get local issuer certificate

I am new to openwrt and normally am doing everything through python or mosquitto bridge on full linux.
So looking for some advice :wink:

Connecting via openssl provides some more details

r oot@Teltonika-RUT955:/etc# openssl s_client -connect broker.losant.com:8883 -CAfile /lib/uci/upload/cbid.mosquitto.mqtt.bridge_cafile -CApath /etc
CONNECTED(00000003)
depth=1 C = US, O = DigiCert Inc, CN = DigiCert SHA2 Secure Server CA
verify error:num=20:unable to get local issuer certificate
—
Certificate chain
0 s:/C=US/ST=Ohio/L=Cincinnati/O=Losant IoT, Inc./CN=.losant.com
i:/C=US/O=DigiCert Inc/CN=DigiCert SHA2 Secure Server CA
1 s:/C=US/O=DigiCert Inc/CN=DigiCert SHA2 Secure Server CA
i:/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert Global Root CA
—
Server certificate
-----BEGIN CERTIFICATE-----
MIIGnjCCBYagAwIBAgIQB1hRcQwEBmL0kIZXyjqaYzANBgkqhkiG9w0BAQsFADBN
…
-----END CERTIFICATE-----
subject=/C=US/ST=Ohio/L=Cincinnati/O=Losant IoT, Inc./CN=
.losant.com
issuer=/C=US/O=DigiCert Inc/CN=DigiCert SHA2 Secure Server CA
—
No client certificate CA names sent
Client Certificate Types: RSA sign, DSA sign, ECDSA sign
Requested Signature Algorithms: ECDSA+SHA256:ECDSA+SHA384:ECDSA+SHA512:0x07+0x08:0x08+0x08:0x09+0x08:0x0A+0x08:0x0B+0x08:0x04+0x08:0x05+0x08:0x06+0x08:RSA+SHA256:RSA+SHA384:RSA+SHA512:ECDSA+SHA224:ECDSA+SHA1:RSA+SHA224:RSA+SHA1:DSA+SHA224:DSA+SHA1:DSA+SHA256:DSA+SHA384:DSA+SHA512
Shared Requested Signature Algorithms: ECDSA+SHA256:ECDSA+SHA384:ECDSA+SHA512:RSA+SHA256:RSA+SHA384:RSA+SHA512:ECDSA+SHA224:ECDSA+SHA1:RSA+SHA224:RSA+SHA1:DSA+SHA224:DSA+SHA1:DSA+SHA256:DSA+SHA384:DSA+SHA512
Peer signing digest: SHA512
Server Temp Key: ECDH, P-256, 256 bits
—
SSL handshake has read 3610 bytes and written 396 bytes
—
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES256-GCM-SHA384
Server public key is 2048 bit
Secure Renegotiation IS supported
No ALPN negotiated
SSL-Session:
Protocol : TLSv1.2
Cipher : ECDHE-RSA-AES256-GCM-SHA384
Session-ID: 9A29C7AEA16B507D493C951AA970FCEFFB6FCBCE49EAC7D6D40667415242BF80
Session-ID-ctx:
Master-Key: E9EEEC80D016DB26954163565235EB0197A70F5DE1247E135E1BDFCA9000929E3BC7EE87539CA702C13C09E2B974F205
Key-Arg : None
PSK identity: None
PSK identity hint: None
SRP username: None
TLS session ticket lifetime hint: 300 (seconds)
TLS session ticket:
0000 - 41 93 82 43 e7 b1 6f 61-f6 64 d7 d2 5f de 0b 02 A…C…oa.d……
0010 - 63 bf 75 0f 65 ff 4e dd-bc aa b5 02 85 d8 1b 92 c.u.e.N…
0020 - ed 6a ac 0b 31 0f 27 72-08 65 24 76 48 4c 93 a0 .j…1.'r.e$vHL…
0030 - e5 e2 38 1a e5 3c 3b 4f-68 3b e4 86 7e 5c 55 bf …8…<;Oh;…~\U.
0040 - 7d 76 ab e1 9b 83 2a 41-e9 cf 20 75 08 5f d8 08 }v…*A… u.
…
0050 - 38 fd 83 36 ed d7 32 38-32 0d 6f 7a 27 34 a6 04 8…6…282.oz’4…
0060 - 57 9b 94 8f b3 24 ca 12-3e bd 18 f9 e7 48 d1 0d W…$…>…H…
0070 - 22 31 1a 7a d1 67 99 98-3f 80 e8 a9 4f d6 ba 9d "1.z.g…?..O…
0080 - d5 9c 44 2a f9 60 2c 9d-34 b2 e2 86 5a 73 83 2f …D*.`,.4…Zs./
0090 - 16 51 b4 51 c9 e9 a4 0c-23 f5 38 d6 5d b7 e9 f9 .Q.Q…#.8.]…
00a0 - 22 19 9b 8e 97 cf fa c0-4a b1 0b e1 f7 b4 31 7d "…J…1}

    Start Time: 1570665869
    Timeout   : 300 (sec)
    Verify return code: 20 (unable to get local issuer certificate)
---
closed

Ok got a little further at least with openssl

I found that install ca-certificates package (opkg install ca-certificates) openssl command connects with out the error lib(20) us unable to get local issuer certificate error

root@Teltonika-RUT955:/etc/ssl/certs# openssl s_client -connect broker.losant.com:8883 -CAfile /lib/uci/upload/cbid.mosquitto.mqtt.bridge_cafile
CONNECTED(00000003)
depth=2 C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert Global Root CA
verify return:1
depth=1 C = US, O = DigiCert Inc, CN = DigiCert SHA2 Secure Server CA
verify return:1
depth=0 C = US, ST = Ohio, L = Cincinnati, O = "Losant IoT, Inc.", CN = *.losant.com
verify return:1
---
Certificate chain
 0 s:/C=US/ST=Ohio/L=Cincinnati/O=Losant IoT, Inc./CN=*.losant.com
   i:/C=US/O=DigiCert Inc/CN=DigiCert SHA2 Secure Server CA
 1 s:/C=US/O=DigiCert Inc/CN=DigiCert SHA2 Secure Server CA
   i:/C=US/O=DigiCert Inc/OU=www.digicert.com/CN=DigiCert Global Root CA

However mosquitto broker is still unable to connect and has the same error.
It would seem the broker is unable to locate other required certificates in the certificate chain.

Will keep digging and reporting - hopefully this well help someone else too.

Ok found the solution.

The modem as a cacert bundle which can be editined through the web interface (or via commandline).

By adding all of the digicert certificates to this bundle and the specifying the bridge_cafile points to the bundle the mosquitto bridge can connect successfully using TLS.

It would seem there are not enough of the full chain of certificates present, by default. After installing them pointing capath in mosquitto.conf was insufficient. Documentation for mosquitto.conf would suggest that would work.

So point bridge_cafile to the bundle solves the issue

bridge_cafile /etc/cacert.pem

Hope this helps anyone else venturing here :wink:

T

1 Like

Lastly I had to modify the UCI services for mosquitto as it the incarnation provided by default expects

bridge_keyfile
bridge_certfile

Which we don’t have for a losant connection. So in /etc/init.d/mosquitto added conditions on each of these.

                # Use TLS/SSL for bridge connection
                if [ "$use_remote_tls" == "1" ]; then
                        echo "bridge_cafile $bridge_ca_file" >> $CONFIG
                        if [ ! -z "$bridge_cert_file"]; then
                          echo "bridge_certfile $bridge_cert_file" >> $CONFIG
                        fi
                        if [ ! -z "$bridge_key_file"]; then
                          echo "bridge_keyfile $bridge_key_file" >> $CONFIG
                        fi
                        echo "bridge_tls_version $bridge_tls_version" >> $CONFIG
                        if [ "$bridge_insecure" = "1" ]
                        then
                                echo "bridge_insecure true" >> $CONFIG
                        fi
                fi
1 Like

Hi @Tim_Hoffman,

So glad you found a solution, and thank you so much for sharing it! I know this will help someone in the future :smile:

Thanks,
Julia

1 Like

Hi @Tim_Hoffman,
I see that you’re using a Teltonika device, any chance you managed to configure the MQTT broker via the WebUI?
Any feedback on this would be much appreciated, I’m trying to send some modbus register values to Losant via MQTT and I can’t seem to get it working.
Cheers
Jules

@Jules_Huguenin,

If you can provide any screenshots, error message etc., we can see if we can help point you in the right direction!

What are you running into?

Hi @anaptfox,
Here is the process described by the device’s manufacturer:


The device supports the MQTT functionality via the Mosquitto broker.

I can locally retrieve the required data via modbus, then my understanding is that I have two options to send it to Losant.

  1. Data to server:

  2. MQTT broker:

I’m not getting any error messages from the WebUI, not sure where to look for these.
Thanks for your help.

[UPDATE]
@anaptfox, I have managed to establish a connection to Losant without using the remote TLS:

Both the gateway and peripheral devices are connected and I can publish and subscribe to topics using an integration.

Question; this gets quite complicated considering I need two devices + an integration in Losant per physical device. Am I doing this the right way?
Cheers
Jules

@Jules_Huguenin,

Overall, here I’d recommend your “Data to server:” method. You would still need to create a device for every device you wanted to represent in Losant. However, this would save you an integration for each device.

For the configuration:

Losant requires the client ID, username, and password fields be correctly set on all MQTT connect calls:

  • client id —Must be set to a valid Device ID that is already registered with the Losant Platform.
  • username —Must be set to a Losant Access Key.
  • password —Must be set to a Losant Access Secret, which is generated when creating an Access key.

You can find more details here:

For a TLS connection, here is where you can find the Root Cert: https://github.com/Losant/losant-mqtt-ruby/blob/master/lib/losant_mqtt/RootCA.crt

Hi @anaptfox,
Thanks for your previous recommendation on using the “Data To Server” function. Unfortunately I can’t get the device to send data without using the MQTT bridge.
The only difference I can see between the two options is that the client ID is not required in the Data To Server configuration:

MQTT broker with bridge configuration: (OK)
image

Data To Server via MQTT: (no Client ID)
image

Would the TLS option help me?
certificate based:
image
or with a pre-shared key:
image

While I can make the above work using the device broker with the bridge configuration, and with two devices in LOSANT, I have another problem sending commands from LOSANT to the device.
I can send the command and I receive the state, but with an invalid response. I’m guessing the device doesn’t like the format of the payload:
image

From what I can read here: TRB145 Modbus - Teltonika Networks Wiki, it looks like the device is not expecting a JSON object? Is there a way to send a string only?

Cheers
Jules

@Jules_Huguenin,

Unfortunately I can’t get the device to send data without using the MQTT bridge.

This is due to how the Losant Broker is orchestrated. We require ClientID, Key, and Secret for authentication.

Would the TLS option help me?

Setting up a TLS connection, in this case, would take some work, and is something I am unfortunately unable to help with.

I can send the command and I receive the state, but with an invalid response.

According to your picture, it looks like you might be getting an invalid response due to an improperly formatted JSON object on the state topic. This could be because of an unparseable JSON object. Are you able to view the message being sent from your device to the cloud?

One option you have, if you are unable to change the message being sent, is to report to a Custom Topic, and then use a workflow to parse the message and report state. This will, though, require you to scope your Access Key/Secret for All MQTT topics or Additional Topics (you will have to input the additional topic).

Please let me know if this helps, or if you have any other questions.

Thank you,
Heath

Hi @heath,
Thanks for your response.
Regarding the client ID, I’ll check with Teltonika whether it’s possible or not to implement this.

Regarding the MQTT request and response, I don’t have a problem with the state topic, I understand that I need a valid JSON format and I do have it when I get a valid response from the “Data to Server” recurring response (which is then not triggered by a request).
Even though I have an invalid JSON format response, I can still see the kind of response I get in the log in LOSANT, and it tells me that the device didn’t like the command.

I’m fairly confident the problem comes from the format of the command being sent from LOSANT. I did a test with MQTT lens with a succesful outcome:
image

Any way we can adjust the format of the command from LOSANT?
Cheers
Jules

@Jules_Huguenin,

My apologies, I interpreted your question incorrectly.

There is not a way, currently, to adjust the format of the command from Losant when sending a device command.

Thank you,
Heath

@Jules_Huguenin,

Would you be able to share with me a screenshot of the contents of the device command you are sending from Losant to your device?

Are you using Device Commands? Device commands are sent as a JSON String. Is your device subscribed to the correct topic to receive commands from Losant (losant/<losant-device-id>/commands)?

Any additional information you can provide will be greatly appreciated.

Thank you,
Heath

Hi @Heath,
Yes my device is subscribed to the correct topic, and the fact that I’m receiving a response in Losant confirms this.
Below is a screenshot with the command workflow:

Here is my conversation on this subject with Teltonika: Invalid request from MQTT response - TRB145 - Crowd Support Forum | Teltonika Networks
Cheers
Jules

@Jules_Huguenin,

Thanks for including the thread that you had with Teltonika.

Instead of sending a Device Command, which sends a message in a specific format, you can have your device subscribe to a Custom Topic, and then you can use the MQTT Output node to send a message that you define both the content and format.

This option, though, will require you to scope your Access Key/Secret for All MQTT topics or Additional Topics (you will have to input the additional topic).

Please let me know if this works.

Thank you,
Heath

1 Like

Hey @Heath,
Sorry for not sending feedback earlier, I’ve just implement your suggestion and it works fine.
Thanks for your help.
Cheers
Jules

1 Like