Add WireGuard VPN usermod (#3270)

* added wireguard VPN usermod

* add example PIO override & edit readme

* add contact information and improve usermod performance
This commit is contained in:
Aiden 2023-07-27 05:35:52 -04:00 committed by GitHub
parent b67235a7e5
commit 0ccadb246f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 177 additions and 0 deletions

View File

@ -0,0 +1,22 @@
# Example PlatformIO Project Configuration Override for WireGuard
# ------------------------------------------------------------------------------
# Copy to platformio_override.ini to activate.
# ------------------------------------------------------------------------------
# Please visit documentation: https://docs.platformio.org/page/projectconf.html
[platformio]
default_envs = WLED_ESP32-WireGuard
[env:WLED_ESP32-WireGuard]
board = esp32dev
platform = ${esp32.platform}
platform_packages = ${esp32.platform_packages}
build_unflags = ${common.build_unflags}
build_flags = ${common.build_flags_esp32}
-D WLED_RELEASE_NAME=ESP32-WireGuard
-D USERMOD_WIREGUARD
lib_deps = ${esp32.lib_deps}
https://github.com/kienvu58/WireGuard-ESP32-Arduino.git
monitor_filters = esp32_exception_decoder
board_build.partitions = ${esp32.default_partitions}
upload_speed = 921600

View File

@ -0,0 +1,19 @@
# WireGuard VPN
This usermod will connect your WLED instance to a remote WireGuard subnet.
Configuration is performed via the Usermod menu. There are no parameters to set in code!
## Installation
Copy the `platformio_override.ini` file to the root project directory, review the build options, and select the `WLED_ESP32-WireGuard` environment.
## Author
Aiden Vigue [vigue.me](https://vigue.me)
[@acvigue](https://github.com/acvigue)
aiden@vigue.me

View File

@ -0,0 +1,127 @@
#pragma once
#include <WireGuard-ESP32.h>
#include "wled.h"
class WireguardUsermod : public Usermod {
public:
void setup() { configTzTime(posix_tz, ntpServerName); }
void connected() {
if (wg.is_initialized()) {
wg.end();
}
}
void loop() {
if (millis() - lastTime > 5000) {
if (is_enabled && WLED_CONNECTED) {
if (!wg.is_initialized()) {
struct tm timeinfo;
if (getLocalTime(&timeinfo, 0)) {
if (strlen(preshared_key) < 1) {
wg.begin(local_ip, private_key, endpoint_address, public_key, endpoint_port, NULL);
} else {
wg.begin(local_ip, private_key, endpoint_address, public_key, endpoint_port, preshared_key);
}
}
}
}
lastTime = millis();
}
}
void addToJsonInfo(JsonObject& root) {
JsonObject user = root["u"];
if (user.isNull()) user = root.createNestedObject("u");
JsonArray infoArr = user.createNestedArray(F("WireGuard"));
String uiDomString;
struct tm timeinfo;
if (!getLocalTime(&timeinfo, 0)) {
uiDomString = "Time out of sync!";
} else {
if (wg.is_initialized()) {
uiDomString = "netif up!";
} else {
uiDomString = "netif down :(";
}
}
if (is_enabled) infoArr.add(uiDomString);
}
void appendConfigData() {
oappend(SET_F("addInfo('WireGuard:host',1,'Server Hostname');")); // 0 is field type, 1 is actual field
oappend(SET_F("addInfo('WireGuard:port',1,'Server Port');")); // 0 is field type, 1 is actual field
oappend(SET_F("addInfo('WireGuard:ip',1,'Device IP');")); // 0 is field type, 1 is actual field
oappend(SET_F("addInfo('WireGuard:psk',1,'Pre Shared Key (optional)');")); // 0 is field type, 1 is actual field
oappend(SET_F("addInfo('WireGuard:pem',1,'Private Key');")); // 0 is field type, 1 is actual field
oappend(SET_F("addInfo('WireGuard:pub',1,'Public Key');")); // 0 is field type, 1 is actual field
oappend(SET_F("addInfo('WireGuard:tz',1,'POSIX timezone string');")); // 0 is field type, 1 is actual field
}
void addToConfig(JsonObject& root) {
JsonObject top = root.createNestedObject(F("WireGuard"));
top[F("host")] = endpoint_address;
top[F("port")] = endpoint_port;
top[F("ip")] = local_ip.toString();
top[F("psk")] = preshared_key;
top[F("pem")] = private_key;
top[F("pub")] = public_key;
top[F("tz")] = posix_tz;
}
bool readFromConfig(JsonObject& root) {
JsonObject top = root[F("WireGuard")];
if (top["host"].isNull() || top["port"].isNull() || top["ip"].isNull() || top["pem"].isNull() || top["pub"].isNull() || top["tz"].isNull()) {
is_enabled = false;
return false;
} else {
const char* host = top["host"];
strncpy(endpoint_address, host, 100);
const char* ip_s = top["ip"];
uint8_t ip[4];
sscanf(ip_s, "%u.%u.%u.%u", &ip[0], &ip[1], &ip[2], &ip[3]);
local_ip = IPAddress(ip[0], ip[1], ip[2], ip[3]);
const char* pem = top["pem"];
strncpy(private_key, pem, 45);
const char* pub = top["pub"];
strncpy(public_key, pub, 45);
const char* tz = top["tz"];
strncpy(posix_tz, tz, 150);
endpoint_port = top["port"];
if (!top["psk"].isNull()) {
const char* psk = top["psk"];
strncpy(preshared_key, psk, 45);
}
is_enabled = true;
}
return is_enabled;
}
uint16_t getId() { return USERMOD_ID_WIREGUARD; }
private:
WireGuard wg;
char preshared_key[45];
char private_key[45];
IPAddress local_ip;
char public_key[45];
char endpoint_address[100];
char posix_tz[150];
int endpoint_port = 0;
bool is_enabled = false;
unsigned long lastTime = 0;
};

View File

@ -148,6 +148,7 @@
#define USERMOD_ID_PWM_OUTPUTS 38 //Usermod "usermod_pwm_outputs.h
#define USERMOD_ID_SHT 39 //Usermod "usermod_sht.h
#define USERMOD_ID_KLIPPER 40 // Usermod Klipper percentage
#define USERMOD_ID_WIREGUARD 41 //Usermod "wireguard.h"
//Access point behavior
#define AP_BEHAVIOR_BOOT_NO_CONN 0 //Open AP when no connection after boot

View File

@ -133,6 +133,10 @@
#include "../usermods/wizlights/wizlights.h"
#endif
#ifdef USERMOD_WIREGUARD
#include "../usermods/wireguard/wireguard.h"
#endif
#ifdef USERMOD_WORDCLOCK
#include "../usermods/usermod_v2_word_clock/usermod_v2_word_clock.h"
#endif
@ -306,6 +310,10 @@ void registerUsermods()
usermods.add(new WizLightsUsermod());
#endif
#ifdef USERMOD_WIREGUARD
usermods.add(new WireguardUsermod());
#endif
#ifdef USERMOD_WORDCLOCK
usermods.add(new WordClockUsermod());
#endif