WireGuard for esp8266 (#6365)

This commit is contained in:
Simone Rossetto 2024-03-24 23:21:04 +01:00 committed by GitHub
parent 3801462589
commit bd8f9db037
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 139 additions and 92 deletions

View file

@ -22,7 +22,7 @@ CONF_PEER_ALLOWED_IPS = "peer_allowed_ips"
CONF_PEER_PERSISTENT_KEEPALIVE = "peer_persistent_keepalive" CONF_PEER_PERSISTENT_KEEPALIVE = "peer_persistent_keepalive"
CONF_REQUIRE_CONNECTION_TO_PROCEED = "require_connection_to_proceed" CONF_REQUIRE_CONNECTION_TO_PROCEED = "require_connection_to_proceed"
DEPENDENCIES = ["time", "esp32"] DEPENDENCIES = ["time"]
CODEOWNERS = ["@lhoracek", "@droscy", "@thomas0bernard"] CODEOWNERS = ["@lhoracek", "@droscy", "@thomas0bernard"]
# The key validation regex has been described by Jason Donenfeld himself # The key validation regex has been described by Jason Donenfeld himself
@ -120,7 +120,7 @@ async def to_code(config):
# the '+1' modifier is relative to the device's own address that will # the '+1' modifier is relative to the device's own address that will
# be automatically added to the provided list. # be automatically added to the provided list.
cg.add_build_flag(f"-DCONFIG_WIREGUARD_MAX_SRC_IPS={len(allowed_ips) + 1}") cg.add_build_flag(f"-DCONFIG_WIREGUARD_MAX_SRC_IPS={len(allowed_ips) + 1}")
cg.add_library("droscy/esp_wireguard", "0.3.2") cg.add_library("droscy/esp_wireguard", "0.4.0")
await cg.register_component(var, config) await cg.register_component(var, config)

View file

@ -1,7 +1,5 @@
#include "wireguard.h" #include "wireguard.h"
#ifdef USE_ESP32
#include <cinttypes> #include <cinttypes>
#include <ctime> #include <ctime>
#include <functional> #include <functional>
@ -11,26 +9,20 @@
#include "esphome/core/time.h" #include "esphome/core/time.h"
#include "esphome/components/network/util.h" #include "esphome/components/network/util.h"
#include <esp_err.h>
#include <esp_wireguard.h> #include <esp_wireguard.h>
#include <esp_wireguard_err.h>
// includes for resume/suspend wdt
#if defined(USE_ESP_IDF)
#include <esp_task_wdt.h>
#if ESP_IDF_VERSION_MAJOR >= 5
#include <spi_flash_mmap.h>
#endif
#elif defined(USE_ARDUINO)
#include <esp32-hal.h>
#endif
namespace esphome { namespace esphome {
namespace wireguard { namespace wireguard {
static const char *const TAG = "wireguard"; static const char *const TAG = "wireguard";
static const char *const LOGMSG_PEER_STATUS = "WireGuard remote peer is %s (latest handshake %s)"; /*
* Cannot use `static const char*` for LOGMSG_PEER_STATUS on esp8266 platform
* because log messages in `Wireguard::update()` method fail.
*/
#define LOGMSG_PEER_STATUS "WireGuard remote peer is %s (latest handshake %s)"
static const char *const LOGMSG_ONLINE = "online"; static const char *const LOGMSG_ONLINE = "online";
static const char *const LOGMSG_OFFLINE = "offline"; static const char *const LOGMSG_OFFLINE = "offline";
@ -257,20 +249,13 @@ void Wireguard::start_connection_() {
} }
ESP_LOGD(TAG, "starting WireGuard connection..."); ESP_LOGD(TAG, "starting WireGuard connection...");
/*
* The function esp_wireguard_connect() contains a DNS resolution
* that could trigger the watchdog, so before it we suspend (or
* increase the time, it depends on the platform) the wdt and
* then we resume the normal timeout.
*/
suspend_wdt();
ESP_LOGV(TAG, "executing esp_wireguard_connect");
this->wg_connected_ = esp_wireguard_connect(&(this->wg_ctx_)); this->wg_connected_ = esp_wireguard_connect(&(this->wg_ctx_));
resume_wdt();
if (this->wg_connected_ == ESP_OK) { if (this->wg_connected_ == ESP_OK) {
ESP_LOGI(TAG, "WireGuard connection started"); ESP_LOGI(TAG, "WireGuard connection started");
} else if (this->wg_connected_ == ESP_ERR_RETRY) {
ESP_LOGD(TAG, "WireGuard is waiting for endpoint IP address to be available");
return;
} else { } else {
ESP_LOGW(TAG, "cannot start WireGuard connection, error code %d", this->wg_connected_); ESP_LOGW(TAG, "cannot start WireGuard connection, error code %d", this->wg_connected_);
return; return;
@ -300,44 +285,7 @@ void Wireguard::stop_connection_() {
} }
} }
void suspend_wdt() {
#if defined(USE_ESP_IDF)
#if ESP_IDF_VERSION_MAJOR >= 5
ESP_LOGV(TAG, "temporarily increasing wdt timeout to 15000 ms");
esp_task_wdt_config_t wdtc;
wdtc.timeout_ms = 15000;
wdtc.idle_core_mask = 0;
wdtc.trigger_panic = false;
esp_task_wdt_reconfigure(&wdtc);
#else
ESP_LOGV(TAG, "temporarily increasing wdt timeout to 15 seconds");
esp_task_wdt_init(15, false);
#endif
#elif defined(USE_ARDUINO)
ESP_LOGV(TAG, "temporarily disabling the wdt");
disableLoopWDT();
#endif
}
void resume_wdt() {
#if defined(USE_ESP_IDF)
#if ESP_IDF_VERSION_MAJOR >= 5
wdtc.timeout_ms = CONFIG_ESP_TASK_WDT_TIMEOUT_S * 1000;
esp_task_wdt_reconfigure(&wdtc);
ESP_LOGV(TAG, "wdt resumed with %" PRIu32 " ms timeout", wdtc.timeout_ms);
#else
esp_task_wdt_init(CONFIG_ESP_TASK_WDT_TIMEOUT_S, false);
ESP_LOGV(TAG, "wdt resumed with %d seconds timeout", CONFIG_ESP_TASK_WDT_TIMEOUT_S);
#endif
#elif defined(USE_ARDUINO)
enableLoopWDT();
ESP_LOGV(TAG, "wdt resumed");
#endif
}
std::string mask_key(const std::string &key) { return (key.substr(0, 5) + "[...]="); } std::string mask_key(const std::string &key) { return (key.substr(0, 5) + "[...]="); }
} // namespace wireguard } // namespace wireguard
} // namespace esphome } // namespace esphome
#endif // USE_ESP32

View file

@ -1,7 +1,5 @@
#pragma once #pragma once
#ifdef USE_ESP32
#include <ctime> #include <ctime>
#include <vector> #include <vector>
#include <tuple> #include <tuple>
@ -172,5 +170,3 @@ template<typename... Ts> class WireguardDisableAction : public Action<Ts...>, pu
} // namespace wireguard } // namespace wireguard
} // namespace esphome } // namespace esphome
#endif // USE_ESP32

View file

@ -94,6 +94,7 @@ lib_deps =
ESP8266mDNS ; mdns (Arduino built-in) ESP8266mDNS ; mdns (Arduino built-in)
DNSServer ; captive_portal (Arduino built-in) DNSServer ; captive_portal (Arduino built-in)
crankyoldgit/IRremoteESP8266@~2.8.4 ; heatpumpir crankyoldgit/IRremoteESP8266@~2.8.4 ; heatpumpir
droscy/esp_wireguard@0.4.0 ; wireguard
build_flags = build_flags =
${common:arduino.build_flags} ${common:arduino.build_flags}
-Wno-nonnull-compare -Wno-nonnull-compare
@ -123,7 +124,7 @@ lib_deps =
DNSServer ; captive_portal (Arduino built-in) DNSServer ; captive_portal (Arduino built-in)
esphome/ESP32-audioI2S@2.0.7 ; i2s_audio esphome/ESP32-audioI2S@2.0.7 ; i2s_audio
crankyoldgit/IRremoteESP8266@~2.8.4 ; heatpumpir crankyoldgit/IRremoteESP8266@~2.8.4 ; heatpumpir
droscy/esp_wireguard@0.3.2 ; wireguard droscy/esp_wireguard@0.4.0 ; wireguard
build_flags = build_flags =
${common:arduino.build_flags} ${common:arduino.build_flags}
-DUSE_ESP32 -DUSE_ESP32
@ -142,7 +143,7 @@ framework = espidf
lib_deps = lib_deps =
${common:idf.lib_deps} ${common:idf.lib_deps}
espressif/esp32-camera@1.0.0 ; esp32_camera espressif/esp32-camera@1.0.0 ; esp32_camera
droscy/esp_wireguard@0.3.2 ; wireguard droscy/esp_wireguard@0.4.0 ; wireguard
build_flags = build_flags =
${common:idf.build_flags} ${common:idf.build_flags}
-Wno-nonnull-compare -Wno-nonnull-compare

View file

@ -1,36 +1,14 @@
---
esphome:
name: test10
build_path: build/test10
esp32:
board: esp32doit-devkit-v1
framework:
type: arduino
wifi: wifi:
ssid: "MySSID1" ssid: "MySSID1"
password: "password1" password: "password1"
reboot_timeout: 3min
power_save_mode: high
network: network:
enable_ipv6: true enable_ipv6: true
logger:
level: VERBOSE
api:
reboot_timeout: 10min
web_server:
version: 3
time: time:
- platform: sntp - platform: sntp
wireguard: wireguard:
id: vpn
address: 172.16.34.100 address: 172.16.34.100
netmask: 255.255.255.0 netmask: 255.255.255.0
# NEVER use the following keys for your vpn, they are now public! # NEVER use the following keys for your vpn, they are now public!

View file

@ -0,0 +1,62 @@
wifi:
ssid: "MySSID1"
password: "password1"
network:
enable_ipv6: true
time:
- platform: sntp
wireguard:
address: 172.16.34.100
netmask: 255.255.255.0
# NEVER use the following keys for your vpn, they are now public!
private_key: wPBMxtNYH3mChicrbpsRpZIasIdPq3yZuthn23FbGG8=
peer_public_key: Hs2JfikvYU03/Kv3YoAs1hrUIPPTEkpsZKSPUljE9yc=
peer_preshared_key: 20fjM5GRnSolGPC5SRj9ljgIUyQfruv0B0bvLl3Yt60=
peer_endpoint: wg.server.example
peer_persistent_keepalive: 25s
peer_allowed_ips:
- 172.16.34.0/24
- 192.168.4.0/24
binary_sensor:
- platform: wireguard
status:
name: 'WireGuard Status'
enabled:
name: 'WireGuard Enabled'
sensor:
- platform: wireguard
latest_handshake:
name: 'WireGuard Latest Handshake'
text_sensor:
- platform: wireguard
address:
name: 'WireGuard Address'
button:
- platform: template
name: 'Toggle WireGuard'
entity_category: config
on_press:
- if:
condition: wireguard.enabled
then:
- wireguard.disable:
else:
- wireguard.enable:
- platform: template
name: 'Log WireGuard status'
entity_category: config
on_press:
- if:
condition: wireguard.peer_online
then:
- logger.log: 'wireguard remote peer is online'
else:
- logger.log: 'wireguard remote peer is offline'

View file

@ -0,0 +1,62 @@
wifi:
ssid: "MySSID1"
password: "password1"
network:
enable_ipv6: true
time:
- platform: sntp
wireguard:
address: 172.16.34.100
netmask: 255.255.255.0
# NEVER use the following keys for your vpn, they are now public!
private_key: wPBMxtNYH3mChicrbpsRpZIasIdPq3yZuthn23FbGG8=
peer_public_key: Hs2JfikvYU03/Kv3YoAs1hrUIPPTEkpsZKSPUljE9yc=
peer_preshared_key: 20fjM5GRnSolGPC5SRj9ljgIUyQfruv0B0bvLl3Yt60=
peer_endpoint: wg.server.example
peer_persistent_keepalive: 25s
peer_allowed_ips:
- 172.16.34.0/24
- 192.168.4.0/24
binary_sensor:
- platform: wireguard
status:
name: 'WireGuard Status'
enabled:
name: 'WireGuard Enabled'
sensor:
- platform: wireguard
latest_handshake:
name: 'WireGuard Latest Handshake'
text_sensor:
- platform: wireguard
address:
name: 'WireGuard Address'
button:
- platform: template
name: 'Toggle WireGuard'
entity_category: config
on_press:
- if:
condition: wireguard.enabled
then:
- wireguard.disable:
else:
- wireguard.enable:
- platform: template
name: 'Log WireGuard status'
entity_category: config
on_press:
- if:
condition: wireguard.peer_online
then:
- logger.log: 'wireguard remote peer is online'
else:
- logger.log: 'wireguard remote peer is offline'