marvinroger / async-mqtt-client

📶 An Arduino for ESP8266 asynchronous MQTT client implementation
MIT License
835 stars 266 forks source link

Stack Trace using SSL example #55

Open PhracturedBlue opened 7 years ago

PhracturedBlue commented 7 years ago

I'm getting the following stack-trace when connecting to an SSL enabled mosquitto broker. Could this be related to my mosquitto configuration? I didn't modify anything other than the necessary vaeriables at the top of the code. Build was: platformio run --target upload

I am using Mosquitto as the broker if that is helpful. The only log messages from the broker are:

1499780241: New connection from 192.168.1.3 on port 8883.
1499780331: Client (null) has exceeded timeout, disconnecting.
1499780448: mosquitto version 1.3.4 terminating

Stacktrace:

Exception 3: LoadStoreError: Processor internal physical address or data error during load or store
Decoding 28 results
0x4020e647: __memcpy_aux at /Users/igrokhotkov/e/newlib-xtensa/xtensa-lx106-elf/newlib/libc/machine/xtensa/../../../../.././newlib/libc/machine/xtensa/memcpy.S line 92
0x40246114: chip_v6_unset_chanfreq at ?? line ?
0x402204fb: SHA512_Final at crypto/sha512.c line 207 (discriminator 3)
0x40219770: x509_new at ssl/x509.c line 201
0x4023d427: pp_attach at ?? line ?
0x4023d476: pp_attach at ?? line ?
0x402178f5: process_certificate at ssl/tls1.c line 2005
0x40218cd2: do_clnt_handshake at ssl/tls1_clnt.c line 107
0x4010020c: _umm_free at umm_malloc.c line ?
0x402069b6: ax_port_read at ?? line ?
0x4021871c: do_handshake at ssl/tls1.c line 2005
:  (inlined by) basic_read at ssl/tls1.c line 1481
0x40100688: free at ?? line ?
0x40218884: ssl_read at ssl/tls1.c line 2005
0x4020677d: tcp_ssl_read at ?? line ?
0x40205fa9: AsyncClient::_recv(tcp_pcb*, pbuf*, signed char) at ?? line ?
0x40212b1e: tcp_output at /Users/ivan/e/arduino-esp8266/tools/sdk/lwip/src/core/tcp_out.c line 925
0x40205fdb: AsyncClient::_s_recv(void*, tcp_pcb*, pbuf*, signed char) at ?? line ?
0x4021681c: tcp_input at /Users/ivan/e/arduino-esp8266/tools/sdk/lwip/src/core/tcp_in.c line 394 (discriminator 1)
0x401068f8: pvPortMalloc at ?? line ?
0x40214dd5: ip_input at /Users/ivan/e/arduino-esp8266/tools/sdk/lwip/src/core/ipv4/ip.c line 559
0x40214271: ethernet_input at /Users/ivan/e/arduino-esp8266/tools/sdk/lwip/src/netif/etharp.c line 1379
0x40103c12: lmacTxFrame at ?? line ?
0x4010402d: ppEnqueueRxq at ?? line ?
0x40103dc3: ppProcessTxQ at ?? line ?
0x40103dfe: ppProcessTxQ at ?? line ?
0x4022641b: ets_snprintf at ?? line ?
PhracturedBlue commented 7 years ago

FYI, I found that the issue was that my cert was generated using SHA512. I used the openssl defaults and everything worked fine.

Feel free to close the issue, but you may want to note it as a caveat that SHA512 certs aren't supported currently.

FYI, The reason I used SHA512 was because I generated my keys with this: https://github.com/owntracks/tools/blob/master/TLS/generate-CA.sh

Which was linked from this tutorial: https://stackoverflow.com/questions/26657319/how-do-you-set-up-encrypted-mosquitto-broker-like-a-webpage-which-has-https

allanbartley commented 7 years ago

Thank you for figuring this out.

I've just done a few tests: SHA1 - OK SHA256 - OK SHA512 - Fail (same error as above)

I also note that test.mosquitto.org:8883 uses a certificate with an SHA512 certificate, which explains why I can't connect to that server.

allanbartley commented 7 years ago

Further tests: SHA224 - OK SHA384 - Fail MD5 - OK

PhracturedBlue commented 7 years ago

I guess this is a bug in the 2.4 staging core? I'm not sure how to provide a test-case though, since the connection goes through many layers. Thanks for confirming this with various encryption. I have extended your fingerprint code to detect the encryption and warn my users about it: https://github.com/PhracturedBlue/ESP8266MQTTMesh/blob/master/utils/get_mqtt_fingerprint.py

I hardcoded the patterns, which is crude, but means I don't need to require that any other libraries be installed to use it. Also, I did not see MD5 as a legal signature in the reference docs here: https://tools.ietf.org/html/rfc5754#section-3

allanbartley commented 7 years ago

MD5 is broken, and I hope no one is using it, I tested it because it listed in the tool I was generating the certificates from. Maybe they removed it from the standard?

I'll make some amendments to the documentation.

gjt211 commented 7 years ago

UPDATE I found the solution in #53 changing the file async_config.h for ESPAsyncTCP as follows;

#ifndef ASYNC_TCP_SSL_ENABLED
#define ASYNC_TCP_SSL_ENABLED 0
#endif

to

#ifndef ASYNC_TCP_SSL_ENABLED
#define ASYNC_TCP_SSL_ENABLED 1
#endif

Sorry for the trouble.

I would like to implement TLS using the arduino IDE, not with PlatformIO. I am using the staging 2.4.0-rc1 core with the appropriate Async libraries.

When I added the TLS parts and try to compile I get the error; class AsyncMqttClient has no member named 'setSecure'

I understand that somehow I need to add the compiler flag build_flags = -DASYNC_TCP_SSL_ENABLED=1 but have no idea how to do this.

I have been (and still am) using TLS fingerprint with PubSubClient and I have quite a few sensors that run 24/7. I have been porting my code over to the Async libraries step by step and now have everything running except for TLS. If anyone can help or provide guidance (or even some clues!) it would be appreciated.

timpur commented 7 years ago

I got it working with Arduino ide.

I found you also need to import the esp wifi lib as the first thing of your sketch

Example

include

if ASYNC_TCP_SSL_ENABLED

Homie.getLogger() << F("ESP Homie Using TLS") << endl; Homie.getMqttClient().setSecure(true); //Homie.getMqttClient().addServerFingerprint((const uint8_t[])MQTT_SERVER_FINGERPRINT);

endif

// Before homie setup

barrenechea commented 7 years ago

@timpur did you achieve stability while running over SSL? I'm running it with Arduino IDE, and it crashes and reboots the ESP12 several times while connecting to the MQTT broker (it reboots between 2 to 10 times, until it finally connects).

Using SHA256 cert btw.

timpur commented 7 years ago

Tbh haven't tested lately, but from memory it seemed fine. No crashes, just a bit longer to connect, but that would make sense.

You can try a combo of these options. Try with better wifi signal. Also try with 160mhz over clock. I'd try the best case, both better wifi signal and over clock. Then work back to see which one make the most significant difference, assuming this effect the crashes at all.

This might tell you if it's performance issues that's causing the crashes.

Also not sure about this but in my tests I was using sha256 like you but I remember making sure the RSA key was only 2048. This might also effect it but not sure.

The picture I get it try use the lowest security on the eap8266 that is still reasonable.

Hope this helps. I'll try do some tests over the weekend and get back to you on these details.

barrenechea commented 7 years ago

Tried overclocking the device and still the same behavior (I didn't test a better wifi signal because I have an access point like 50cm from my desk).

And I'm using Let's Encrypt certificates, SHA256 and 2048 RSA Key, so it's the same as your tests.

Maybe it's my code, I have to dig deeper in order to detect why it (sometimes) crashes on boot, I guess I'll do that when I have more time.

timpur commented 7 years ago

Ill do some tests and get back to you with a sketch which is stable for me.

josep112 commented 6 years ago

I am using mqtt async and I want to implement tls, I followed this tutorial to program the mqtt of linux: https://myles.eftos.id.au/blog/2016/08/07/adding-tls/#.WnhwI5M-fR1 Now I am having trouble programming the esp8266 interface, if anyone can help me thank you, I already researched a lot on Google and found nothing consistent; my code:

include

include

include

if ASYNC_TCP_SSL_ENABLED

define MQTT_SECURE true

define MQTT_SERVER_FINGERPRINT {0x7e, 0x36, 0x22, 0x01, 0xf9, 0x7e, 0x99, 0x2f, 0xc5, 0xdb, 0x3d, 0xbe, 0xac, 0x48, 0x67, 0x5b, 0x5d, 0x47, 0x94, 0xd2}

define MQTT_PORT 8883

else

define MQTT_PORT 1883

endif

define WIFI_SSID "MyHome"

define WIFI_PASSWORD "1234567"

const char host = "xxxx.xxxx.net.br"; const char mqtt_user = "user"; //usuário do mosquitto const char* mqtt_pwd = "12345"; //senha do mqtt

AsyncMqttClient mqttClient; Ticker mqttReconnectTimer;

WiFiEventHandler wifiConnectHandler; WiFiEventHandler wifiDisconnectHandler; Ticker wifiReconnectTimer; //========================================= void connectToWifi() { Serial.println("Connecting to Wi-Fi..."); WiFi.begin(WIFI_SSID, WIFI_PASSWORD); } //========================================= void onWifiConnect(const WiFiEventStationModeGotIP& event) { Serial.println("Connected to Wi-Fi."); connectToMqtt(); } //========================================= void onWifiDisconnect(const WiFiEventStationModeDisconnected& event) { Serial.println("Disconnected from Wi-Fi."); mqttReconnectTimer.detach(); // ensure we don't reconnect to MQTT while reconnecting to Wi-Fi wifiReconnectTimer.once(2, connectToWifi); } //========================================= void connectToMqtt() { Serial.println("Connecting to MQTT..."); mqttClient.connect(); } //========================================= void onMqttConnect(bool sessionPresent) // MQTT Subscribe { String clientName; clientName += "LS"; if (mqttClient.subscribe(clientName.c_str(), 2)) { Serial.print(">>> [Mosquitto] Subscribe LS : "); Serial.println(clientName); }

}
//========================================= void onMqttDisconnect(AsyncMqttClientDisconnectReason reason) { Serial.println("Disconnected from MQTT.");

if (WiFi.isConnected()) { mqttReconnectTimer.once(2, connectToMqtt); } } //========================================= /void onMqttSubscribe(uint16_t packetId, uint8_t qos) { Serial.println("Subscribe acknowledged."); Serial.print(" packetId: "); Serial.println(packetId); Serial.print(" qos: "); Serial.println(qos); }/

/void onMqttUnsubscribe(uint16_t packetId) { Serial.println("Unsubscribe acknowledged."); Serial.print(" packetId: "); Serial.println(packetId); }/ //========================================= void onMqttMessage(char topic, char payload, AsyncMqttClientMessageProperties properties, size_t len, size_t index, size_t total) { char message_buff[150]; int i; for(i=0; i<len; i++) { message_buff[i] = payload[i]; } message_buff[i] = '\0'; String msgString = String(message_buff); Serial.println(msgString);

} //========================================= /void onMqttPublish(uint16_t packetId) { Serial.println("Publish acknowledged."); Serial.print(" packetId: "); Serial.println(packetId); }/ //========================================= void setup() { Serial.begin(115200); Serial.println(); Serial.println();

wifiConnectHandler = WiFi.onStationModeGotIP(onWifiConnect); wifiDisconnectHandler = WiFi.onStationModeDisconnected(onWifiDisconnect); mqttClient.onConnect(onMqttConnect); mqttClient.onDisconnect(onMqttDisconnect); mqttClient.onMessage(onMqttMessage); mqttClient.setServer(host, 1883); mqttClient.setCredentials(mqtt_user,mqtt_pwd); connectToWifi();

if ASYNC_TCP_SSL_ENABLED

mqttClient.setSecure(MQTT_SECURE); if (MQTT_SECURE) { mqttClient.addServerFingerprint((const uint8_t[])MQTT_SERVER_FINGERPRINT); }

endif

}

void loop() { }

timpur commented 6 years ago

you defined MQTT_PORT but never used it in mqttClient.setServer(host, 1883); .... so the port never changes based of this define which will definitely cause a issue for you with tls.

josep112 commented 6 years ago

Does this mean that I should just remove this line and the code will work?

mqttClient.onMessage(onMqttMessage); //mqttClient.setServer(host, 1883); mqttClient.setCredentials(mqtt_user,mqtt_pwd); connectToWifi();

timpur commented 6 years ago

sorry no should of added, use mqttClient.setServer(host, MQTT_PORT); instead.

josep112 commented 6 years ago

I made the change you said but I still can not connect to the linux server, is there any more detail I should do in esp?Thank you for your help

timpur commented 6 years ago

Assuming the fingerprint is the same as your broker ssl fingerprint ?

Assuming your broker certificate is the right format (see docs / known issues)

Should be all g

timpur commented 6 years ago

When I'm testing SSL connection I normally disable the fingerprint check on the esp and when working then work out the fingerprint

josep112 commented 6 years ago

Sorry for my experience! So I have to generate a FINGERPRINT of my linux server and for this there is the get-fingerprint.py script, but I can not generate this code I get the following error: python get-fingerprint.py --host site.net.br --port 8883 site.net.br Traceback (most recent call last): File "get-fingerprint.py", line 14, in cert_pem = ssl.get_server_certificate((args.host, args.port)) File "/usr/lib/python2.7/ssl.py", line 964, in get_server_certificate with closing(create_connection(addr)) as sock: File "/usr/lib/python2.7/socket.py", line 571, in create_connection raise err socket.error: [Errno 111] Connection refused

timpur commented 6 years ago

I don't know what your doing sorry, this is beyond this repo, I recommend following a guide on the mqtt broker you are trying to set up. In that they should run through how to set up SSL and to get the fingerprint from the certificate.

josep112 commented 6 years ago

Thanks, I'm looking for a complete esp and linux tutorial with tls but I'm not finding

josep112 commented 6 years ago

I have now managed to create my fingerprint but I get the error on the linux side when esp tries to connect Client connection from xxx.xxx.xxx.xxx failed: error:1408F10B:SSL routines:SSL3_GET_RECORD:wrong version number.

josep112 commented 6 years ago

My question now is whether to load the ca.crt file into esp spiffs or only fingerprint resolves?

timpur commented 6 years ago

So on the Linux side there are to ways you can set up the SSL certificate generate a CA certificate and then generate a server certificate from the CA or just create a server certificate. Rather way the esp only checks the server certificate fingerprint, it doesn't check certificate chaining (to my knowledge), so only use the server certificate not the CA certificate. Thus get the server certificate (the one directly used in the mqtt broker) and get the sha1 fingerprint of the certificate

But as I said in one of my posts, I'd test SSL with no fingerprint check enabled on the esp, so you can just test the TLS, and then work out the certificate verification.

josep112 commented 6 years ago

Yes, now I understand. Debugging better I realized that my code can not activate SSL:

if ASYNC_TCP_SSL_ENABLED

define MQTT_SECURE true

define MQTT_SERVER_FINGERPRINT {0x7e, 0x36, 0x22, 0x01, 0xf9, 0x7e, 0x99, 0x2f, 0xc5, 0xdb, 0x3d, 0xbe, 0xac, 0x48, 0x67, 0x5b, 0x5d, 0x47, 0x94, 0xd2}

define MQTT_PORT 8883

else

define MQTT_PORT 1883

endif

according to this one above I tried to change async_config.h for ESPAsyncTCP as follows;

ifndef ASYNC_TCP_SSL_ENABLED

define ASYNC_TCP_SSL_ENABLED 0

endif

to

ifndef ASYNC_TCP_SSL_ENABLED

define ASYNC_TCP_SSL_ENABLED 1

endif

but receive error