Big code refactoring #10

Merged
Sirherobrine23 merged 15 commits from code_refactoring into main 2024-03-15 04:08:27 +00:00
19 changed files with 657 additions and 128 deletions
Showing only changes of commit fb883a4a5d - Show all commits

@ -1,11 +0,0 @@
version: 2
updates:
- directory: /
package-ecosystem: "github-actions"
schedule:
interval: daily
- directory: /
package-ecosystem: npm
schedule:
interval: monthly

22
.vscode/c_cpp_properties.json vendored Normal file

@ -0,0 +1,22 @@
{
"configurations": [
{
"name": "Mac",
"includePath": [
"${workspaceFolder}/node_modules/node-addon-api",
"/usr/local/include/node",
"${workspaceFolder}/**",
"${workspaceFolder}/addon"
],
"defines": [],
"macFrameworkPath": [
"/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks"
],
"compilerPath": "/usr/bin/clang",
"cStandard": "c17",
"cppStandard": "c++17",
"intelliSenseMode": "macos-clang-x64"
}
],
"version": 4
}

66
.vscode/settings.json vendored

@ -23,8 +23,72 @@
"PATH": "${workspaceFolder}/node_modules/.bin:${env:PATH}"
},
"files.associations": {
"*.dsc": "ini",
"*.gyp": "python",
"random": "cpp",
"limits": "cpp",
"xstring": "cpp"
"xstring": "cpp",
"__bit_reference": "cpp",
"__bits": "cpp",
"__config": "cpp",
"__debug": "cpp",
"__errc": "cpp",
"__hash_table": "cpp",
"__locale": "cpp",
"__mutex_base": "cpp",
"__node_handle": "cpp",
"__nullptr": "cpp",
"__split_buffer": "cpp",
"__string": "cpp",
"__threading_support": "cpp",
"__tree": "cpp",
"__tuple": "cpp",
"array": "cpp",
"atomic": "cpp",
"bitset": "cpp",
"cctype": "cpp",
"chrono": "cpp",
"clocale": "cpp",
"cmath": "cpp",
"compare": "cpp",
"complex": "cpp",
"concepts": "cpp",
"cstdarg": "cpp",
"cstddef": "cpp",
"cstdint": "cpp",
"cstdio": "cpp",
"cstdlib": "cpp",
"cstring": "cpp",
"ctime": "cpp",
"cwchar": "cpp",
"cwctype": "cpp",
"exception": "cpp",
"initializer_list": "cpp",
"ios": "cpp",
"iosfwd": "cpp",
"iostream": "cpp",
"istream": "cpp",
"locale": "cpp",
"map": "cpp",
"memory": "cpp",
"mutex": "cpp",
"new": "cpp",
"numeric": "cpp",
"optional": "cpp",
"ostream": "cpp",
"ratio": "cpp",
"sstream": "cpp",
"stdexcept": "cpp",
"streambuf": "cpp",
"string": "cpp",
"string_view": "cpp",
"system_error": "cpp",
"tuple": "cpp",
"type_traits": "cpp",
"typeinfo": "cpp",
"unordered_map": "cpp",
"variant": "cpp",
"vector": "cpp",
"algorithm": "cpp"
}
}

@ -0,0 +1,22 @@
#include "wginterface.hh"
#include <string>
std::string getWireguardVersion() {
return "";
}
void IpManeger::SetInInterface(std::string interfaceName) {
throw std::string("Use userspace module");
}
void WireguardConfig::setWireguardConfig() {
throw std::string("Use userspace module");
}
void WireguardConfig::getWireguardConfig() {
throw std::string("Use userspace module");
}
void WireguardDevices::deleteInterface(std::string wgName) {
throw std::string("Use userspace module");
}
void WireguardDevices::getInterfaces() {}

@ -1,8 +1,6 @@
#include "wgkeys.hh"
#include <errno.h>
#include <assert.h>
#include <fcntl.h>
#include <iostream>
#include <random>
#include <string.h>
@ -15,20 +13,23 @@
static void encode_base64(char dest[4], const uint8_t src[3]) {
const uint8_t input[] = {
static_cast<uint8_t>((src[0] >> 2) & 63),
static_cast<uint8_t>(((src[0] << 4) | (src[1] >> 4)) & 63),
static_cast<uint8_t>(((src[1] << 2) | (src[2] >> 6)) & 63),
static_cast<uint8_t>(src[2] & 63)
};
static_cast<uint8_t>((src[0] >> 2) & 63),
static_cast<uint8_t>(((src[0] << 4) | (src[1] >> 4)) & 63),
static_cast<uint8_t>(((src[1] << 2) | (src[2] >> 6)) & 63),
static_cast<uint8_t>(src[2] & 63)};
unsigned int i;
for (i = 0; i < 4; ++i) dest[i] = input[i] + 'A' + (((25 - input[i]) >> 8) & 6) - (((51 - input[i]) >> 8) & 75) - (((61 - input[i]) >> 8) & 15) + (((62 - input[i]) >> 8) & 3);
for (i = 0; i < 4; ++i)
dest[i] = input[i] + 'A' + (((25 - input[i]) >> 8) & 6) -
(((51 - input[i]) >> 8) & 75) - (((61 - input[i]) >> 8) & 15) +
(((62 - input[i]) >> 8) & 3);
}
void keyToBase64(wg_key_b64_string base64, const wg_key key) {
unsigned int i;
for (i = 0; i < 32 / 3; ++i) encode_base64(&base64[i * 4], &key[i * 3]);
const uint8_t tempKey[3] = { key[i * 3 + 0], key[i * 3 + 1], 0 };
for (i = 0; i < 32 / 3; ++i)
encode_base64(&base64[i * 4], &key[i * 3]);
const uint8_t tempKey[3] = {key[i * 3 + 0], key[i * 3 + 1], 0};
encode_base64(&base64[i * 4], tempKey);
base64[sizeof(wg_key_b64_string) - 2] = '=';
base64[sizeof(wg_key_b64_string) - 1] = '\0';
@ -38,19 +39,28 @@ static int decodeBase64(const char src[4]) {
int val = 0;
unsigned int i;
for (i = 0; i < 4; ++i) val |= (-1 + ((((('A' - 1) - src[i]) & (src[i] - ('Z' + 1))) >> 8) & (src[i] - 64)) + ((((('a' - 1) - src[i]) & (src[i] - ('z' + 1))) >> 8) & (src[i] - 70)) + ((((('0' - 1) - src[i]) & (src[i] - ('9' + 1))) >> 8) & (src[i] + 5)) + ((((('+' - 1) - src[i]) & (src[i] - ('+' + 1))) >> 8) & 63) + ((((('/' - 1) - src[i]) & (src[i] - ('/' + 1))) >> 8) & 64)) << (18 - 6 * i);
for (i = 0; i < 4; ++i)
val |=
(-1 +
((((('A' - 1) - src[i]) & (src[i] - ('Z' + 1))) >> 8) &
(src[i] - 64)) +
((((('a' - 1) - src[i]) & (src[i] - ('z' + 1))) >> 8) &
(src[i] - 70)) +
((((('0' - 1) - src[i]) & (src[i] - ('9' + 1))) >> 8) & (src[i] + 5)) +
((((('+' - 1) - src[i]) & (src[i] - ('+' + 1))) >> 8) & 63) +
((((('/' - 1) - src[i]) & (src[i] - ('/' + 1))) >> 8) & 64))
<< (18 - 6 * i);
return val;
}
#ifdef _WIN32
static volatile void * (*memset_func)(void *, int, size_t) = (volatile void * (*)(void *, int, size_t))&memset;
void memzero_explicit(void *s, size_t count) {
memset_func(s, 0, count);
}
static volatile void *(*memset_func)(void *, int, size_t) =
(volatile void *(*)(void *, int, size_t)) & memset;
void memzero_explicit(void *s, size_t count) { memset_func(s, 0, count); }
#else
static __attribute__((noinline)) void memzero_explicit(void *s, size_t count) {
memset(s, 0, count);
__asm__ __volatile__("": :"r"(s) :"memory");
__asm__ __volatile__("" : : "r"(s) : "memory");
}
#endif
@ -109,21 +119,25 @@ static void pack(uint8_t *o, const fe n) {
static void add(fe o, const fe a, const fe b) {
int i;
for (i = 0; i < 16; ++i) o[i] = a[i] + b[i];
for (i = 0; i < 16; ++i)
o[i] = a[i] + b[i];
}
static void subtract(fe o, const fe a, const fe b) {
int i;
for (i = 0; i < 16; ++i) o[i] = a[i] - b[i];
for (i = 0; i < 16; ++i)
o[i] = a[i] - b[i];
}
static void multmod(fe o, const fe a, const fe b) {
int i, j;
int64_t t[31] = { 0 };
int64_t t[31] = {0};
for (i = 0; i < 16; ++i) {
for (j = 0; j < 16; ++j) t[i + j] += a[i] * b[j];
for (j = 0; j < 16; ++j)
t[i + j] += a[i] * b[j];
}
for (i = 0; i < 15; ++i) t[i] += 38 * t[i + 16];
for (i = 0; i < 15; ++i)
t[i] += 38 * t[i + 16];
memcpy(o, t, sizeof(fe));
carry(o);
carry(o);
@ -136,27 +150,39 @@ static void invert(fe o, const fe i) {
memcpy(c, i, sizeof(c));
for (a = 253; a >= 0; --a) {
multmod(c, c, c);
if (a != 2 && a != 4) multmod(c, c, i);
if (a != 2 && a != 4)
multmod(c, c, i);
}
memcpy(o, c, sizeof(fe));
memzero_explicit(c, sizeof(c));
}
void wgKeys::generatePreshared(wg_key preshared_key) {
#if _WIN32 || defined(__CYGWIN__)
#if _WIN32 || defined(__CYGWIN__)
HCRYPTPROV hCryptProv;
BOOL winStatus;
if ((winStatus = CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))) winStatus = CryptGenRandom(hCryptProv, sizeof(wg_key), (BYTE*)preshared_key);
if ((winStatus = CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL,
CRYPT_VERIFYCONTEXT)))
winStatus =
CryptGenRandom(hCryptProv, sizeof(wg_key), (BYTE *)preshared_key);
CryptReleaseContext(hCryptProv, 0);
if (winStatus) return;
if (winStatus)
return;
#elif defined(__OpenBSD__) || (defined(__APPLE__) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_12) || (defined(__GLIBC__) && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 25)))
if (!getentropy(preshared_key, sizeof(wg_key))) return;
#elif defined(__OpenBSD__) || \
(defined(__APPLE__) && \
MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_12) || \
(defined(__GLIBC__) && \
(__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 25)))
if (!getentropy(preshared_key, sizeof(wg_key)))
return;
#elif defined(__NR_getrandom) && defined(__linux__)
if (syscall(__NR_getrandom, preshared_key, sizeof(wg_key), 0) == sizeof(wg_key)) return;
#elif defined(__NR_getrandom) && defined(__linux__)
if (syscall(__NR_getrandom, preshared_key, sizeof(wg_key), 0) ==
sizeof(wg_key))
return;
#elif __linux__ || _ANDROID__ || __termux__
#elif __linux__ || _ANDROID__ || __termux__
size_t ret, i;
int fd;
fd = open("/dev/urandom", O_RDONLY);
@ -167,7 +193,7 @@ void wgKeys::generatePreshared(wg_key preshared_key) {
}
close(fd);
return;
#endif
#endif
std::random_device rd;
for (uint8_t i = 0; i < sizeof(wg_key); ++i) {
@ -191,7 +217,7 @@ void wgKeys::generatePrivate(wg_key private_key) {
void wgKeys::generatePublic(wg_key public_key, const wg_key private_key) {
int i, r;
uint8_t z[32];
fe a = { 1 }, b = { 9 }, c = { 0 }, d = { 1 }, e, f;
fe a = {1}, b = {9}, c = {0}, d = {1}, e, f;
memcpy(z, private_key, sizeof(z));
clamp_key(z);
@ -212,12 +238,12 @@ void wgKeys::generatePublic(wg_key public_key, const wg_key private_key) {
subtract(a, a, c);
multmod(b, a, a);
subtract(c, d, f);
const fe abc = { 0xdb41, 1 };
const fe abc = {0xdb41, 1};
multmod(a, c, abc);
add(a, a, d);
multmod(c, c, a);
multmod(a, d, f);
const fe abc2 = { 9 };
const fe abc2 = {9};
multmod(d, b, abc2);
multmod(b, e, e);
cswap(a, b, r);
@ -237,8 +263,7 @@ void wgKeys::generatePublic(wg_key public_key, const wg_key private_key) {
memzero_explicit(f, sizeof(f));
}
bool key_is_zero(const uint8_t key[32])
{
bool key_is_zero(const uint8_t key[32]) {
volatile uint8_t acc = 0;
for (unsigned int i = 0; i < 32; ++i) {
@ -250,7 +275,10 @@ bool key_is_zero(const uint8_t key[32])
void wgKeys::stringToKey(wg_key key, std::string keyBase64) {
auto base64 = keyBase64.c_str();
if (keyBase64.length() != B64_WG_KEY_LENGTH || base64[B64_WG_KEY_LENGTH - 1] != '=') throw std::string("invalid key, length: ").append(std::to_string(keyBase64.length()));
if (keyBase64.length() != B64_WG_KEY_LENGTH ||
base64[B64_WG_KEY_LENGTH - 1] != '=')
throw std::string("invalid key, length: ")
.append(std::to_string(keyBase64.length()));
unsigned int i;
int val;
@ -263,24 +291,28 @@ void wgKeys::stringToKey(wg_key key, std::string keyBase64) {
key[i * 3 + 1] = (val >> 8) & 0xff;
key[i * 3 + 2] = val & 0xff;
}
const char tempDecode[4] = {base64[i * 4 + 0], base64[i * 4 + 1], base64[i * 4 + 2], 'A'};
const char tempDecode[4] = {base64[i * 4 + 0], base64[i * 4 + 1],
base64[i * 4 + 2], 'A'};
val = decodeBase64(tempDecode);
ret |= ((uint32_t)val >> 31) | (val & 0xff);
key[i * 3 + 0] = (val >> 16) & 0xff;
key[i * 3 + 1] = (val >> 8) & 0xff;
int status = EINVAL & ~((ret - 1) >> 8);
if (status != 0) throw std::string("Cannot decode key, ret code: ").append(std::to_string(status));
if (status != 0)
throw std::string("Cannot decode key, ret code: ")
.append(std::to_string(status));
}
std::string wgKeys::toString(const wg_key key) {
wg_key_b64_string base64;
unsigned int i;
for (i = 0; i < 32 / 3; ++i) encode_base64(&base64[i * 4], &key[i * 3]);
const uint8_t tempKey[3] = { key[i * 3 + 0], key[i * 3 + 1], 0 };
for (i = 0; i < 32 / 3; ++i)
encode_base64(&base64[i * 4], &key[i * 3]);
const uint8_t tempKey[3] = {key[i * 3 + 0], key[i * 3 + 1], 0};
encode_base64(&base64[i * 4], tempKey);
base64[sizeof(wg_key_b64_string) - 2] = '=';
base64[sizeof(wg_key_b64_string) - 1] = '\0';
return std::string(base64);
}
}

@ -3,6 +3,8 @@
#include <string>
const int WG_KEY_LENGTH = 32, B64_WG_KEY_LENGTH = ((WG_KEY_LENGTH + 2) / 3) * 4;
const int wgKeyLength = 32, Base64WgKeyLength = ((wgKeyLength + 2) / 3) * 4;
typedef unsigned char wg_key[WG_KEY_LENGTH];
typedef char wg_key_b64_string[B64_WG_KEY_LENGTH + 1];
typedef long long fe[16];

7
addon/go/userspace.cpp Normal file

@ -0,0 +1,7 @@
#include <string>
namespace WireguardUserspace {
std::string getVersion() {
return "";
}
};

70
addon/main.cpp Normal file

@ -0,0 +1,70 @@
#include "wg.hh"
#include "go/userspace.cpp"
#include <napi.h>
Napi::Object StartAddon(const Napi::Env env, const Napi::Object exports) {
const Napi::Object Constants = Napi::Object::New(env), Userspace = Napi::Object::New(env);
if (getWireguardVersion().length() > 0) Constants.Set("driveVersion", getWireguardVersion());
Userspace.Set("driveVersion", WireguardUserspace::getVersion());
exports.Set("deleteInterface", Napi::Function::New(env, [](const Napi::CallbackInfo &info) -> Napi::Value {
const Napi::Env env = info.Env();
if (!(info[0].IsString())) {
Napi::Error::New(env, "Set interface name").ThrowAsJavaScriptException();
return env.Undefined();
}
try {
DeleteInterface *worker = new DeleteInterface(env, info[0].ToString());
worker->Queue();
return worker->NodePromise.Promise();
} catch (std::string &err) {
Napi::Error::New(env, err).ThrowAsJavaScriptException();
return env.Undefined();
}
}));
exports.Set("listDevices", Napi::Function::New(env, [](const Napi::CallbackInfo &info) -> Napi::Value {
const Napi::Env env = info.Env();
try {
ListDevices *worker = new ListDevices(env);
worker->Queue();
return worker->NodePromise.Promise();
} catch (std::string &err) {
Napi::Error::New(env, err).ThrowAsJavaScriptException();
return env.Undefined();
}
}));
exports.Set("setConfig", Napi::Function::New(env, [](const Napi::CallbackInfo &info) -> Napi::Value {
const Napi::Env env = info.Env();
try {
SetConfig *worker = new SetConfig(env, info[0].ToObject());
worker->Queue();
return worker->NodePromise.Promise();
} catch (std::string &err) {
Napi::Error::New(env, err).ThrowAsJavaScriptException();
return env.Undefined();
}
}));
exports.Set("getConfig", Napi::Function::New(env, [](const Napi::CallbackInfo &info) -> Napi::Value {
const Napi::Env env = info.Env();
if (!(info[0].IsString())) {
Napi::Error::New(env, "Set interface name in fist argument!").ThrowAsJavaScriptException();
return env.Undefined();
}
try {
GetConfig *worker = new GetConfig(env, info[0].ToString());
worker->Queue();
return worker->NodePromise.Promise();
} catch (std::string &err) {
Napi::Error::New(env, err).ThrowAsJavaScriptException();
return env.Undefined();
}
}));
exports.Set("constants", Constants);
exports.Set("userspace", Userspace);
return exports;
}
NODE_API_MODULE(addon, StartAddon);

138
addon/wg.hh Normal file

@ -0,0 +1,138 @@
#ifndef __WG_NODE__
#define __WG_NODE__
#include <wginterface.hh>
#include <napi.h>
#include <functional>
#include <iostream>
class Promised : public Napi::AsyncWorker {
public:
Napi::Promise::Deferred NodePromise;
Promised(const Napi::Env &env): AsyncWorker(env), NodePromise{env} {}
void OnError(const Napi::Error& e) override {
Napi::HandleScope scope(Env());
NodePromise.Reject(e.Value());
}
void OnOK() override {
Napi::HandleScope scope(Env());
auto call = [&](Napi::Value data) -> void { NodePromise.Resolve(data); };
runOk(call);
}
virtual void runOk(std::function<void(Napi::Value)> callback) {
Napi::HandleScope scope(Env());
callback(Env().Undefined());
};
};
class DeleteInterface : public Promised {
std::string wgName;
public:
DeleteInterface(const Napi::Env &env, const Napi::String &name): Promised(env), wgName{name.Utf8Value()} {}
void Execute() override {
WireguardDevices wgDevs = WireguardDevices();
try {
wgDevs.deleteInterface(wgName);
} catch (std::string &err) { SetError(err); }
}
};
class ListDevices : public Promised {
WireguardDevices wgDevs;
public:
ListDevices(const Napi::Env &env): Promised(env), wgDevs{} {}
void Execute() override {
try {
wgDevs.getInterfaces();
} catch (std::string &err) { SetError(err); }
}
void runOk(std::function<void(Napi::Value)> callback) override {
Napi::HandleScope scope(Env());
const Napi::Env env = Env();
const Napi::Array interf = Napi::Array::New(env);
for (auto &ip : wgDevs) interf.Set(interf.Length(), ip);
callback(interf);
}
};
class SetConfig : public WireguardConfig, public Promised {
public:
void Execute() {
try {
this->setWireguardConfig();
} catch (std::string err) {
SetError(err);
}
}
SetConfig(const Napi::Env &env, const Napi::Object config): Promised(env) {
if (!(config.Has("name"))) throw std::string("Set wireguard interface name!");
if (!(config.Has("privateKey"))) throw std::string("Set wireguard private key!");
this->name = config.Get("name").ToString().Utf8Value();
}
};
class GetConfig : public WireguardConfig, public Promised {
public:
GetConfig(const Napi::Env &env, const Napi::String name): Promised(env) {
this->name = name.Utf8Value();
}
void Execute() {
try {
this->getWireguardConfig();
} catch (std::string err) {
SetError(err);
}
}
void runOk(std::function<void(Napi::Value)> callback) {
Napi::HandleScope scope(Env());
const Napi::Env env = Env();
const Napi::Object config = Napi::Object::New(env);
config.Set("name", this->name);
config.Set("privateKey", this->privateKey);
if (this->publicKey.length() == Base64WgKeyLength) config.Set("publicKey", this->publicKey);
if (this->portListen > 0) config.Set("portListen", this->portListen);
if (this->fwmark > 0) config.Set("fwmark", this->fwmark);
// Interface IPs
const Napi::Array ips = Napi::Array::New(env);
for (auto ip : this->interfaceAddress) ips.Set(ips.Length(), ip);
config.Set("address", ips);
// Peers
const Napi::Object peersObj = Napi::Object::New(env);
for (auto &__peer : this->Peers) {
std::cout << "script\n";
std::string publicKey = __peer.first;
if (publicKey.length() != Base64WgKeyLength) continue;
const Napi::Object peerConfig = Napi::Object::New(env);
const Peer config = __peer.second;
if (config.presharedKey.length() == Base64WgKeyLength) peerConfig.Set("presharedKey", config.presharedKey);
if (config.keepInterval >= 0) peerConfig.Set("keepInterval", config.keepInterval);
if (config.endpoint.length() > 0) peerConfig.Set("endpoint", config.endpoint);
peerConfig.Set("lastHandshake", Napi::Date::New(env, config.lastHandshake));
peerConfig.Set("rxBytes", Napi::BigInt::New(env, (uint64_t)config.rxBytes));
peerConfig.Set("txBytes", Napi::BigInt::New(env, (uint64_t)config.txBytes));
const Napi::Array ips = Napi::Array::New(env);
for (auto &ip : config.allowedIPs) ips.Set(ips.Length(), ip);
peersObj.Set("allowedIPs", ips);
peersObj.Set(publicKey, peerConfig);
}
config.Set("peers", peersObj);
// Set data
callback(config);
}
};
#endif

124
addon/wginterface.hh Normal file

@ -0,0 +1,124 @@
#ifndef __WIREGUARD_ADDON__
#define __WIREGUARD_ADDON__
#include "genKey/wgkeys.hh"
#include <string>
#include <vector>
#include <map>
extern const int wgKeyLength;
extern const int Base64WgKeyLength;
std::string getWireguardVersion();
class WireguardDevices : public std::vector<std::string> {
public:
~WireguardDevices() { this->clear(); }
/** Get all interfaces from kernel and insert in vector */
void getInterfaces();
/** Delete interface from kernel network */
void deleteInterface(std::string wgName);
/** Check if exists wireguard interface intterface */
bool exist(std::string name) {
this->getInterfaces();
for (auto wgDev = this->begin(); wgDev != this->end(); ++wgDev) {
if (name == *wgDev) return true;
}
return false;
}
};
/** Maneger Interface IPs */
class IpManeger : public std::vector<std::string> {
public:
void SetInInterface(std::string interfaceName);
void addIP(std::string ip) {
this->push_back(ip);
}
};
/**
* peer class
*/
class Peer {
public:
Peer() {
this->removeMe = false;
this->keepInterval = 0;
this->rxBytes = 0;
this->txBytes = 0;
this->lastHandshake = 0;
}
/** Remove specifies if the peer with this public key should be removed from a device's peer list. */
bool removeMe;
/** PresharedKey is an optional preshared key which may be used as an additional layer of security for peer communications. */
std::string presharedKey;
/** Endpoint is the most recent source address used for communication by this Peer. */
std::string endpoint;
/** PersistentKeepaliveInterval specifies how often an "empty" packet is sent to a peer to keep a connection alive.
*
* A value of 0 indicates that persistent keepalives are disabled.
*/
unsigned int keepInterval;
/** Last peer handshake in milisseconds */
unsigned long long lastHandshake;
/** Peer data received (RX) and transferred (TX) */
unsigned long long rxBytes, txBytes;
/** Peer ips allowed to recive data */
IpManeger allowedIPs;
};
/**
* Set and Get Wireguard configs
*/
class WireguardConfig {
public:
WireguardConfig() {
this->portListen = 0;
this->fwmark = 0;
}
/** Wireguard interface name */
std::string name;
/** Wireguard interface private key */
std::string privateKey;
/** Wireguard interface public key */
std::string publicKey;
/** Wireguard port listening or listened */
unsigned short portListen;
/** FirewallMark specifies a device's firewall mark else set to 0, the firewall mark will be cleared */
unsigned int fwmark;
/** Replace Wireguard peers if wireguard interface exists */
bool replacePeers;
/** Wireguard interface IPs */
IpManeger interfaceAddress;
/** Wireguard peers */
std::map<std::string, Peer> Peers;
/** Set wireguard config in interface */
void setWireguardConfig();
/** Get configuration from wireguard */
void getWireguardConfig();
};
#endif

@ -1,80 +1,28 @@
name: wginterface
flags:
- "!-fno-exceptions"
- "-fpermissive"
- "-fexceptions"
- "-w"
- "-fpermissive"
flagsCC:
- "!-fno-exceptions"
- "-fpermissive"
- "-fexceptions"
- "-w"
- "-fpermissive"
defines:
- "NAPI_DISABLE_CPP_EXCEPTIONS"
- "NODE_VERSION=4"
- "NODE_VERSION=9"
- "NAPI_CPP_EXCEPTIONS"
includes:
- addons/genKey
- addons/tools
- node_modules/node-addon-api
- ./addon
sources:
- "addons/genKey/wgkeys.cpp"
- "addons/tools/wginterface.cpp"
- "addons/tools/wginterface-dummy.cpp"
- "addon/main.cpp"
- "addon/genKey/wgkeys.cpp"
# Set undefined functions to non supported system
- "addon/dummy/wginterface.cpp"
target:
macos:
defines:
- USERSPACE_GO
linux:
sources:
- "addons/tools/linux/wireguard.c"
- "addons/tools/wginterface-linux.cpp"
- "!addons/tools/wginterface-dummy.cpp"
defines:
- "LISTDEV"
- "GETCONFIG"
- "SETCONFIG"
- "DELIFACE"
target:
x86_64:
release: true
flags:
- "-fPIC"
flagsCC:
- "-fPIC"
aarch64:
release: true
flags:
- "-fPIC"
flagsCC:
- "-fPIC"
windows:
flags:
- "-undefined"
- "dynamic_lookup"
target:
x86_64:
release: true
aarch64:
release: true
sources:
- "addons/tools/wginterface-win.cpp"
- "!addons/tools/wginterface-dummy.cpp"
includes:
- "addons/tools/win"
defines:
- "ONSTARTADDON"
- "LISTDEV"
- "GETCONFIG"
- "SETCONFIG"
- "DELIFACE"
- "_HAS_EXCEPTIONS=1"
libraries:
- "bcrypt.lib"
- "crypt32.lib"
- "iphlpapi.lib"
- "kernel32.lib"
- "ntdll.lib"
- "ws2_32.lib"
- "setupapi.lib"
- "!-fno-exceptions"
- "-fpermissive"
- "-fexceptions"
- "-w"
- "-fpermissive"
macos:
flags:
- "!-fno-exceptions"
- "-fpermissive"
- "-fexceptions"
- "-w"
- "-fpermissive"

@ -46,6 +46,6 @@
},
"dependencies": {
"node-addon-api": "^7.1.0",
"rebory": "^0.1.12"
"rebory": "^0.2.4"
}
}

@ -1 +1,4 @@
export * as key from "./key.js";
export * as quickConfig from "./quick.js";
export * from "./wginterface.js";
export * as wginterface from "./wginterface.js";

108
src/wginterface.ts Normal file

@ -0,0 +1,108 @@
import path from "node:path";
import { loadAddon } from "rebory";
const __dirname = import.meta.dirname || path.dirname((await import("node:url")).fileURLToPath(import.meta.url));
interface Peer {
/** Preshared key to peer */
presharedKey?: string;
/** keepInterval specifies the persistent keepalive interval for this peer */
keepInterval?: number;
/** Remote address or hostname to Wireguard connect or endpoint is the most recent source address used for communication by peer. */
endpoint?: string;
/** AllowedIPs specifies a list of allowed IP addresses in CIDR notation (`0.0.0.0/0`, `::/0`) */
allowedIPs?: string[];
};
export interface SetPeer extends Peer {
/** Remove this peer */
removeMe?: boolean;
}
export interface GetPeer extends Peer {
/** ReceiveBytes indicates the number of bytes received from this peer. */
rxBytes: bigint;
/** TransmitBytes indicates the number of bytes transmitted to this peer. */
txBytes: bigint;
/** Last peer Handshake */
lastHandshake: Date;
}
interface Config<T extends Peer> {
/** Wireguard interface name */
name: string;
/** privateKey specifies a private key configuration */
privateKey: string;
/** publicKey specifies a public key configuration */
publicKey?: string;
/** ListenPort specifies a device's listening port, 0 is random */
portListen?: number;
/** FirewallMark specifies a device's firewall mark */
fwmark?: number;
/** Interface IP address'es */
address?: string[];
/** Interface Peers */
peers: Record<string, T>;
};
export interface GetConfig extends Config<GetPeer> {};
export interface SetConfig extends Config<SetPeer> {
/** this option will remove all peers if `true` and add new peers */
replacePeers?: boolean;
};
const addon = (await loadAddon(path.resolve(__dirname, "../binding.yaml"))).wginterface.load_addon<{
/** Userspace support */
userspace?: {
/** Wireguard-go version */
driveVersion?: string;
/** Get tunel socket path */
getTunel: (name: string) => Promise<string>;
/** Get tunel socket path */
deleteTunel: (name: string) => Promise<string>;
};
/** Kernel wireguard version */
driveVersion?: string;
deleteInterface(name: string): Promise<GetConfig>;
listDevices(): Promise<string[]>;
getConfig(name: string): Promise<GetConfig>;
setConfig(config: SetConfig): Promise<void>;
}>({});
/**
* Wireguard interface to kernel level
*/
export namespace Kernel {
export const {
driveVersion,
listDevices,
getConfig,
setConfig,
deleteInterface
} = addon;
};
/**
* Wireguard userspace (wireguard-go)
*/
export namespace Userspace {
const { userspace } = addon;
export const { driveVersion } = userspace || {};
export async function listDevices() {}
export async function deleteInterface() {}
export async function setConfig() {}
export async function getConfig() {}
};