A secure UDP client library for ESP32 that implements DTLS (Datagram Transport Layer Security) using mbedTLS. This library provides encrypted and authenticated UDP communication, making it ideal for IoT applications requiring secure datagram transport.
- DTLS Support: Secure UDP connections using Datagram Transport Layer Security
- Multiple Authentication Methods:
- Root CA certificate authentication
- Client certificate and private key authentication
- Pre-shared key (PSK) authentication
- ESP32 Compatibility: Supports both ESP32 Arduino 2.x and 3.x
- Error Handling: Enhanced error reporting with errno information and LwIP statistics
- Memory Management: Automatic retry logic for memory-related errors
- WiFiClient Interface: Inherits from WiFiClient, providing familiar API
- Hardware: ESP32 development board
- Arduino IDE: Version 1.8.13 or later (or PlatformIO)
- ESP32 Arduino Core: Version 1.0.4 or later (2.x and 3.x supported)
- mbedTLS: Must be compiled with
MBEDTLS_SSL_PROTO_DTLSenabled
- Download this repository as a ZIP file
- In Arduino IDE, go to
Sketch→Include Library→Add .ZIP Library... - Select the downloaded ZIP file
- The library will be installed in your Arduino libraries folder
Add to your platformio.ini:
lib_deps =
https://github.com/alorbach/wificlientsecureudp.gitImportant: The mbedTLS library must be compiled with DTLS support enabled.
The ESP32 Arduino framework should already have DTLS support. If not, you may need to:
- Edit your
sdkconfigfile (usually in~/.platformio/packages/framework-arduinoespressif32/tools/sdk/sdkconfigor similar) - Ensure the following is set:
CONFIG_MBEDTLS_SSL_PROTO_DTLS=y
If you need to compile mbedTLS yourself, follow the ESP-IDF Component documentation.
After compilation, replace these files in your ESP32 Arduino framework:
packages/esp32/hardware/esp32/[version]/tools/sdk/sdkconfigpackages/esp32/hardware/esp32/[version]/tools/sdk/include/config/sdkconfig.hpackages/esp32/hardware/esp32/[version]/tools/sdk/lib/libmbedtls.apackages/esp32/hardware/esp32/[version]/tools/sdk/include/mbedtls/mbedtls/*
#include <WiFi.h>
#include <WiFiClientSecureUdp.h>
const char* ssid = "your_SSID";
const char* password = "your_PASSWORD";
const char* host = "example.com";
const uint16_t port = 4433;
// Root CA certificate (for server authentication)
const char* rootCACertificate = \
"-----BEGIN CERTIFICATE-----\n" \
"...\n" \
"-----END CERTIFICATE-----\n";
WiFiClientSecureUdp client;
void setup() {
Serial.begin(115200);
// Connect to WiFi
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("WiFi connected");
// Set CA certificate
client.setCACert(rootCACertificate);
// Connect to server
if (client.connect(host, port)) {
Serial.println("Connected to server");
// Send data
client.println("Hello, DTLS Server!");
// Read response
while (client.available()) {
char c = client.read();
Serial.print(c);
}
} else {
Serial.println("Connection failed");
}
}
void loop() {
// Your code here
}int connect(IPAddress ip, uint16_t port);
int connect(IPAddress ip, uint16_t port, int32_t timeout);
int connect(const char *host, uint16_t port);
int connect(const char *host, uint16_t port, int32_t timeout);int connect(IPAddress ip, uint16_t port, const char *rootCABuff, const char *cli_cert, const char *cli_key);
int connect(const char *host, uint16_t port, const char *rootCABuff, const char *cli_cert, const char *cli_key);int connect(IPAddress ip, uint16_t port, const char *pskIdent, const char *psKey);
int connect(const char *host, uint16_t port, const char *pskIdent, const char *psKey);void setCACert(const char *rootCA); // Set root CA certificate
void setCertificate(const char *client_ca); // Set client certificate
void setPrivateKey(const char *private_key); // Set client private key
void setPreSharedKey(const char *pskIdent, const char *psKey); // Set PSK (key in hex)
// Load certificates from Stream
bool loadCACert(Stream& stream, size_t size);
bool loadCertificate(Stream& stream, size_t size);
bool loadPrivateKey(Stream& stream, size_t size);size_t write(uint8_t data); // Write single byte
size_t write(const uint8_t *buf, size_t size); // Write buffer
int read(); // Read single byte
int read(uint8_t *buf, size_t size); // Read into buffer
int available(); // Check available bytes
int peek(); // Peek next byte
void flush(); // Flush output (no-op for UDP)uint8_t connected(); // Check connection status
void stop(); // Close connection
void setHandshakeTimeout(unsigned long timeout); // Set DTLS handshake timeoutint lastError(char *buf, const size_t size); // Get last error message
void setwriteFailTimeout(int timeout); // Set write failure timeout (ms)
void setwriteFailDelay(int delay); // Set write failure retry delay (ms)bool verify(const char* fingerprint, const char* domain_name); // Verify server certificateAuthenticates the server and negotiates an encrypted connection (similar to HTTPS in browsers).
For your own server:
- Generate a root certificate for your CA
- Generate a server certificate signed by your root CA
- Use
setCACert()with your root CA certificate
For public servers:
- Obtain the public CA certificate that signed the server's certificate
- Use
setCACert()with the public CA certificate
Adds client authentication to server authentication.
- Generate a client certificate and private key using your root CA
- Register the client certificate with your server
- Use
setCACert()for server authentication - Use
setCertificate()andsetPrivateKey()for client authentication
Simpler authentication using a shared secret key.
- Generate a random hex string (32 bytes max, commonly using MD5 or SHA)
- Create a client ID string
- Configure your server to accept the ID/key pair
- Use
setPreSharedKey(pskIdent, psKey)wherepsKeyis in hex format
Note: PSK is more secure than plain passwords because the key is never directly transmitted, and the server is also authenticated to the client.
This library supports both ESP32 Arduino 2.x and 3.x:
- ESP32 3.x: Uses public mbedTLS timing API and updated header includes
- ESP32 2.x: Uses custom timing implementation and legacy headers
The library automatically detects the ESP32 version and uses the appropriate APIs.
The library includes enhanced error handling:
- Memory Errors: On
ENOBUFSerrors, the library displays LwIP statistics and automatically retries after a delay - Write Failures: Configurable timeout and retry delay for handling temporary write failures during UDP bursts
- Error Logging: All errors include errno information for better debugging
MBEDTLS_ERR_NET_SEND_FAILED(-0x004E): Network send failed (often temporary with UDP)ENOBUFS: Out of memory in TCP/IP stack (library will retry automatically)- Connection timeouts: Adjust using
setHandshakeTimeout()
- Check DTLS support: Ensure
CONFIG_MBEDTLS_SSL_PROTO_DTLS=yin sdkconfig - Verify certificates: Ensure certificates are valid and properly formatted
- Check network: Verify WiFi connection and server accessibility
- Review logs: Enable debug logging to see detailed error messages
- The library automatically retries on memory errors
- If persistent, consider:
- Reducing buffer sizes
- Increasing FreeRTOS heap size
- Reducing concurrent connections
- UDP can experience temporary write failures during high burst traffic
- Use
setwriteFailTimeout()andsetwriteFailDelay()to handle transient errors - Default behavior: connection closes immediately on write failure
- UDP is connectionless; the library maintains a pseudo-connection state
- No guarantee of packet delivery or ordering (UDP characteristics)
- Some TCP-specific socket options are not applicable (e.g., TCP_NODELAY, SO_KEEPALIVE)
Contributions are welcome! Please feel free to submit a Pull Request.
This library is licensed under the BSD 3-Clause License. See LICENSE.txt for details.
- Original WiFiClientSecure: Copyright (c) 2016 Hristo Gochkov, Additions Copyright (C) 2017 Evandro Luis Copercini
- WiFiClientSecureUdp Fork: Copyright (c) 2020 Andre Lorbach
- mbedTLS: Copyright (c) ARM Limited and Contributors
For issues, questions, or contributions, please use the GitHub Issues page.