WIP: Test - Update addon #9
13
.npmignore
13
.npmignore
@ -2,20 +2,19 @@
|
||||
node_modules/
|
||||
/*.tgz
|
||||
|
||||
# Addon
|
||||
build/**/*
|
||||
!build/**/*.node
|
||||
|
||||
# Typescript
|
||||
src/**/*_test.*
|
||||
src/**/*test*
|
||||
src/**/*.ts
|
||||
!src/**/*.d.ts
|
||||
|
||||
# vscode
|
||||
.devcontainer/
|
||||
.vscode/
|
||||
.vscode-ctags
|
||||
|
||||
# Github and Git
|
||||
# Github, Gitlab, Git
|
||||
.github/
|
||||
.git*
|
||||
|
||||
# Project
|
||||
.vscode-ctags*
|
||||
*.addrs.json
|
64
.vscode/settings.json
vendored
64
.vscode/settings.json
vendored
@ -23,8 +23,70 @@
|
||||
"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",
|
||||
"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"
|
||||
}
|
||||
}
|
@ -1,15 +1,16 @@
|
||||
#include <napi.h>
|
||||
#include <wginterface.hh>
|
||||
|
||||
unsigned long maxName() {
|
||||
unsigned long SetupAddon::maxName() {
|
||||
return 16;
|
||||
}
|
||||
|
||||
std::string versionDrive() {
|
||||
std::string SetupAddon::versionDrive() {
|
||||
return "Userspace";
|
||||
}
|
||||
|
||||
void listDevices::Execute() {}
|
||||
void deleteInterface::Execute() {}
|
||||
void setConfig::Execute() {}
|
||||
void getConfig::Execute() {}
|
||||
|
||||
void ConfigBase::getWireguardConfig() {}
|
||||
void ConfigBase::setWireguardConfig() {}
|
0
addons/tools/wginterface-go.cpp
Normal file
0
addons/tools/wginterface-go.cpp
Normal file
@ -33,11 +33,11 @@ std::string getKernelMesage(int errStatus) {
|
||||
return message;
|
||||
}
|
||||
|
||||
unsigned long maxName() {
|
||||
unsigned long SetupAddon::maxName() {
|
||||
return IFNAMSIZ;
|
||||
}
|
||||
|
||||
std::string versionDrive() {
|
||||
std::string SetupAddon::versionDrive() {
|
||||
return "Kernel";
|
||||
}
|
||||
|
||||
@ -67,22 +67,17 @@ class List {
|
||||
|
||||
void listDevices::Execute() {
|
||||
List l;
|
||||
try {
|
||||
l.getAll();
|
||||
for (auto ifname : l.devs) {
|
||||
listInfo setInfo;
|
||||
setInfo.tunType = "kernel";
|
||||
deviceNames[ifname] = setInfo;
|
||||
}
|
||||
} catch (std::string err) {
|
||||
SetError(err);
|
||||
l.getAll();
|
||||
for (auto ifname : l.devs) {
|
||||
listInfo setInfo;
|
||||
setInfo.tunType = "kernel";
|
||||
deviceNames[ifname] = setInfo;
|
||||
}
|
||||
l.~List();
|
||||
}
|
||||
|
||||
void deleteInterface::Execute() {
|
||||
int status = wg_del_device(wgName.c_str());
|
||||
if (status < 0) SetError(std::string("Cannot delete interface, code status: ").append(std::to_string(status)));
|
||||
if (status < 0) throw std::string("Cannot delete interface, code status: ").append(std::to_string(status));
|
||||
}
|
||||
|
||||
int createInterface(std::string &wgName) {
|
||||
@ -102,11 +97,10 @@ int createInterface(std::string &wgName) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void setConfig::Execute() {
|
||||
void ConfigBase::setWireguardConfig() {
|
||||
int res = createInterface(wgName);
|
||||
if (res < 0) {
|
||||
SetError(std::string("Cannot create wireguard interface, Code: ").append(std::to_string(res)));
|
||||
return;
|
||||
throw std::string("Cannot create wireguard interface, Code: ").append(std::to_string(res));
|
||||
}
|
||||
|
||||
// Set device struct
|
||||
@ -139,7 +133,7 @@ void setConfig::Execute() {
|
||||
if (replacePeers) deviceStruct->flags = (wg_device_flags)(deviceStruct->flags|WGDEVICE_REPLACE_PEERS);
|
||||
|
||||
unsigned int peerIndex = 0;
|
||||
for (auto it = peersVector.begin(); it != peersVector.end(); ++it) {
|
||||
for (auto it = this->Peers.begin(); it != this->Peers.end(); ++it) {
|
||||
const std::string peerPubKey = it->first;
|
||||
auto peerConfig = it->second;
|
||||
peerIndex++;
|
||||
@ -175,13 +169,13 @@ void setConfig::Execute() {
|
||||
end = strchr(Endpoint, ']');
|
||||
if (!end) {
|
||||
free(Endpoint);
|
||||
SetError("Unable to find matching brace of endpoint");
|
||||
throw std::string("Unable to find matching brace of endpoint");
|
||||
return;
|
||||
}
|
||||
*end++ = '\0';
|
||||
if (*end++ != ':' || !*end) {
|
||||
free(Endpoint);
|
||||
SetError("Unable to find port of endpoint");
|
||||
throw std::string("Unable to find port of endpoint");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
@ -189,7 +183,7 @@ void setConfig::Execute() {
|
||||
end = strrchr(Endpoint, ':');
|
||||
if (!end || !*(end + 1)) {
|
||||
free(Endpoint);
|
||||
SetError("Unable to find port of endpoint");
|
||||
throw std::string("Unable to find port of endpoint");
|
||||
return;
|
||||
}
|
||||
*end++ = '\0';
|
||||
@ -211,7 +205,7 @@ void setConfig::Execute() {
|
||||
(retries >= 0 && !retries--)) {
|
||||
free(Endpoint);
|
||||
fprintf(stderr, "%s: `%s'\n", ret == EAI_SYSTEM ? strerror(errno) : gai_strerror(ret), peerConfig.endpoint.c_str());
|
||||
SetError("Unable to resolve endpoint");
|
||||
throw std::string("Unable to resolve endpoint");
|
||||
return;
|
||||
}
|
||||
fprintf(stderr, "%s: `%s'. Trying again in %.2f seconds...\n", ret == EAI_SYSTEM ? strerror(errno) : gai_strerror(ret), peerConfig.endpoint.c_str(), timeout / 1000000.0);
|
||||
@ -232,7 +226,7 @@ void setConfig::Execute() {
|
||||
} else {
|
||||
freeaddrinfo(resolved);
|
||||
free(Endpoint);
|
||||
SetError("Neither IPv4 nor IPv6 address found");
|
||||
throw std::string("Neither IPv4 nor IPv6 address found");
|
||||
return;
|
||||
}
|
||||
freeaddrinfo(resolved);
|
||||
@ -275,7 +269,7 @@ void setConfig::Execute() {
|
||||
}
|
||||
|
||||
// Set interface config
|
||||
if ((res = wg_set_device(deviceStruct)) < 0) SetError(getKernelMesage(res));
|
||||
if ((res = wg_set_device(deviceStruct)) < 0) throw std::string(getKernelMesage(res));
|
||||
}
|
||||
|
||||
const char* getHostAddress(bool addPort, const sockaddr* addr) {
|
||||
@ -304,10 +298,10 @@ std::string keyTo64(const uint8_t *key) {
|
||||
return strKey;
|
||||
}
|
||||
|
||||
void getConfig::Execute() {
|
||||
void ConfigBase::getWireguardConfig() {
|
||||
int res; wg_device *device;
|
||||
if ((res = wg_get_device(&device, strdup(wgName.c_str()))) < 0) {
|
||||
SetError(std::string("Device not exists or cannot get config from this interface!, code error: ").append(std::to_string(res)));
|
||||
throw std::string("Device not exists or cannot get config from this interface!, code error: ").append(std::to_string(res));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -348,6 +342,6 @@ void getConfig::Execute() {
|
||||
}
|
||||
}
|
||||
|
||||
peersVector[keyTo64(peer->public_key)] = PeerConfig;
|
||||
this->Peers[keyTo64(peer->public_key)] = PeerConfig;
|
||||
}
|
||||
}
|
@ -43,10 +43,6 @@ static WIREGUARD_SET_ADAPTER_STATE_FUNC *WireGuardSetAdapterState;
|
||||
static WIREGUARD_GET_CONFIGURATION_FUNC *WireGuardGetConfiguration;
|
||||
static WIREGUARD_SET_CONFIGURATION_FUNC *WireGuardSetConfiguration;
|
||||
|
||||
unsigned long maxName() {
|
||||
return IFNAMSIZ;
|
||||
}
|
||||
|
||||
std::string getErrorString(DWORD errorMessageID) {
|
||||
if (errorMessageID == 0 || errorMessageID < 0) std::string("Error code: ").append(std::to_string(errorMessageID));
|
||||
LPSTR messageBuffer = nullptr;
|
||||
@ -60,7 +56,7 @@ std::string getErrorString(DWORD errorMessageID) {
|
||||
return std::string("Error code: ").append(std::to_string(errorMessageID)).append(", Message: ").append(message);
|
||||
}
|
||||
|
||||
std::string startAddon(const Napi::Env env, Napi::Object exports) {
|
||||
std::string SetupAddon::startAddon(const Napi::Env env, Napi::Object exports) {
|
||||
if (!IsRunAsAdmin()) return "Run nodejs with administrator privilegies";
|
||||
auto DLLPATH = exports.Get("WIN32DLLPATH");
|
||||
if (!(DLLPATH.IsString())) return "Require WIREGUARD_DLL_PATH in addon load!";
|
||||
@ -81,7 +77,11 @@ std::string startAddon(const Napi::Env env, Napi::Object exports) {
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string versionDrive() {
|
||||
unsigned long SetupAddon::maxName() {
|
||||
return IFNAMSIZ;
|
||||
}
|
||||
|
||||
std::string SetupAddon::versionDrive() {
|
||||
WIREGUARD_ADAPTER_HANDLE Adapter = WireGuardCreateAdapter(L"getWgVersion", L"Wireguard-tools.js", NULL);
|
||||
DWORD Version = WireGuardGetRunningDriverVersion();
|
||||
if (Version == 0) {
|
||||
@ -116,11 +116,13 @@ void listDevices::Execute() {
|
||||
deviceNames[std::string(iface)] = setInfo;
|
||||
} while (FindNextFile(find_handle, &find_data));
|
||||
FindClose(find_handle);
|
||||
if (ret < 0) return SetError(std::string("Erro code: ").append(std::to_string(ret)));
|
||||
if (ret < 0) {
|
||||
throw std::string(std::string("Erro code: ").append(std::to_string(ret)));
|
||||
}
|
||||
}
|
||||
|
||||
HDEVINFO dev_info = SetupDiGetClassDevsExW(&GUID_DEVCLASS_NET, L"SWD\\WireGuard", NULL, DIGCF_PRESENT, NULL, NULL, NULL);
|
||||
if (dev_info == INVALID_HANDLE_VALUE) return SetError("Cannot get devices");
|
||||
if (dev_info == INVALID_HANDLE_VALUE) throw std::string("Cannot get devices");
|
||||
|
||||
for (DWORD i = 0;; ++i) {
|
||||
DWORD buf_len;
|
||||
@ -161,8 +163,8 @@ void listDevices::Execute() {
|
||||
|
||||
void deleteInterface::Execute() {
|
||||
WIREGUARD_ADAPTER_HANDLE Adapter = WireGuardOpenAdapter(toLpcwstr(wgName));
|
||||
if (!Adapter) return SetError("This interface not exists in Wireguard-Tools.js addon!");
|
||||
if (!(WireGuardSetAdapterState(Adapter, WIREGUARD_ADAPTER_STATE::WIREGUARD_ADAPTER_STATE_DOWN))) return SetError(std::string("Failed to set down interface, ").append(getErrorString(GetLastError())));
|
||||
if (!Adapter) throw std::string("This interface not exists in Wireguard-Tools.js addon!");
|
||||
if (!(WireGuardSetAdapterState(Adapter, WIREGUARD_ADAPTER_STATE::WIREGUARD_ADAPTER_STATE_DOWN))) throw std::string("Failed to set down interface, ").append(getErrorString(GetLastError()));
|
||||
WireGuardCloseAdapter(Adapter);
|
||||
}
|
||||
|
||||
@ -178,15 +180,16 @@ template <typename T, typename C> C* changePoint(T *x) {
|
||||
return reinterpret_cast<C*>(((char*)x) + sizeof(T));
|
||||
}
|
||||
|
||||
void getConfig::Execute() {
|
||||
|
||||
void ConfigBase::getWireguardConfig() {
|
||||
WIREGUARD_ADAPTER_HANDLE Adapter = WireGuardOpenAdapter(toLpcwstr(wgName));
|
||||
if (!Adapter) return SetError("This interface not exists in Wireguard-Tools.js addon!");
|
||||
if (!Adapter) throw std::string("This interface not exists in Wireguard-Tools.js addon!");
|
||||
NET_LUID InterfaceLuid;
|
||||
WireGuardGetAdapterLUID(Adapter, &InterfaceLuid);
|
||||
try {
|
||||
for (auto aip : getIpAddr(InterfaceLuid)) Address.push_back(aip);
|
||||
} catch (std::string err) {
|
||||
return SetError(err);
|
||||
throw std::string(err);
|
||||
}
|
||||
|
||||
DWORD buf_len = 0;
|
||||
@ -194,9 +197,9 @@ void getConfig::Execute() {
|
||||
|
||||
while (!(WireGuardGetConfiguration(Adapter, wg_iface, &buf_len))) {
|
||||
free(wg_iface);
|
||||
if (GetLastError() != ERROR_MORE_DATA) return SetError((std::string("Failed get interface config, code: ")).append(std::to_string(GetLastError())));
|
||||
if (GetLastError() != ERROR_MORE_DATA) throw std::string("Failed get interface config, code: ").append(std::to_string(GetLastError()));
|
||||
wg_iface = (WIREGUARD_INTERFACE *)malloc(buf_len);
|
||||
if (!wg_iface) return SetError(std::string("Failed get interface config, ").append(std::to_string(-errno)));
|
||||
if (!wg_iface) throw std::string("Failed get interface config, ").append(std::to_string(-errno));
|
||||
}
|
||||
|
||||
if (wg_iface->Flags & WIREGUARD_INTERFACE_FLAG::WIREGUARD_INTERFACE_HAS_PRIVATE_KEY) privateKey = wgKeys::toString(wg_iface->PrivateKey);
|
||||
@ -231,24 +234,24 @@ void getConfig::Execute() {
|
||||
++wg_aip;
|
||||
}
|
||||
wg_peer = reinterpret_cast<WIREGUARD_PEER*>(wg_aip);
|
||||
peersVector[pubKey] = peerConfig;
|
||||
this->Peers[pubKey] = peerConfig;
|
||||
}
|
||||
|
||||
free(wg_iface);
|
||||
}
|
||||
|
||||
void setConfig::Execute() {
|
||||
void ConfigBase::setWireguardConfig() {
|
||||
DWORD buf_len = sizeof(WIREGUARD_INTERFACE);
|
||||
for (auto peer : peersVector) {
|
||||
if (DWORD_MAX - buf_len < sizeof(WIREGUARD_PEER)) return SetError("Buffer overflow");
|
||||
for (auto peer : this->Peers) {
|
||||
if (DWORD_MAX - buf_len < sizeof(WIREGUARD_PEER)) throw std::string("Buffer overflow");
|
||||
buf_len += sizeof(WIREGUARD_PEER);
|
||||
for (auto aip : peer.second.allowedIPs) {
|
||||
if (DWORD_MAX - buf_len < sizeof(WIREGUARD_ALLOWED_IP)) return SetError("Buffer overflow");
|
||||
if (DWORD_MAX - buf_len < sizeof(WIREGUARD_ALLOWED_IP)) throw std::string("Buffer overflow");
|
||||
buf_len += sizeof(WIREGUARD_ALLOWED_IP);
|
||||
}
|
||||
}
|
||||
WIREGUARD_INTERFACE *wg_iface = reinterpret_cast<WIREGUARD_INTERFACE*>(calloc(1, buf_len));
|
||||
if (!wg_iface) return SetError("Cannot alloc buff");
|
||||
if (!wg_iface) throw std::string("Cannot alloc buff");
|
||||
wg_iface->PeersCount = 0;
|
||||
|
||||
wgKeys::stringToKey(wg_iface->PrivateKey, privateKey);
|
||||
@ -261,13 +264,13 @@ void setConfig::Execute() {
|
||||
|
||||
WIREGUARD_ALLOWED_IP *wg_aip;
|
||||
WIREGUARD_PEER *wg_peer = changePoint<WIREGUARD_INTERFACE, WIREGUARD_PEER>(wg_iface);
|
||||
for (auto __peer : peersVector) {
|
||||
for (auto __peer : this->Peers) {
|
||||
auto peerPublicKey = __peer.first; auto peerConfig = __peer.second;
|
||||
try {
|
||||
wgKeys::stringToKey(wg_peer->PublicKey, peerPublicKey);
|
||||
} catch (std::string &err) {
|
||||
SetError(err);
|
||||
free(wg_iface);
|
||||
throw std::string(err);
|
||||
return;
|
||||
}
|
||||
wg_peer->Flags = WIREGUARD_PEER_FLAG::WIREGUARD_PEER_HAS_PUBLIC_KEY;
|
||||
@ -283,8 +286,8 @@ void setConfig::Execute() {
|
||||
wgKeys::stringToKey(wg_peer->PresharedKey, peerConfig.presharedKey);
|
||||
wg_peer->Flags = (WIREGUARD_PEER_FLAG)(wg_peer->Flags|WIREGUARD_PEER_FLAG::WIREGUARD_PEER_HAS_PRESHARED_KEY);
|
||||
} catch (std::string &err) {
|
||||
SetError(err);
|
||||
free(wg_iface);
|
||||
throw std::string(err);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -297,8 +300,8 @@ void setConfig::Execute() {
|
||||
insertEndpoint(&wg_peer->Endpoint, peerConfig.endpoint.c_str());
|
||||
wg_peer->Flags = (WIREGUARD_PEER_FLAG)(wg_peer->Flags|WIREGUARD_PEER_FLAG::WIREGUARD_PEER_HAS_ENDPOINT);
|
||||
} catch (std::string &err) {
|
||||
SetError(std::string("Cannot parse endpoint, ").append(err));
|
||||
free(wg_iface);
|
||||
throw std::string(std::string("Cannot parse endpoint, ").append(err));
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -327,15 +330,21 @@ void setConfig::Execute() {
|
||||
|
||||
WIREGUARD_ADAPTER_HANDLE Adapter = WireGuardOpenAdapter(toLpcwstr(wgName));
|
||||
if (!Adapter) Adapter = WireGuardCreateAdapter(toLpcwstr(wgName), L"Wireguard-tools.js", NULL);
|
||||
if (!Adapter) SetError(std::string("Failed to create adapter, ").append(getErrorString(GetLastError())));
|
||||
else if (!WireGuardSetConfiguration(Adapter, reinterpret_cast<WIREGUARD_INTERFACE*>(wg_iface), buf_len)) {
|
||||
if (!Adapter) {
|
||||
free(wg_iface);
|
||||
throw std::string(std::string("Failed to create adapter, ").append(getErrorString(GetLastError())));
|
||||
} else if (!WireGuardSetConfiguration(Adapter, reinterpret_cast<WIREGUARD_INTERFACE*>(wg_iface), buf_len)) {
|
||||
free(wg_iface);
|
||||
auto status = GetLastError();
|
||||
SetError(std::string("Failed to set interface config, ").append(getErrorString(status)));
|
||||
auto err = std::string(std::string("Failed to set interface config, ").append(getErrorString(status)));
|
||||
WireGuardCloseAdapter(Adapter);
|
||||
throw err;
|
||||
} else if (!WireGuardSetAdapterState(Adapter, WIREGUARD_ADAPTER_STATE::WIREGUARD_ADAPTER_STATE_UP)) {
|
||||
free(wg_iface);
|
||||
auto status = GetLastError();
|
||||
SetError(std::string("Failed to set interface up, ").append(getErrorString(status)));
|
||||
auto err = std::string(std::string("Failed to set interface up, ").append(getErrorString(status)));
|
||||
WireGuardCloseAdapter(Adapter);
|
||||
throw err;
|
||||
} else {
|
||||
if (Address.size() > 0) {
|
||||
std::string IPv4, IPv6;
|
||||
@ -355,7 +364,10 @@ void setConfig::Execute() {
|
||||
NET_LUID InterfaceLuid;
|
||||
WireGuardGetAdapterLUID(Adapter, &InterfaceLuid);
|
||||
auto setStatus = insertIpAddr(InterfaceLuid, IPv4, IPv6);
|
||||
if (setStatus.size() > 0) SetError(setStatus);
|
||||
if (setStatus.size() > 0) {
|
||||
free(wg_iface);
|
||||
throw std::string(setStatus);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,34 +5,28 @@
|
||||
Napi::Object Init(Napi::Env initEnv, Napi::Object exports) {
|
||||
/// Call Addon
|
||||
#ifdef ONSTARTADDON
|
||||
auto status = startAddon(initEnv, exports);
|
||||
auto status = SetupAddon::startAddon(initEnv, exports);
|
||||
if (status.length() >= 1) {
|
||||
Napi::Error::New(initEnv, status).ThrowAsJavaScriptException();
|
||||
return exports;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Wireguard constants set
|
||||
const Napi::Object constants = Napi::Object::New(initEnv);
|
||||
// Init Objects
|
||||
const Napi::Object Constant = Napi::Object::New(initEnv), Userspace = Napi::Object::New(initEnv);
|
||||
|
||||
// Set wireguard version if present
|
||||
constants.Set("driveVersion", versionDrive());
|
||||
const auto wgVersion = SetupAddon::versionDrive();
|
||||
if (wgVersion.length() > 0) Constant.Set("driveVersion", wgVersion);
|
||||
else Constant.Set("driveVersion", initEnv.Null());
|
||||
|
||||
// Wireguard max name length
|
||||
constants.Set("nameLength", maxName());
|
||||
Constant.Set("nameLength", SetupAddon::maxName());
|
||||
|
||||
constants.Set("base64Length", B64_WG_KEY_LENGTH);
|
||||
constants.Set("keyLength", WG_KEY_LENGTH);
|
||||
|
||||
// Set addon constants
|
||||
exports.Set("constants", constants);
|
||||
|
||||
// Function's
|
||||
#ifdef USERSPACE_GO
|
||||
exports.Set("createTun", Napi::Function::New(initEnv, [&](const Napi::CallbackInfo &info) -> Napi::Value { return info.Env().Undefined(); }));
|
||||
exports.Set("deleteTun", Napi::Function::New(initEnv, [&](const Napi::CallbackInfo &info) -> Napi::Value { return info.Env().Undefined(); }));
|
||||
exports.Set("checkTun", Napi::Function::New(initEnv, [&](const Napi::CallbackInfo &info) -> Napi::Value { return info.Env().Undefined(); }));
|
||||
exports.Set("getTun", Napi::Function::New(initEnv, [&](const Napi::CallbackInfo &info) -> Napi::Value { return info.Env().Undefined(); }));
|
||||
#endif
|
||||
Userspace.Set("createTun", Napi::Function::New(initEnv, [&](const Napi::CallbackInfo &info) -> Napi::Value { return info.Env().Undefined(); }));
|
||||
Userspace.Set("deleteTun", Napi::Function::New(initEnv, [&](const Napi::CallbackInfo &info) -> Napi::Value { return info.Env().Undefined(); }));
|
||||
Userspace.Set("checkTun", Napi::Function::New(initEnv, [&](const Napi::CallbackInfo &info) -> Napi::Value { return info.Env().Undefined(); }));
|
||||
Userspace.Set("getTunPath", Napi::Function::New(initEnv, [&](const Napi::CallbackInfo &info) -> Napi::Value { return info.Env().Undefined(); }));
|
||||
|
||||
#ifdef SETCONFIG
|
||||
exports.Set("setConfig", Napi::Function::New(initEnv, [&](const Napi::CallbackInfo &info) -> Napi::Value {
|
||||
@ -43,7 +37,7 @@ Napi::Object Init(Napi::Env initEnv, Napi::Object exports) {
|
||||
if (!(wgName.IsString())) {
|
||||
Napi::Error::New(env, "Require wireguard interface name").ThrowAsJavaScriptException();
|
||||
return env.Undefined();
|
||||
} else if (wgName.ToString().Utf8Value().length() >= maxName()) {
|
||||
} else if (wgName.ToString().Utf8Value().length() >= SetupAddon::maxName()) {
|
||||
Napi::Error::New(env, "interface name is so long").ThrowAsJavaScriptException();
|
||||
return env.Undefined();
|
||||
} else if (!(wgConfig.IsObject())) {
|
||||
@ -54,7 +48,7 @@ Napi::Object Init(Napi::Env initEnv, Napi::Object exports) {
|
||||
try {
|
||||
auto worker = new setConfig(env, wgName.ToString().Utf8Value(), wgConfig.ToObject());
|
||||
worker->Queue();
|
||||
return worker->setPromise.Promise();
|
||||
return worker->Promised.Promise();
|
||||
} catch (const Napi::Error &err) {
|
||||
err.ThrowAsJavaScriptException();
|
||||
}
|
||||
@ -69,14 +63,14 @@ Napi::Object Init(Napi::Env initEnv, Napi::Object exports) {
|
||||
if (!(wgName.IsString())) {
|
||||
Napi::Error::New(env, "Require wireguard interface name").ThrowAsJavaScriptException();
|
||||
return env.Undefined();
|
||||
} else if (wgName.ToString().Utf8Value().length() >= maxName()) {
|
||||
} else if (wgName.ToString().Utf8Value().length() >= SetupAddon::maxName()) {
|
||||
Napi::Error::New(env, "interface name is so long").ThrowAsJavaScriptException();
|
||||
return env.Undefined();
|
||||
}
|
||||
|
||||
auto worker = new deleteInterface(env, wgName.ToString().Utf8Value());
|
||||
worker->Queue();
|
||||
return worker->deletePromise.Promise();
|
||||
return worker->Promised.Promise();
|
||||
}));
|
||||
#endif
|
||||
|
||||
@ -87,7 +81,7 @@ Napi::Object Init(Napi::Env initEnv, Napi::Object exports) {
|
||||
if (!(wgName.IsString())) {
|
||||
Napi::Error::New(env, "Require wireguard interface name").ThrowAsJavaScriptException();
|
||||
return env.Undefined();
|
||||
} else if (wgName.ToString().Utf8Value().length() >= maxName()) {
|
||||
} else if (wgName.ToString().Utf8Value().length() >= SetupAddon::maxName()) {
|
||||
Napi::Error::New(env, "interface name is so long").ThrowAsJavaScriptException();
|
||||
return env.Undefined();
|
||||
}
|
||||
@ -95,7 +89,7 @@ Napi::Object Init(Napi::Env initEnv, Napi::Object exports) {
|
||||
try {
|
||||
auto worker = new getConfig(env, wgName.ToString().Utf8Value());
|
||||
worker->Queue();
|
||||
return worker->getPromise.Promise();
|
||||
return worker->Promised.Promise();
|
||||
} catch (const Napi::Error &err) {
|
||||
err.ThrowAsJavaScriptException();
|
||||
}
|
||||
@ -108,9 +102,12 @@ Napi::Object Init(Napi::Env initEnv, Napi::Object exports) {
|
||||
const Napi::Env env = info.Env();
|
||||
auto worker = new listDevices(env);
|
||||
worker->Queue();
|
||||
return worker->listDevicesPromise.Promise();
|
||||
return worker->Promised.Promise();
|
||||
}));
|
||||
#endif
|
||||
|
||||
exports.Set("constant", Constant);
|
||||
exports.Set("userspace", Userspace);
|
||||
return exports;
|
||||
}
|
||||
NODE_API_MODULE(addon, Init);
|
@ -5,31 +5,38 @@
|
||||
#include <map>
|
||||
#include <wgkeys.hh>
|
||||
|
||||
// Get wireguard max name length
|
||||
unsigned long maxName();
|
||||
// namespace SetupAddon
|
||||
namespace SetupAddon {
|
||||
// Get wireguard max name length
|
||||
unsigned long maxName();
|
||||
|
||||
// Get wireguard version
|
||||
std::string versionDrive();
|
||||
// Get wireguard version
|
||||
std::string versionDrive();
|
||||
|
||||
// On start module call this function
|
||||
std::string startAddon(const Napi::Env env, Napi::Object exports);
|
||||
// On start module call this function
|
||||
std::string startAddon(const Napi::Env env, Napi::Object exports);
|
||||
};
|
||||
|
||||
class deleteInterface : public Napi::AsyncWorker {
|
||||
class GlobalPromise : public Napi::AsyncWorker {
|
||||
public:
|
||||
GlobalPromise(const Napi::Env env): AsyncWorker(env), Promised{env} {}
|
||||
~GlobalPromise() {}
|
||||
const Napi::Promise::Deferred Promised;
|
||||
void OnError(const Napi::Error &e) override {
|
||||
Napi::HandleScope scope(Env());
|
||||
Promised.Reject(e.Value());
|
||||
}
|
||||
};
|
||||
|
||||
class deleteInterface : public GlobalPromise {
|
||||
private:
|
||||
std::string wgName;
|
||||
public:
|
||||
deleteInterface(const Napi::Env env, std::string name): AsyncWorker(env), wgName{name}, deletePromise{env} {}
|
||||
deleteInterface(const Napi::Env env, std::string name): GlobalPromise(env), wgName{name} {}
|
||||
~deleteInterface() {}
|
||||
const Napi::Promise::Deferred deletePromise;
|
||||
|
||||
void OnError(const Napi::Error &e) override {
|
||||
Napi::HandleScope scope(Env());
|
||||
deletePromise.Reject(e.Value());
|
||||
}
|
||||
|
||||
void OnOK() override {
|
||||
Napi::HandleScope scope(Env());
|
||||
deletePromise.Resolve(Env().Undefined());
|
||||
Promised.Resolve(Env().Undefined());
|
||||
};
|
||||
|
||||
// Set platform Execute script
|
||||
@ -41,19 +48,12 @@ class listInfo {
|
||||
std::string tunType, pathSock;
|
||||
};
|
||||
|
||||
class listDevices : public Napi::AsyncWorker {
|
||||
class listDevices : public GlobalPromise {
|
||||
private:
|
||||
std::map<std::string, listInfo> deviceNames;
|
||||
public:
|
||||
~listDevices() {}
|
||||
listDevices(const Napi::Env env) : AsyncWorker(env), listDevicesPromise{env} {}
|
||||
const Napi::Promise::Deferred listDevicesPromise;
|
||||
|
||||
void OnError(const Napi::Error& e) override {
|
||||
Napi::HandleScope scope(Env());
|
||||
listDevicesPromise.Reject(e.Value());
|
||||
}
|
||||
|
||||
listDevices(const Napi::Env env) : GlobalPromise(env) {}
|
||||
void OnOK() override {
|
||||
Napi::HandleScope scope(Env());
|
||||
const Napi::Env env = Env();
|
||||
@ -66,7 +66,7 @@ class listDevices : public Napi::AsyncWorker {
|
||||
if (infoSrc.pathSock.size() > 0) info.Set("path", infoSrc.pathSock);
|
||||
deviceArray.Set(deviceArray.Length(), info);
|
||||
}
|
||||
listDevicesPromise.Resolve(deviceArray);
|
||||
Promised.Resolve(deviceArray);
|
||||
};
|
||||
void Execute() override;
|
||||
};
|
||||
@ -118,11 +118,8 @@ class Peer {
|
||||
int ProtocolVersion = 0;
|
||||
};
|
||||
|
||||
/*
|
||||
Configure uma interface do Wireguard.
|
||||
*/
|
||||
class setConfig : public Napi::AsyncWorker {
|
||||
private:
|
||||
class ConfigBase {
|
||||
public:
|
||||
// Wireguard interface name (required)
|
||||
std::string wgName;
|
||||
|
||||
@ -133,11 +130,11 @@ class setConfig : public Napi::AsyncWorker {
|
||||
std::string publicKey;
|
||||
|
||||
// Wireguard port listen
|
||||
unsigned short portListen = 0;
|
||||
unsigned short portListen;
|
||||
|
||||
// FirewallMark specifies a device's firewall mark
|
||||
// else set to 0, the firewall mark will be cleared.
|
||||
int fwmark = -1;
|
||||
int fwmark;
|
||||
|
||||
// Interface address'es
|
||||
std::vector<std::string> Address;
|
||||
@ -146,24 +143,39 @@ class setConfig : public Napi::AsyncWorker {
|
||||
bool replacePeers = false;
|
||||
|
||||
// Wireguard peers, Map: <publicKey(std::string), Peer>
|
||||
std::map<std::string, Peer> peersVector;
|
||||
public:
|
||||
const Napi::Promise::Deferred setPromise;
|
||||
std::map<std::string, Peer> Peers;
|
||||
|
||||
ConfigBase() {
|
||||
this->fwmark = 0;
|
||||
this->portListen = 0;
|
||||
}
|
||||
~ConfigBase() {
|
||||
this->Address.clear();
|
||||
this->Peers.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set configuration in interface
|
||||
*/
|
||||
void setWireguardConfig();
|
||||
/**
|
||||
* Get configuration from interface and insert in class
|
||||
*/
|
||||
void getWireguardConfig();
|
||||
};
|
||||
|
||||
/*
|
||||
Configure uma interface do Wireguard.
|
||||
*/
|
||||
class setConfig : public GlobalPromise, ConfigBase {
|
||||
public:
|
||||
void OnOK() override {
|
||||
Napi::HandleScope scope(Env());
|
||||
// Callback().Call({ Env().Undefined() });
|
||||
setPromise.Resolve(Env().Undefined());
|
||||
Promised.Resolve(Env().Undefined());
|
||||
};
|
||||
|
||||
void OnError(const Napi::Error& e) override {
|
||||
Napi::HandleScope scope(Env());
|
||||
// Callback().Call({ e.Value() });
|
||||
setPromise.Reject(e.Value());
|
||||
}
|
||||
|
||||
~setConfig() {}
|
||||
setConfig(const Napi::Env env, std::string name, const Napi::Object &config) : AsyncWorker(env), wgName{name}, setPromise{env} {
|
||||
setConfig(const Napi::Env env, std::string name, const Napi::Object &config) : GlobalPromise(env) {
|
||||
// Wireguard public key
|
||||
const auto sppk = config.Get("publicKey");
|
||||
if (sppk.IsString()) {
|
||||
@ -201,14 +213,14 @@ class setConfig : public Napi::AsyncWorker {
|
||||
// Peers
|
||||
const auto speers = config.Get("peers");
|
||||
if (speers.IsObject()) {
|
||||
const Napi::Object Peers = speers.ToObject();
|
||||
const Napi::Array Keys = Peers.GetPropertyNames();
|
||||
const Napi::Object PeersObject = speers.ToObject();
|
||||
const Napi::Array Keys = PeersObject.GetPropertyNames();
|
||||
for (unsigned int peerIndex = 0; peerIndex < Keys.Length(); peerIndex++) {
|
||||
const auto peerPubKey = Keys[peerIndex];
|
||||
if (peerPubKey.IsString() && Peers.Get(Keys[peerIndex]).IsObject()) {
|
||||
if (peerPubKey.IsString() && PeersObject.Get(Keys[peerIndex]).IsObject()) {
|
||||
std::string ppkey = peerPubKey.ToString().Utf8Value();
|
||||
if (ppkey.length() != B64_WG_KEY_LENGTH) throw Napi::Error::New(env, std::string("Set valid peer publicKey, value: ").append(ppkey));
|
||||
const Napi::Object peerConfigObject = Peers.Get(Keys[peerIndex]).ToObject();
|
||||
const Napi::Object peerConfigObject = PeersObject.Get(Keys[peerIndex]).ToObject();
|
||||
|
||||
Peer peerConfig = Peer();
|
||||
const auto removeMe = peerConfigObject.Get("removeMe");
|
||||
@ -240,52 +252,33 @@ class setConfig : public Napi::AsyncWorker {
|
||||
}
|
||||
|
||||
// Insert peer
|
||||
peersVector[ppkey] = peerConfig;
|
||||
this->Peers[ppkey] = peerConfig;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Set platform Execute script
|
||||
void Execute() override;
|
||||
void Execute() override {
|
||||
try {
|
||||
this->setWireguardConfig();
|
||||
} catch (std::string &err) {
|
||||
SetError(err);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class getConfig : public Napi::AsyncWorker {
|
||||
private:
|
||||
// Wireguard interface name (required)
|
||||
std::string wgName;
|
||||
|
||||
// Wireguard private key (required)
|
||||
std::string privateKey;
|
||||
|
||||
// Wireguard interface publicKey <optional>
|
||||
std::string publicKey;
|
||||
|
||||
// Wireguard port listen
|
||||
unsigned int portListen;
|
||||
|
||||
// FirewallMark specifies a device's firewall mark
|
||||
// else set to 0, the firewall mark will be cleared.
|
||||
int fwmark = -1;
|
||||
|
||||
// Interface address'es
|
||||
std::vector<std::string> Address;
|
||||
|
||||
/*
|
||||
Wireguard peers
|
||||
Map: <publicKey, Peer>
|
||||
*/
|
||||
std::map<std::string, Peer> peersVector;
|
||||
class getConfig : public GlobalPromise, ConfigBase {
|
||||
public:
|
||||
~getConfig() {}
|
||||
getConfig(const Napi::Env env, std::string name): AsyncWorker(env), wgName{name}, getPromise{env} {}
|
||||
const Napi::Promise::Deferred getPromise;
|
||||
|
||||
void OnError(const Napi::Error& e) override {
|
||||
Napi::HandleScope scope(Env());
|
||||
getPromise.Reject(e.Value());
|
||||
getConfig(const Napi::Env env, std::string name): GlobalPromise(env) {}
|
||||
void Execute() override {
|
||||
try {
|
||||
this->getWireguardConfig();
|
||||
} catch (std::string &err) {
|
||||
SetError(err);
|
||||
}
|
||||
}
|
||||
|
||||
void OnOK() override {
|
||||
Napi::HandleScope scope(Env());
|
||||
const Napi::Env env = Env();
|
||||
@ -303,7 +296,7 @@ class getConfig : public Napi::AsyncWorker {
|
||||
|
||||
// Peer object
|
||||
const auto PeersObject = Napi::Object::New(env);
|
||||
for (auto &peer : peersVector) {
|
||||
for (auto &peer : this->Peers) {
|
||||
const auto PeerObject = Napi::Object::New(env);
|
||||
auto peerConfig = peer.second;
|
||||
|
||||
@ -330,9 +323,6 @@ class getConfig : public Napi::AsyncWorker {
|
||||
config.Set("peers", PeersObject);
|
||||
|
||||
// Resolve config json
|
||||
getPromise.Resolve(config);
|
||||
Promised.Resolve(config);
|
||||
};
|
||||
|
||||
// Set platform Execute script
|
||||
void Execute() override;
|
||||
};
|
||||
|
@ -46,6 +46,6 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"node-addon-api": "^7.1.0",
|
||||
"rebory": "^0.1.12"
|
||||
"rebory": "^0.2.4"
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
export * as key from "./key.js";
|
||||
export * as wgQuick from "./quick.js";
|
||||
export * as key from "./key.js";
|
||||
|
||||
export * from "./wginterface.js";
|
||||
export * as wginterface from "./wginterface.js";
|
||||
export * as default from "./wginterface.js";
|
||||
export * as wginterface from "./wginterface.js";
|
@ -1,45 +1,33 @@
|
||||
import { promises as fs } from "fs";
|
||||
import { isIPv4, createConnection as netConnection } from "net";
|
||||
import path from "path";
|
||||
import readline from "readline";
|
||||
import { finished } from "stream/promises";
|
||||
import rebory from "rebory";
|
||||
import { fileURLToPath } from "url";
|
||||
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
const addon = rebory.loadAddon(path.join(__dirname, "../binding.yaml")).wginterface.loadRelease<{
|
||||
listDevices?: () => Promise<{from: "userspace"|"kernel", name: string, path?: string}[]>;
|
||||
deleteInterface?: (wgName: string) => Promise<void>;
|
||||
const addon = (await rebory.loadAddon(path.join(__dirname, "../binding.yaml"))).wginterface.load_addon<{
|
||||
setConfig?: (wgName: string, config: WgConfigSet) => Promise<void>;
|
||||
getConfig?: (wgName: string) => Promise<WgConfigGet>;
|
||||
listDevices?: () => Promise<string[]>;
|
||||
deleteInterface?: (wgName: string) => Promise<void>;
|
||||
|
||||
createTun?: () => Promise<number|string>;
|
||||
deleteTun?: () => void;
|
||||
checkTun?: () => Promise<boolean>;
|
||||
getTun?: () => Promise<number|string>;
|
||||
/**
|
||||
* Wireguard addon userspace
|
||||
*/
|
||||
userspace: {
|
||||
createTun?: () => Promise<number|string>;
|
||||
deleteTun?: () => void;
|
||||
checkTun?: () => Promise<boolean>;
|
||||
getTunPath?: () => Promise<number|string>;
|
||||
};
|
||||
|
||||
/** Wireguard addon constants */
|
||||
constants: {
|
||||
driveVersion: string;
|
||||
base64Length: number;
|
||||
keyLength: number;
|
||||
driveVersion: string|null;
|
||||
nameLength: number;
|
||||
};
|
||||
}>({
|
||||
WIN32DLLPATH: path.resolve(__dirname, "../addons/tools/win/wireguard-nt/bin", ((process.arch === "x64" && "amd64") || (process.arch === "ia32" && "i386"))||process.arch, "wireguard.dll")
|
||||
});
|
||||
|
||||
export const {
|
||||
constants
|
||||
} = addon;
|
||||
|
||||
/** default location to run socket's */
|
||||
const defaultPath = (process.env.WIRWGUARD_GO_RUN||"").length > 0 ? path.resolve(process.cwd(), process.env.WIRWGUARD_GO_RUN) : process.platform === "win32" ? "\\\\.\\pipe\\WireGuard" : "/var/run/wireguard";
|
||||
|
||||
async function exists(path: string) {
|
||||
return fs.open(path).then(o => o && (o.close().then(() => true, () => true))||true, () => false);
|
||||
}
|
||||
|
||||
export interface Peer {
|
||||
/** Preshared key to peer */
|
||||
presharedKey?: string;
|
||||
@ -99,151 +87,71 @@ export interface WgConfigSet extends WgConfigBase<PeerSet> {
|
||||
export type WgGlobalConfig = WgConfigSet & WgConfigGet;
|
||||
|
||||
/**
|
||||
* Get Wireguard devices and locations
|
||||
* Userspace wireguard
|
||||
*/
|
||||
export async function listDevices() {
|
||||
let devices: {from: "userspace"|"kernel", name: string, path?: string}[] = [];
|
||||
if (typeof addon.listDevices === "function") devices = devices.concat(await addon.listDevices());
|
||||
if (await exists(defaultPath)) (await fs.readdir(defaultPath)).forEach(file => devices.push({ from: "userspace", name: file.endsWith(".sock") ? file.slice(0, -5) : file, path: path.join("/var/run/wireguard", file) }));
|
||||
return devices;
|
||||
export namespace Userspace {
|
||||
/**
|
||||
* Set Wireguard interface configuration
|
||||
* @param name - Interface name
|
||||
* @param config - Interface config
|
||||
*/
|
||||
export async function SetConfig(name: string, config: WgConfigSet) {}
|
||||
|
||||
/**
|
||||
* Get Wireguard interface config if exist
|
||||
* @param name - Interface name
|
||||
*/
|
||||
export async function GetConfig(name: string): Promise<WgConfigGet> { return null; }
|
||||
|
||||
/**
|
||||
* List Wireguard userspace devices
|
||||
* @returns Wireguard userspace devices
|
||||
*/
|
||||
export async function ListDevices(): Promise<{name: string, path?: string}[]> { return []; }
|
||||
|
||||
/**
|
||||
* Delete Wireguard Userspace interface
|
||||
* @param name - Interface name
|
||||
*/
|
||||
export async function DeleteDevice(name: string) {}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete wireguard interface if present
|
||||
* @param wgName - Interface name
|
||||
* @returns
|
||||
*/
|
||||
export async function deleteInterface(wgName: string): Promise<void> {
|
||||
if (typeof addon.deleteInterface === "function") return addon.deleteInterface(wgName);
|
||||
const dev = (await listDevices()).find(s => s.name === wgName);
|
||||
if (dev && dev.path) return fs.rm(dev.path, { force: true });
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the settings to the Wireguard interface, if it does not exist and the interface will be created automatically.
|
||||
*
|
||||
* To update the interface settings, first get the interface settings to update!
|
||||
*
|
||||
* @param wgName - Interface name
|
||||
* @param config - Interface config
|
||||
*/
|
||||
export async function setConfig(wgName: string, config: WgConfigGet): Promise<void>;
|
||||
/**
|
||||
* Add the settings to the Wireguard interface, if it does not exist and the interface will be created automatically.
|
||||
*
|
||||
* To update the interface settings, first get the interface settings to update!
|
||||
*
|
||||
* @param wgName - Interface name
|
||||
* @param config - Interface config
|
||||
*/
|
||||
export async function setConfig(wgName: string, config: WgConfigSet): Promise<void> {
|
||||
if (wgName.length > constants.nameLength) throw new Error("Interface name more then allowed", { cause: constants.nameLength });
|
||||
if (typeof addon.setConfig === "function") return addon.setConfig(wgName, config);
|
||||
const client = netConnection(path.join(defaultPath, (wgName).concat(".sock")));
|
||||
const writel = (...data: any[]) => client.write(data.map(String).join("").concat("\n"));
|
||||
// Init set config in interface
|
||||
writel("set=1");
|
||||
|
||||
// Port listening
|
||||
if (config.portListen !== undefined && Math.floor(config.portListen) >= 0) writel(("listen_port="), ((Math.floor(config.portListen))));
|
||||
|
||||
// fwmark
|
||||
if (Math.floor(config.fwmark) >= 0) writel(("fwmark="), ((Math.floor(config.fwmark))));
|
||||
|
||||
// Replace peer's
|
||||
if (config.replacePeers) writel("replace_peers=true");
|
||||
|
||||
// Keys
|
||||
if (typeof config.privateKey === "string" && config.privateKey.length > 0) writel(("private_key="), (Buffer.from(config.privateKey, "base64").toString("hex")));
|
||||
|
||||
// Mount peer
|
||||
for (const publicKey of Object.keys(config.peers||{})) {
|
||||
const { presharedKey, endpoint, keepInterval, removeMe, allowedIPs = [] } = config.peers[publicKey];
|
||||
|
||||
// Public key
|
||||
writel(("public_key="), (Buffer.from(publicKey, "base64").toString("hex")));
|
||||
if (removeMe) {
|
||||
writel("remove=true"); // Remove peer
|
||||
continue;
|
||||
}
|
||||
|
||||
if (typeof endpoint === "string" && endpoint.length > 0) writel(("endpoint="), (endpoint));
|
||||
if (typeof presharedKey === "string" && presharedKey.length > 3) writel(("preshared_key="), (Buffer.from(presharedKey, "base64").toString("hex")));
|
||||
if (typeof keepInterval === "number" && Math.floor(keepInterval) > 0) writel(("persistent_keepalive_interval="), (String(Math.floor(keepInterval))));
|
||||
if (allowedIPs.length > 0) {
|
||||
writel("replace_allowed_ips=true");
|
||||
const fixed = allowedIPs.map(i => i.indexOf("/") === -1 ? i.concat("/", (isIPv4(i) ? "32" : "128")) : i)
|
||||
for (const IIP of fixed) writel(("allowed_ip="), (IIP));
|
||||
}
|
||||
* Kernel Wireguard
|
||||
*/
|
||||
export namespace Kernel {
|
||||
export const { constants: { driveVersion, nameLength } } = addon;
|
||||
/**
|
||||
* Set Wireguard interface configuration and if not exists create
|
||||
*
|
||||
* @param name - Wireguard interface name
|
||||
* @param config - Interface configuration
|
||||
*/
|
||||
export async function SetConfig(name: string, config: WgConfigSet) {
|
||||
await addon.setConfig(name, config);
|
||||
}
|
||||
|
||||
let payload = "";
|
||||
client.once("data", function processBuff(buff) {
|
||||
payload = payload.concat(buff.toString("utf8"));
|
||||
if (payload[payload.length - 1] === "\n" && payload[payload.length - 2] === "\n") {
|
||||
client.end(); // Close conenction
|
||||
return;
|
||||
}
|
||||
client.once("data", processBuff);
|
||||
});
|
||||
client.write("\n");
|
||||
await finished(client, { error: true });
|
||||
const payloadKeys = payload.split("\n").filter(i => i.length > 3).map(line => { const iit = line.indexOf("="); return [ line.slice(0, iit), line.slice(iit+1) ]; })
|
||||
if (payloadKeys.at(-1)[1] !== "0") {
|
||||
const err = new Error("Invalid send config, check log");
|
||||
throw err;
|
||||
/**
|
||||
* Get Wireguard interface configuration
|
||||
* @param name - Wireguard interface name
|
||||
*/
|
||||
export async function GetConfig(name: string): Promise<WgConfigGet> {
|
||||
return addon.getConfig(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Lista Wireguard interfaces
|
||||
* @returns Devices
|
||||
*/
|
||||
export async function ListDevices(): Promise<string[]> {
|
||||
return addon.listDevices();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete Wireguard interface
|
||||
* @param name - Wireguard interface name
|
||||
*/
|
||||
export async function DeleteDevice(name: string) {
|
||||
return addon.deleteInterface(name);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get wireguard interface config
|
||||
* @param wgName - Interface name
|
||||
* @returns
|
||||
*/
|
||||
export async function getConfig(wgName: string): Promise<WgConfigGet> {
|
||||
if (typeof addon.getConfig === "function") return addon.getConfig(wgName);
|
||||
const info = (await listDevices()).find(int => int.name === wgName);
|
||||
if (!info) throw new Error("Create interface, not exists");
|
||||
const client = netConnection(path.join(defaultPath, wgName.concat(".sock")));
|
||||
const config: WgConfigGet = Object();
|
||||
let latestPeer: string, previewKey: string;
|
||||
|
||||
const tetrisBreak = readline.createInterface(client);
|
||||
tetrisBreak.on("line", function lineProcess(line) {
|
||||
if (line === "") tetrisBreak.removeListener("line", lineProcess).close();
|
||||
const findout = line.indexOf("="), keyName = line.slice(0, findout), value = line.slice(findout+1);
|
||||
if (findout <= 0) return;
|
||||
if (keyName === "errno" && value !== "0") throw new Error(("wireguard-go error, code: ").concat(value));
|
||||
|
||||
// Drop
|
||||
if ((["last_handshake_time_nsec", "protocol_version", "errno"]).includes(keyName)) return;
|
||||
else if (keyName === "private_key") config.privateKey = Buffer.from(value, "hex").toString("base64");
|
||||
else if (keyName === "listen_port") config.portListen = Number(value);
|
||||
else if (keyName === "endpoint") ((config.peers||(config.peers = {}))[latestPeer]).endpoint = value;
|
||||
else if (keyName === "persistent_keepalive_interval") ((config.peers||(config.peers = {}))[latestPeer]).keepInterval = Number(value);
|
||||
else if (keyName === "rx_bytes") ((config.peers||(config.peers = {}))[latestPeer]).rxBytes = Number(value);
|
||||
else if (keyName === "tx_bytes") ((config.peers||(config.peers = {}))[latestPeer]).txBytes = Number(value);
|
||||
else if (keyName === "last_handshake_time_sec") ((config.peers||(config.peers = {}))[latestPeer]).lastHandshake = new Date(Number(value) * 1000);
|
||||
else if (keyName === "allowed_ip") {
|
||||
if (!value) return;
|
||||
((config.peers||(config.peers = {}))[latestPeer]).allowedIPs = (((config.peers||(config.peers = {}))[latestPeer]).allowedIPs||[]).concat(value);
|
||||
} else if (keyName === "preshared_key") {
|
||||
if (value === "0000000000000000000000000000000000000000000000000000000000000000") return;
|
||||
((config.peers||(config.peers = {}))[latestPeer]).presharedKey = Buffer.from(value, "hex").toString("base64");
|
||||
} else if (keyName === "public_key") {
|
||||
const keyDecode = Buffer.from(value, "hex").toString("base64");
|
||||
if (previewKey !== "public_key") (config.peers||(config.peers = {}))[latestPeer] = {};
|
||||
else {
|
||||
config.publicKey = latestPeer;
|
||||
(config.peers||(config.peers = {}))[keyDecode] = (config.peers||(config.peers = {}))[latestPeer];
|
||||
delete (config.peers||(config.peers = {}))[latestPeer];
|
||||
latestPeer = keyDecode;
|
||||
}
|
||||
}
|
||||
previewKey = keyName;
|
||||
});
|
||||
client.write("get=1\n\n");
|
||||
await new Promise((done, reject) => tetrisBreak.on("error", reject).once("close", done));
|
||||
await finished(client.end());
|
||||
return config;
|
||||
}
|
@ -1,10 +1,10 @@
|
||||
import test from "node:test";
|
||||
import { setConfig, deleteInterface, WgConfigSet, getConfig } from "./wginterface.js";
|
||||
import { Kernel, Userspace, WgConfigSet } from "./wginterface.js";
|
||||
import { publicKey } from "./key.js";
|
||||
import { userInfo } from "os";
|
||||
|
||||
if (process.platform === "win32" || process.platform === "linux" && (userInfo().uid === 0)) {
|
||||
test("Wireguard configuration", async t => {
|
||||
await test(String.prototype.concat("Wireguard kernel (", Kernel.driveVersion, ")"), async t => {
|
||||
// Config base
|
||||
const peer1Key = 'EKgSatFzZtsv1qFJ6gE8HqfuA+tXzW+7vDeVc7Xaa2E=', peer2Key = '4BSvgiM9j5jjuR0Vg3gbqTFD5+CyuOU2K2kJE5+cakQ=',
|
||||
config: WgConfigSet = {
|
||||
@ -22,11 +22,11 @@ if (process.platform === "win32" || process.platform === "linux" && (userInfo().
|
||||
}
|
||||
|
||||
await t.test("Set config in interface", async () => {
|
||||
await setConfig("wg23", config);
|
||||
await Kernel.SetConfig("wg23", config);
|
||||
});
|
||||
|
||||
await t.test("Get config in interface", async () => {
|
||||
const __config = await getConfig("wg23");
|
||||
const __config = await Kernel.GetConfig("wg23");
|
||||
if (!__config.peers[publicKey(peer1Key)]) throw new Error("Not exist peer 1!");
|
||||
});
|
||||
|
||||
@ -38,17 +38,21 @@ if (process.platform === "win32" || process.platform === "linux" && (userInfo().
|
||||
}
|
||||
|
||||
await t.test("Set config in interface", async () => {
|
||||
await setConfig("wg23", config);
|
||||
await Kernel.SetConfig("wg23", config);
|
||||
});
|
||||
|
||||
await t.test("Get config in interface", async () => {
|
||||
const __config = await getConfig("wg23");
|
||||
const __config = await Kernel.GetConfig("wg23");
|
||||
if (__config.peers[publicKey(peer1Key)]) throw new Error("Invalid config get!");
|
||||
if (!__config.peers[publicKey(peer2Key)]) throw new Error("Not exist peer 2!");
|
||||
});
|
||||
|
||||
await t.test("Delete interface", async () => {
|
||||
await deleteInterface("wg23");
|
||||
await Kernel.DeleteDevice("wg23");
|
||||
});
|
||||
});
|
||||
|
||||
await test("Wireguard Userspace", async t => {
|
||||
Userspace;
|
||||
});
|
||||
}
|
@ -18,10 +18,7 @@
|
||||
]
|
||||
},
|
||||
"exclude": [
|
||||
"**/libs/**",
|
||||
"**/docs/**",
|
||||
"node_modules/",
|
||||
"index.mjs"
|
||||
"node_modules/"
|
||||
],
|
||||
"ts-node": {
|
||||
"files": true,
|
||||
|
Loading…
x
Reference in New Issue
Block a user