IOT - ESP32 Remotely
Can we simply SSH to the ESP32 for remote config or some sort?
Of course it does not natively support SSH in the same way as full-fledged Linux devices, but it can be configured to mimic similar functionality using various techniques. Here’s an overview of the possibilities:
Native SSH Support
- Not Available: The ESP32 lacks an operating system like Linux to natively support SSH (Secure Shell). SSH requires software like OpenSSH or Dropbear, which the ESP32 cannot run due to limited resources.
Alternative Options for Remote Configuration
1. Using Telnet or Custom TCP Server
- Telnet: You can use libraries like
TelnetStreamor write a custom Telnet-like server for remote text-based communication.- Libraries: The
TelnetStreamlibrary simplifies Telnet server implementation for the ESP32. - Security: Telnet lacks encryption; use it in isolated or development environments only.
- Libraries: The
- Custom TCP Server: You can write a TCP server on the ESP32 to accept commands and configure parameters remotely.
Example: Simple Telnet Implementation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <WiFi.h>
#include <TelnetStream.h>
const char* ssid = "YOUR_WIFI_SSID";
const char* password = "YOUR_WIFI_PASSWORD";
void setup() {
Serial.begin(115200);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("WiFi connected!");
TelnetStream.begin();
}
void loop() {
if (TelnetStream.available()) {
String command = TelnetStream.readStringUntil('\n');
TelnetStream.println("Received command: " + command);
// Handle commands
}
}
2. Web-Based Configuration
- Web Server: Run a lightweight web server on the ESP32, allowing configuration changes via a browser.
- Libraries like
ESPAsyncWebServermake it easy to create user-friendly interfaces. - Security: Implement HTTPS (with TLS) for secure communication.
- Libraries like
Example: Basic Web Server for Configuration
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <WiFi.h>
#include <WebServer.h>
const char* ssid = "YOUR_WIFI_SSID";
const char* password = "YOUR_WIFI_PASSWORD";
WebServer server(80);
void handleRoot() {
server.send(200, "text/plain", "ESP32 Web Config Page");
}
void setup() {
Serial.begin(115200);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("WiFi connected!");
server.on("/", handleRoot);
server.begin();
}
void loop() {
server.handleClient();
}
3. MQTT for Remote Configuration
- Use MQTT to send and receive configuration commands.
- Example: Publish configuration changes (e.g., WiFi SSID, passwords, or operational parameters) to specific topics.
4. Over-the-Air (OTA) Updates
- OTA allows updating firmware and configurations remotely.
- Use the ArduinoOTA library to upload new code or configurations wirelessly.
5. Secure Shell-Like Functionality with ESP-IDF
- The ESP-IDF framework (official SDK for ESP32) allows advanced features.
- You can implement a custom shell-like interface using the ESP-IDF console or FreeRTOS tasks.
- Example: Use UART, Telnet, or a WebSocket for interactive sessions.
Best Practices for Secure Remote Configuration
- Encryption: Use SSL/TLS (via the
mbedtlslibrary) for secure communication. - Authentication: Require user credentials for any configuration interface.
- Restricted Access: Limit access to trusted devices or IP ranges.
- Audit Logs: Maintain logs of configuration changes if possible.
- Firmware Updates: Enable OTA for easy patching of vulnerabilities.
While the ESP32 does not natively support SSH, these alternatives can provide secure and flexible methods to remotely configure the device.
To achieve a secure and configurable setup for two ESP32 Devkit-C devices with DHT22 sensors communicating with a Mosquitto server, the devices will:
- Publish sensor data to the Mosquitto server.
- Subscribe to a configuration topic for remote reconfiguration.
- Use TLS for secure communication with the Mosquitto broker.
Wiring Example for Each Device
DHT22 Pinout:
- VCC (Pin 1): Connect to 3.3V on ESP32.
- Data (Pin 2): Connect to GPIO4 on ESP32 (can be adjusted in code).
- GND (Pin 4): Connect to GND on ESP32.
Steps to Set Up Secure Communication
-
Generate SSL/TLS Certificates for Mosquitto Server
Follow the steps here to generate server certificates. Ensure the certificates are in place and the Mosquitto broker is configured to use them. -
Prepare ESP32 with Certificates Convert the Mosquitto server’s CA certificate (
ca.crt) to a format compatible with the ESP32 and include it in the Arduino IDE. -
Install Required Arduino Libraries
- PubSubClient for MQTT
- Adafruit Unified Sensor and DHT Sensor Library
Code for Each ESP32 Device
Common Configuration
- ESP32 Device 1 Script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
#include <WiFi.h>
#include <PubSubClient.h>
#include <DHT.h>
#include <WiFiClientSecure.h>
// DHT22 Configuration
#define DHTPIN 4
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);
// WiFi and MQTT Configuration
const char* ssid = "YOUR_WIFI_SSID";
const char* password = "YOUR_WIFI_PASSWORD";
const char* mqtt_server = "YOUR_MQTT_BROKER_IP";
const int mqtt_port = 8883; // Secure MQTT port
const char* device_id = "device1";
const char* data_topic = "devices/device1/data";
const char* config_topic = "devices/device1/config";
// Root CA certificate
const char* ca_cert = \
"-----BEGIN CERTIFICATE-----\n" \
"YOUR_CA_CERTIFICATE_HERE\n" \
"-----END CERTIFICATE-----\n";
WiFiClientSecure secureClient;
PubSubClient client(secureClient);
String mqtt_username = "YOUR_MQTT_USERNAME";
String mqtt_password = "YOUR_MQTT_PASSWORD";
void connectWiFi() {
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("WiFi connected");
}
void reconnectMQTT() {
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
if (client.connect(device_id, mqtt_username.c_str(), mqtt_password.c_str())) {
Serial.println("Connected to MQTT");
client.subscribe(config_topic);
} else {
Serial.print("Failed, rc=");
Serial.print(client.state());
Serial.println(" Trying again in 5 seconds");
delay(5000);
}
}
}
void callback(char* topic, byte* message, unsigned int length) {
String incomingMessage;
for (unsigned int i = 0; i < length; i++) {
incomingMessage += (char)message[i];
}
Serial.println("Message received: " + incomingMessage);
// Parse configuration commands
if (String(topic) == config_topic) {
if (incomingMessage.startsWith("update_wifi")) {
// Parse new SSID and password
int ssidIndex = incomingMessage.indexOf(" ") + 1;
int passwordIndex = incomingMessage.lastIndexOf(" ") + 1;
String newSSID = incomingMessage.substring(ssidIndex, passwordIndex - 1);
String newPassword = incomingMessage.substring(passwordIndex);
// Update WiFi configuration
WiFi.begin(newSSID.c_str(), newPassword.c_str());
Serial.println("Updating WiFi configuration...");
}
}
}
void setup() {
Serial.begin(115200);
dht.begin();
connectWiFi();
secureClient.setCACert(ca_cert);
client.setServer(mqtt_server, mqtt_port);
client.setCallback(callback);
}
void loop() {
if (!client.connected()) {
reconnectMQTT();
}
client.loop();
// Read sensor data
float temperature = dht.readTemperature();
float humidity = dht.readHumidity();
if (isnan(temperature) || isnan(humidity)) {
Serial.println("Failed to read from DHT sensor!");
return;
}
// Prepare JSON payload
String payload = "{\"temperature\": " + String(temperature) + ", \"humidity\": " + String(humidity) + "}";
client.publish(data_topic, payload.c_str());
Serial.println("Published data: " + payload);
delay(5000);
}
- ESP32 Device 2 Script
Change only thedevice_id,data_topic, andconfig_topicvalues todevice2anddevices/device2/....
Secure Mosquitto Configuration
- Enable TLS in the Mosquitto configuration file (
/etc/mosquitto/mosquitto.conf):1 2 3 4 5 6 7
listener 8883 cafile /path/to/ca.crt certfile /path/to/server.crt keyfile /path/to/server.key allow_anonymous false password_file /etc/mosquitto/passwordfile
- Create MQTT username and password:
1 2
mosquitto_passwd -c /etc/mosquitto/passwordfile YOUR_MQTT_USERNAME systemctl restart mosquitto
Testing
- Verify Mosquitto broker is running with TLS enabled.
- Use tools like MQTT Explorer to verify data is being published securely.
- Publish commands to
devices/device1/configto test configuration updates.
Configurations Supported by the Provided Code
The code supports reconfiguration of the following parameters dynamically via MQTT messages:
-
Wi-Fi Credentials
Allows the ESP32 to switch to a new Wi-Fi network without requiring reprogramming.- Command format:
1
update_wifi NEW_SSID NEW_PASSWORD
Example:
1
update_wifi MyNewSSID MyNewPassword
- Command format:
-
Additional Parameters (extendable in code)
The code can be extended to include more reconfigurable parameters. Examples include:- MQTT topics for publishing/subscribing.
- Publish interval for sensor data.
- Thresholds for specific alerts (e.g., high temperature or humidity).
Sending Configuration Commands from the MQTT Server
To send configuration commands, you can use an MQTT client like MQTT Explorer, mosquitto_pub, or a Python script.
Using mosquitto_pub Command
Example command to update Wi-Fi credentials:
1
mosquitto_pub -h YOUR_MQTT_BROKER_IP -p 8883 --cafile /path/to/ca.crt -u "YOUR_MQTT_USERNAME" -P "YOUR_MQTT_PASSWORD" -t "devices/device1/config" -m "update_wifi MyNewSSID MyNewPassword"
Explanation:
-h: MQTT broker address-p: Port number (secure port: 8883)--cafile: Path to the CA certificate for secure communication-u: MQTT username-P: MQTT password-t: MQTT topic (devices/device1/config)-m: Message payload (update_wifi MyNewSSID MyNewPassword)
Using MQTT Explorer
- Connect to your MQTT broker with TLS enabled.
- Navigate to the configuration topic for the device (e.g.,
devices/device1/config). - Publish a message in the correct format:
1
update_wifi MyNewSSID MyNewPassword
Extending the Code for Additional Configurations
You can add more configuration commands by extending the callback function in the code. For example:
1
2
3
4
5
if (incomingMessage.startsWith("set_publish_interval")) {
int newInterval = incomingMessage.substring(incomingMessage.indexOf(" ") + 1).toInt();
publishInterval = newInterval;
Serial.println("Updated publish interval to: " + String(publishInterval));
}
To send the updated publish interval:
1
mosquitto_pub -h YOUR_MQTT_BROKER_IP -p 8883 --cafile /path/to/ca.crt -u "YOUR_MQTT_USERNAME" -P "YOUR_MQTT_PASSWORD" -t "devices/device1/config" -m "set_publish_interval 10000"
Here:
set_publish_interval 10000updates the publish interval to 10 seconds (10000 milliseconds).
Validation
- Monitor the device logs via the Arduino Serial Monitor to see the effect of the commands.
- Ensure commands are applied correctly and persist after the MQTT client reconnects to the server.