Big code refactoring #10
11
.github/dependabot.yml
vendored
11
.github/dependabot.yml
vendored
@ -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
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
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"
|
||||
}
|
||||
}
|
22
addon/dummy/wginterface.cpp
Normal file
22
addon/dummy/wginterface.cpp
Normal file
@ -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
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
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
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
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
|
92
binding.yaml
92
binding.yaml
@ -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
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() {}
|
||||
};
|
Loading…
x
Reference in New Issue
Block a user