Initial TLS support

master
informatic 2016-09-11 01:46:42 +02:00
parent 0bba170041
commit e5629c9b04
12 changed files with 74 additions and 37 deletions

View File

@ -15,9 +15,14 @@ is directly connected on ESP-12E module.
Software
--------
Mosquitto contained in docker is used as a broker. ESP8266 code uses [Sming
framework](https://github.com/SmingHub/Sming). Set your Wifi configuration in
`common/common_config.h` (used by both `switch` and `light`)
Mosquitto contained in docker is used as a broker. For proper TLS you need to
create self-signed certificate and store its SHA-1 fingerprint in
`common/common_config.h`.
ESP8266 code uses [slaff's
fork of Sming framework](https://github.com/slaff/Sming). (For axTLS support)
Set your Wifi configuration in `common/common_config.h` (used by both `switch`
and `light`)
Thoughts
@ -27,4 +32,4 @@ Oh my, that's slow.^W^Wquite fast, when patched properly.
**WARNING!** `Sming.reset();` jumps to (serial) bootloader right after flashing.
This causes OTA to fail with `wdt reset`. External RESET assert is required after
flashing.
flashing.

View File

@ -8,7 +8,12 @@
#ifndef MQTT_BROKER
#define MQTT_BROKER "192.168.0.100"
#define MQTT_PORT 1883
#ifdef ENABLE_SSL
#define MQTT_PORT 8883
#define SSL_FINGERPRINT { } // TODO
#else
#define MQTT_PORT 1883
#endif
#endif
#define TOPIC_PREFIX "iot/"

2
master/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
ota/*
mqtt/certs/*

9
master/README.md Normal file
View File

@ -0,0 +1,9 @@
```
openssl req -nodes -new -x509 -days 3650 -extensions v3_ca -keyout ca.key -out ca.crt
openssl genrsa -out server.key 2048
openssl req -out server.csr -key server.key -new
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 3650
# Extract SHA-1
openssl x509 -in server.crt -sha1 -noout -fingerprint | sed 's/.*=/0x/g; s/:/, 0x/g'
```

View File

@ -6,18 +6,21 @@ import sys
# The callback for when the client receives a CONNACK response from the server.
def on_connect(client, userdata, rc):
print("Connected with result code "+str(rc))
# Subscribing in on_connect() means that if we lose the connection and
# reconnect then subscriptions will be renewed.
client.subscribe("light/status")
client.subscribe("#")
client.publish("iot/" + sys.argv[1] + "/" + sys.argv[2], sys.argv[3])
# The callback for when a PUBLISH message is received from the server.
def on_message(client, userdata, msg):
print(str(time.time())+" "+msg.topic+" "+str(msg.payload))
exit()
client = mqtt.Client("test-client-%d" % random.randint(100, 999))
if len(sys.argv) < 4:
print('Usage: client.py [DEVICE_ID] [ENDPOINT] [VALUE]');
exit(1)
client = mqtt.Client()
client.on_connect = on_connect
client.on_message = on_message

View File

@ -1,11 +1,15 @@
mosquitto:
image: toke/mosquitto
volumes:
- mqtt/config/:/mqtt/config/conf.d:ro
- mqtt/certs/:/mqtt/config/certs:ro
ports:
- "1883:1883"
- "8883:8883"
nginx:
image: nginx
volumes:
- ota:/usr/share/nginx/html
- ota:/usr/share/nginx/html
ports:
- "80:80"
- "80:80"

View File

@ -0,0 +1,4 @@
listener 8883
cafile /mqtt/config/certs/ca.crt
certfile /mqtt/config/certs/server.crt
keyfile /mqtt/config/certs/server.key

View File

@ -49,14 +49,22 @@ void SpejsNode::keepAliveHandler() {
void SpejsNode::onConnected() {
Serial.println("Connection successful");
// "+deviceID+"/
mqtt.setWill(TOPIC_PREFIX + deviceID + "/state", "offline", 1, true);
#ifdef ENABLE_SSL
const uint8_t sha1Fingerprint[] = SSL_FINGERPRINT;
mqtt.connect("iot-" + deviceID, "", "", true);
mqtt.addSslOptions(SSL_SERVER_VERIFY_LATER);
mqtt.setSslFingerprint(sha1Fingerprint, 20);
#else
mqtt.connect("iot-" + deviceID);
#endif
mqtt.subscribe(TOPIC_PREFIX + deviceID + "/control");
for(unsigned int i = 0 ; i < inputs.count() ; i++) {
mqtt.subscribe(TOPIC_PREFIX + deviceID + "/" + inputs.keyAt(i));
mqtt.subscribe(TOPIC_PREFIX + deviceID + "/" + inputs.keyAt(i));
}
mqtt.publish(TOPIC_PREFIX + deviceID + "/state", "online");
@ -80,9 +88,10 @@ void SpejsNode::registerInput(String key, MqttStringSubscriptionCallback callbac
void SpejsNode::mqttCallback(String origtopic, String value) {
String devicePrefix = TOPIC_PREFIX + deviceID;
if(!origtopic.startsWith(devicePrefix)) {
Serial.println("ignoring");
return;
Serial.println("ignoring");
return;
}
String topic = origtopic.substring(devicePrefix.length() + 1);
@ -91,24 +100,20 @@ void SpejsNode::mqttCallback(String origtopic, String value) {
Serial.println(value);
if(inputs.contains(topic)) {
Serial.println("dupa");
inputs[topic](origtopic, value);
inputs[topic](origtopic, value);
} else {
Serial.println("unknown topic?");
Serial.println("unknown topic?");
}
}
void SpejsNode::controlHandler(String key, String value) {
Serial.println("Control command: " + value);
if(value == "ota") {
startOTA();
startOTA();
} else if(value == "restart") {
//System.restart();
keepaliveTimer.initializeMs(500, *[] {
System.restart();
}).start();
System.restart();
} else {
Serial.println("Invalid command");
Serial.println("Invalid command");
}
}
@ -127,9 +132,9 @@ void SpejsNode::startOTA() {
bootconf = rboot_get_config();
if (currentSlot == 0)
slot = 1;
slot = 1;
else
slot = 0;
slot = 0;
Serial.printf("Updating to rom %d.\r\n", slot);
@ -147,11 +152,11 @@ void SpejsNode::startOTA() {
otaUpdater->setCallback(otaUpdateDelegate(&SpejsNode::otaUpdateCallback, this));
otaUpdater->start();
notify("ota", "started");
}
void SpejsNode::otaUpdateCallback(bool result) {
Serial.println("In callback...");
void SpejsNode::otaUpdateCallback(rBootHttpUpdate& updater, bool result) {
if(result == true) {
// success
notify("ota", "finished");
@ -159,18 +164,16 @@ void SpejsNode::otaUpdateCallback(bool result) {
uint8 slot;
if (currentSlot == 0)
slot = 1;
slot = 1;
else
slot = 0;
slot = 0;
// set to boot new rom and then reboot
Serial.printf("Firmware updated, rebooting to rom %d...\r\n", slot);
rboot_set_temp_rom(slot);
keepaliveTimer.initializeMs(500, *[] {
System.restart();
}).start();
} else {
notify("ota", "failed");
}

View File

@ -32,5 +32,5 @@ public:
void registerInput(String key, MqttStringSubscriptionCallback cb);
void mqttCallback(String, String);
void controlHandler(String, String);
void otaUpdateCallback(bool result);
void otaUpdateCallback(rBootHttpUpdate& updater, bool result);
};

View File

@ -1,7 +1,8 @@
MODULES = app ../spejsiot
DISABLE_SPIFFS = 1
USER_CFLAGS = -I../common
RBOOT_ENABLED ?= 1
RBOOT_BIG_FLASH ?= 1
ENABLE_SSL = 1
RBOOT_ENABLED = 1
RBOOT_BIG_FLASH = 1
RBOOT_RTC_ENABLED = 1
SPI_SIZE ?= 4M

View File

@ -4,7 +4,7 @@ SpejsNode node("switch");
void init() {
node.init();
node.registerInput("relay", *[](String value) {
node.registerInput("relay", *[](String key, String value) {
Serial.println("handler");
digitalWrite(5, value == "1" ? HIGH : LOW);
});

View File

@ -5,7 +5,7 @@ MEMORY
dport0_0_seg : org = 0x3FF00000, len = 0x10
dram0_0_seg : org = 0x3FFE8000, len = 0x14000
iram1_0_seg : org = 0x40100000, len = 0x8000
irom0_0_seg : org = 0x40202010, len = 0x42000
irom0_0_seg : org = 0x40202010, len = 0xF0000
}
PHDRS
@ -161,6 +161,7 @@ SECTIONS
*(.irom0.literal .irom.literal .irom.text.literal .irom0.text .irom.text)
out/build/app_app.a:*(.literal .text .literal.* .text.* .stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
*libsming.a:*(.literal .text .literal.* .text.* .stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
*libsmingssl.a:*(.literal .text .literal.* .text.* .stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
_irom0_text_end = ABSOLUTE(.);
_flash_code_end = ABSOLUTE(.);
} >irom0_0_seg :irom0_0_phdr