Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
105 changes: 105 additions & 0 deletions examples/disconnect/disconnect.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
#include <WiFi.h>
#include <WireGuard-ESP32.h>
#include <WiFiUdp.h>

// WiFi configuration --- UPDATE this configuration for your WiFi AP
char ssid[] = "ssid";
char password[] = "password";

// WireGuard configuration --- UPDATE this configuration from JSON
char private_key[] = "(Private Key) "; // [Interface] PrivateKey
IPAddress local_ip(1,2,3,4); // [Interface] Address
char public_key[] = "(Public Key)"; // [Peer] PublicKey
char endpoint_address[] = "link.arc.soracom.io"; // [Peer] Endpoint
int endpoint_port = 11010; // [Peer] Endpoint

const char host_inside_vpn[] = "10.0.0.1";
const char host_outside_vpn[] = "192.168.2.1";

static constexpr const uint32_t UPDATE_INTERVAL_MS = 5000;

static WireGuard wg;

void setup()
{
esp_log_level_set("*", ESP_LOG_DEBUG);

Serial.begin(115200);
Serial.println("Connecting to the AP...");
WiFi.begin(ssid, password);
while( !WiFi.isConnected() ) {
delay(1000);
}

Serial.println("Adjusting system time...");
configTime(9 * 60 * 60, 0, "ntp.jst.mfeed.ad.jp", "ntp.nict.jp", "time.google.com");

Serial.println("WiFi Connected.");
}

void loop()
{
static uint64_t send_count = 0;
static uint64_t loop_count = 0;
if( loop_count % 5 == 0) {
if( !wg.is_initialized() ) {
Serial.println("Initializing WG interface...");
if( !wg.begin(
local_ip,
private_key,
endpoint_address,
public_key,
endpoint_port) ) {
Serial.println("Failed to initialize WG interface.");
}
}
else {
Serial.println("Shutting down WG interface...");
wg.end();
}
}
loop_count++;

WiFiUDP client;
const char* host = wg.is_initialized() ? host_inside_vpn : host_outside_vpn;
if( !client.beginPacket(host, 23080) ) {
Serial.println("Failed to begin packet...");
delay(5000);
return;
}

uint64_t uptime_msec = millis();
uint8_t buffer[16];
buffer[ 0] = (uptime_msec >> 0) & 0xff;
buffer[ 1] = (uptime_msec >> 8) & 0xff;
buffer[ 2] = (uptime_msec >> 16) & 0xff;
buffer[ 3] = (uptime_msec >> 24) & 0xff;
buffer[ 4] = (uptime_msec >> 32) & 0xff;
buffer[ 5] = (uptime_msec >> 40) & 0xff;
buffer[ 6] = (uptime_msec >> 48) & 0xff;
buffer[ 7] = (uptime_msec >> 56) & 0xff;
buffer[ 8] = (send_count >> 0) & 0xff;
buffer[ 9] = (send_count >> 8) & 0xff;
buffer[10] = (send_count >> 16) & 0xff;
buffer[11] = (send_count >> 24) & 0xff;
buffer[12] = (send_count >> 32) & 0xff;
buffer[13] = (send_count >> 40) & 0xff;
buffer[14] = (send_count >> 48) & 0xff;
buffer[15] = (send_count >> 56) & 0xff;

Serial.printf("Sending uptime %lu [ms], count=%d\r\n", uptime_msec, send_count);
client.write(buffer, sizeof(buffer));
client.endPacket();

send_count++;

IPAddress result;
if( WiFi.hostByName("www.google.com", result) ) {
Serial.printf("hostByName: %s\r\n", result.toString().c_str());
}
else {
Serial.printf("hostByName failed\r\n");
}

delay(UPDATE_INTERVAL_MS);
}
6 changes: 5 additions & 1 deletion src/WireGuard-ESP32.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@

class WireGuard
{
private:
bool _is_initialized = false;
public:
void begin(const IPAddress& localIP, const char* privateKey, const char* remotePeerAddress, const char* remotePeerPublicKey, uint16_t remotePeerPort);
bool begin(const IPAddress& localIP, const char* privateKey, const char* remotePeerAddress, const char* remotePeerPublicKey, uint16_t remotePeerPort);
void end();
bool is_initialized() const { return this->_is_initialized; }
};
78 changes: 58 additions & 20 deletions src/WireGuard.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,14 @@
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_system.h"
#include "esp_log.h"

#include "lwip/err.h"
#include "lwip/sys.h"
#include "lwip/ip.h"
#include "lwip/netdb.h"

#include "esp32-hal-log.h"

extern "C" {
#include "wireguardif.h"
#include "wireguard-platform.h"
Expand All @@ -23,11 +24,12 @@ extern "C" {
// Wireguard instance
static struct netif wg_netif_struct = {0};
static struct netif *wg_netif = NULL;
static struct netif *previous_default_netif = NULL;
static uint8_t wireguard_peer_index = WIREGUARDIF_INVALID_INDEX;

#define TAG "WireGuard"
#define TAG "[WireGuard] "

void WireGuard::begin(const IPAddress& localIP, const char* privateKey, const char* remotePeerAddress, const char* remotePeerPublicKey, uint16_t remotePeerPort) {
bool WireGuard::begin(const IPAddress& localIP, const char* privateKey, const char* remotePeerAddress, const char* remotePeerPublicKey, uint16_t remotePeerPort) {
struct wireguardif_init_data wg;
struct wireguardif_peer peer;
ip_addr_t ipaddr = IPADDR4_INIT(static_cast<uint32_t>(localIP));
Expand All @@ -45,24 +47,10 @@ void WireGuard::begin(const IPAddress& localIP, const char* privateKey, const ch

wg.bind_netif = NULL;

// Register the new WireGuard network interface with lwIP
wg_netif = netif_add(&wg_netif_struct, ip_2_ip4(&ipaddr), ip_2_ip4(&netmask), ip_2_ip4(&gateway), &wg, &wireguardif_init, &ip_input);

// Mark the interface as administratively up, link up flag is set automatically when peer connects
netif_set_up(wg_netif);

// Initialise the first WireGuard peer structure
wireguardif_peer_init(&peer);
peer.public_key = remotePeerPublicKey;
peer.preshared_key = NULL;
// Allow all IPs through tunnel
{
ip_addr_t allowed_ip = IPADDR4_INIT_BYTES(0, 0, 0, 0);
peer.allowed_ip = allowed_ip;
ip_addr_t allowed_mask = IPADDR4_INIT_BYTES(0, 0, 0, 0);
peer.allowed_mask = allowed_mask;
}
// If we know the endpoint's address can add here
bool success_get_endpoint_ip = false;
for(int retry = 0; retry < 5; retry++) {
ip_addr_t endpoint_ip = IPADDR4_INIT_BYTES(0, 0, 0, 0);
struct addrinfo *res = NULL;
Expand All @@ -73,19 +61,44 @@ void WireGuard::begin(const IPAddress& localIP, const char* privateKey, const ch
vTaskDelay(pdMS_TO_TICKS(2000));
continue;
}
success_get_endpoint_ip = true;
struct in_addr addr4 = ((struct sockaddr_in *) (res->ai_addr))->sin_addr;
inet_addr_to_ip4addr(ip_2_ip4(&endpoint_ip), &addr4);
lwip_freeaddrinfo(res);

peer.endpoint_ip = endpoint_ip;
ESP_LOGI(TAG, "%s is %3d.%3d.%3d.%3d"
log_i(TAG "%s is %3d.%3d.%3d.%3d"
, remotePeerAddress
, (endpoint_ip.u_addr.ip4.addr >> 0) & 0xff
, (endpoint_ip.u_addr.ip4.addr >> 8) & 0xff
, (endpoint_ip.u_addr.ip4.addr >> 16) & 0xff
, (endpoint_ip.u_addr.ip4.addr >> 24) & 0xff
);
break;
}
if( !success_get_endpoint_ip ) {
log_e(TAG "failed to get endpoint ip.");
return false;
}
// Register the new WireGuard network interface with lwIP
wg_netif = netif_add(&wg_netif_struct, ip_2_ip4(&ipaddr), ip_2_ip4(&netmask), ip_2_ip4(&gateway), &wg, &wireguardif_init, &ip_input);
if( wg_netif == nullptr ) {
log_e(TAG "failed to initialize WG netif.");
return false;
}
// Mark the interface as administratively up, link up flag is set automatically when peer connects
netif_set_up(wg_netif);

peer.public_key = remotePeerPublicKey;
peer.preshared_key = NULL;
// Allow all IPs through tunnel
{
ip_addr_t allowed_ip = IPADDR4_INIT_BYTES(0, 0, 0, 0);
peer.allowed_ip = allowed_ip;
ip_addr_t allowed_mask = IPADDR4_INIT_BYTES(0, 0, 0, 0);
peer.allowed_mask = allowed_mask;
}

peer.endport_port = remotePeerPort;

// Initialize the platform
Expand All @@ -94,9 +107,34 @@ void WireGuard::begin(const IPAddress& localIP, const char* privateKey, const ch
wireguardif_add_peer(wg_netif, &peer, &wireguard_peer_index);
if ((wireguard_peer_index != WIREGUARDIF_INVALID_INDEX) && !ip_addr_isany(&peer.endpoint_ip)) {
// Start outbound connection to peer
ESP_LOGI(TAG, "connecting wireguard...");
log_i(TAG "connecting wireguard...");
wireguardif_connect(wg_netif, wireguard_peer_index);
// Save the current default interface for restoring when shutting down the WG interface.
previous_default_netif = netif_default;
// Set default interface to WG device.
netif_set_default(wg_netif);
}

this->_is_initialized = true;
return true;
}

void WireGuard::end() {
if( !this->_is_initialized ) return;

// Restore the default interface.
netif_set_default(previous_default_netif);
previous_default_netif = nullptr;
// Disconnect the WG interface.
wireguardif_disconnect(wg_netif, wireguard_peer_index);
// Remove peer from the WG interface
wireguardif_remove_peer(wg_netif, wireguard_peer_index);
wireguard_peer_index = WIREGUARDIF_INVALID_INDEX;
// Shutdown the wireguard interface.
wireguardif_shutdown(wg_netif);
// Remove the WG interface;
netif_remove(wg_netif);
wg_netif = nullptr;

this->_is_initialized = false;
}
5 changes: 5 additions & 0 deletions src/wireguard-platform.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

static struct mbedtls_ctr_drbg_context random_context;
static struct mbedtls_entropy_context entropy_context;
static bool is_platform_initialized = false;

static int entropy_hw_random_source( void *data, unsigned char *output, size_t len, size_t *olen ) {
esp_fill_random(output, len);
Expand All @@ -22,10 +23,14 @@ static int entropy_hw_random_source( void *data, unsigned char *output, size_t l
}

void wireguard_platform_init() {
if( is_platform_initialized ) return;

mbedtls_entropy_init(&entropy_context);
mbedtls_ctr_drbg_init(&random_context);
mbedtls_entropy_add_source(&entropy_context, entropy_hw_random_source, NULL, 134, MBEDTLS_ENTROPY_SOURCE_STRONG);
mbedtls_ctr_drbg_seed(&random_context, mbedtls_entropy_func, &entropy_context, NULL, 0);

is_platform_initialized = true;
}

void wireguard_random_bytes(void *bytes, size_t size) {
Expand Down
Loading