335 lines
11 KiB
C++
335 lines
11 KiB
C++
#pragma once
|
|
#include <napi.h>
|
|
#include <string>
|
|
#include <vector>
|
|
#include <map>
|
|
#include <wgkeys.hh>
|
|
|
|
// Get wireguard max name length
|
|
unsigned long maxName();
|
|
|
|
// Get wireguard version
|
|
std::string versionDrive();
|
|
|
|
// On start module call this function
|
|
std::string startAddon(const Napi::Env env);
|
|
|
|
class deleteInterface : public Napi::AsyncWorker {
|
|
private:
|
|
std::string wgName;
|
|
public:
|
|
deleteInterface(const Napi::Env env, std::string name): AsyncWorker(env), deletePromise{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());
|
|
};
|
|
|
|
// Set platform Execute script
|
|
void Execute() override;
|
|
};
|
|
|
|
class listInfo {
|
|
public:
|
|
std::string tunType, pathSock;
|
|
};
|
|
|
|
class listDevices : public Napi::AsyncWorker {
|
|
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());
|
|
}
|
|
|
|
void OnOK() override {
|
|
Napi::HandleScope scope(Env());
|
|
const Napi::Env env = Env();
|
|
const auto deviceArray = Napi::Array::New(env);
|
|
for (auto it : deviceNames) {
|
|
auto name = it.first; auto infoSrc = it.second;
|
|
auto info = Napi::Object::New(env);
|
|
info.Set("name", name);
|
|
info.Set("from", infoSrc.tunType);
|
|
if (infoSrc.pathSock.size() > 0) info.Set("path", infoSrc.pathSock);
|
|
deviceArray.Set(deviceArray.Length(), info);
|
|
}
|
|
listDevicesPromise.Resolve(deviceArray);
|
|
};
|
|
void Execute() override;
|
|
};
|
|
|
|
class Peer {
|
|
public:
|
|
// 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;
|
|
|
|
// AllowedIPs specifies which IPv4 and IPv6 addresses this peer is allowed
|
|
// to communicate on.
|
|
//
|
|
// 0.0.0.0/0 indicates that all IPv4 addresses are allowed, and ::/0
|
|
// indicates that all IPv6 addresses are allowed.
|
|
std::vector<std::string> allowedIPs;
|
|
|
|
// 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 = 0;
|
|
|
|
// LastHandshakeTime indicates the most recent time a handshake was performed
|
|
// with this peer.
|
|
//
|
|
// A zero-value time.Time indicates that no handshake has taken place with
|
|
// this peer.
|
|
long long last_handshake = 0;
|
|
|
|
// rxBytes indicates the number of bytes received from this peer.
|
|
unsigned long long rxBytes = 0;
|
|
|
|
// txBytes indicates the number of bytes transmitted to this peer.
|
|
unsigned long long txBytes = 0;
|
|
|
|
// ProtocolVersion specifies which version of the WireGuard protocol is used
|
|
// for this Peer.
|
|
//
|
|
// A value of 0 indicates that the most recent protocol version will be used.
|
|
int ProtocolVersion = 0;
|
|
};
|
|
|
|
/*
|
|
Configure uma interface do Wireguard.
|
|
*/
|
|
class setConfig : 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 short portListen = 0;
|
|
|
|
// 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;
|
|
|
|
// Replace peers
|
|
bool replacePeers = false;
|
|
|
|
// Wireguard peers, Map: <publicKey(std::string), Peer>
|
|
std::map<std::string, Peer> peersVector;
|
|
public:
|
|
const Napi::Promise::Deferred setPromise;
|
|
|
|
void OnOK() override {
|
|
Napi::HandleScope scope(Env());
|
|
// Callback().Call({ Env().Undefined() });
|
|
setPromise.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), setPromise{env}, wgName{name} {
|
|
// Wireguard public key
|
|
const auto sppk = config.Get("publicKey");
|
|
if (sppk.IsString()) {
|
|
publicKey = sppk.ToString().Utf8Value();
|
|
if (publicKey.length() != B64_WG_KEY_LENGTH) throw Napi::Error::New(env, "Set valid publicKey");
|
|
}
|
|
|
|
// Private key
|
|
const auto sprk = config.Get("privateKey");
|
|
if (!(sprk.IsString())) throw Napi::Error::New(env, "privateKey is empty");
|
|
privateKey = sprk.ToString().Utf8Value();
|
|
if (privateKey.length() != B64_WG_KEY_LENGTH) throw Napi::Error::New(env, (std::string("Set valid privateKey ")).append(std::to_string(privateKey.length())));
|
|
|
|
// Port to listen Wireguard interface
|
|
const auto spor = config.Get("portListen");
|
|
if (spor.IsNumber() && (spor.ToNumber().Int32Value() >= 0 && spor.ToNumber().Int32Value() <= 65535)) portListen = spor.ToNumber().Int32Value();
|
|
|
|
// Firewall mark
|
|
const auto sfw = config.Get("fwmark");
|
|
if (sfw.IsNumber() && (sfw.ToNumber().Uint32Value() >= 0)) fwmark = sfw.ToNumber().Uint32Value();
|
|
else fwmark = -1;
|
|
|
|
const auto saddr = config.Get("Address");
|
|
if (saddr.IsArray()) {
|
|
const Napi::Array addrs = saddr.As<Napi::Array>();
|
|
for (unsigned int i = 0; i < addrs.Length(); i++) {
|
|
if (addrs.Get(i).IsString()) Address.push_back(addrs.Get(i).ToString().Utf8Value());
|
|
}
|
|
}
|
|
|
|
// Replace peers
|
|
const auto srpee = config.Get("replacePeers");
|
|
if (srpee.IsBoolean()) replacePeers = srpee.ToBoolean().Value();
|
|
|
|
// Peers
|
|
const auto speers = config.Get("peers");
|
|
if (speers.IsObject()) {
|
|
const Napi::Object Peers = speers.ToObject();
|
|
const Napi::Array Keys = Peers.GetPropertyNames();
|
|
for (unsigned int peerIndex = 0; peerIndex < Keys.Length(); peerIndex++) {
|
|
const auto peerPubKey = Keys[peerIndex];
|
|
if (peerPubKey.IsString() && Peers.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();
|
|
|
|
Peer peerConfig = Peer();
|
|
const auto removeMe = peerConfigObject.Get("removeMe");
|
|
if (removeMe.IsBoolean() && removeMe.ToBoolean().Value()) peerConfig.removeMe = true;
|
|
else {
|
|
// Preshared key
|
|
const auto pprekey = peerConfigObject.Get("presharedKey");
|
|
if (pprekey.IsString()) {
|
|
peerConfig.presharedKey = pprekey.ToString().Utf8Value();
|
|
if (peerConfig.presharedKey.length() != B64_WG_KEY_LENGTH) throw Napi::Error::New(env, "Set valid peer presharedKey");
|
|
}
|
|
|
|
// Keep interval
|
|
const auto pKeepInterval = peerConfigObject.Get("keepInterval");
|
|
if (pKeepInterval.IsNumber() && (pKeepInterval.ToNumber().Int32Value() > 0 && pKeepInterval.ToNumber().Int32Value() <= 65535)) peerConfig.keepInterval = pKeepInterval.ToNumber().Int32Value();
|
|
|
|
// Peer endpoint
|
|
const auto pEndpoint = peerConfigObject.Get("endpoint");
|
|
if (pEndpoint.IsString()) peerConfig.endpoint = pEndpoint.ToString().Utf8Value();
|
|
|
|
// Allowed ip's array
|
|
const auto pAllowedIPs = peerConfigObject.Get("allowedIPs");
|
|
if (pAllowedIPs.IsArray()) {
|
|
const auto AllowedIps = pAllowedIPs.As<Napi::Array>();
|
|
for (uint32_t allIndex = 0; allIndex < AllowedIps.Length(); allIndex++) {
|
|
if (AllowedIps.Get(allIndex).IsString()) peerConfig.allowedIPs.push_back(AllowedIps.Get(allIndex).ToString().Utf8Value());
|
|
}
|
|
}
|
|
}
|
|
|
|
// Insert peer
|
|
peersVector[ppkey] = peerConfig;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Set platform Execute script
|
|
void Execute() override;
|
|
};
|
|
|
|
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
|
|
uint32_t 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;
|
|
public:
|
|
~getConfig() {}
|
|
getConfig(const Napi::Env env, std::string name): AsyncWorker(env), getPromise{env}, wgName{name} {}
|
|
const Napi::Promise::Deferred getPromise;
|
|
|
|
void OnError(const Napi::Error& e) override {
|
|
Napi::HandleScope scope(Env());
|
|
getPromise.Reject(e.Value());
|
|
}
|
|
|
|
void OnOK() override {
|
|
Napi::HandleScope scope(Env());
|
|
const Napi::Env env = Env();
|
|
const auto config = Napi::Object::New(env);
|
|
|
|
if (privateKey.length() == B64_WG_KEY_LENGTH) config.Set("privateKey", privateKey);
|
|
if (publicKey.length() == B64_WG_KEY_LENGTH) config.Set("publicKey", publicKey);
|
|
if (portListen >= 0 && portListen <= 65535) config.Set("portListen", portListen);
|
|
if (fwmark >= 0) config.Set("fwmark", fwmark);
|
|
if (Address.size() > 0) {
|
|
const auto Addrs = Napi::Array::New(env);
|
|
for (auto &addr : Address) Addrs.Set(Addrs.Length(), addr);
|
|
config.Set("Address", Addrs);
|
|
}
|
|
|
|
// Peer object
|
|
const auto PeersObject = Napi::Object::New(env);
|
|
for (auto &peer : peersVector) {
|
|
const auto PeerObject = Napi::Object::New(env);
|
|
const std::string peerPubKey = peer.first;
|
|
auto peerConfig = peer.second;
|
|
|
|
if (peerConfig.presharedKey.length() == B64_WG_KEY_LENGTH) PeerObject.Set("presharedKey", peerConfig.presharedKey);
|
|
if (peerConfig.keepInterval > 0 && peerConfig.keepInterval <= 65535) PeerObject.Set("keepInterval", peerConfig.keepInterval);
|
|
if (peerConfig.endpoint.length() > 0) PeerObject.Set("endpoint", peerConfig.endpoint);
|
|
if (peerConfig.last_handshake >= 0) PeerObject.Set("lastHandshake", Napi::Date::New(env, peerConfig.last_handshake));
|
|
// if (peerConfig.last_handshake >= 0) PeerObject.Set("lastHandshake", peerConfig.last_handshake);
|
|
if (peerConfig.rxBytes >= 0) PeerObject.Set("rxBytes", peerConfig.rxBytes);
|
|
if (peerConfig.txBytes >= 0) PeerObject.Set("txBytes", peerConfig.txBytes);
|
|
if (peerConfig.allowedIPs.size() > 0) {
|
|
const auto allowedIPs = Napi::Array::New(env);
|
|
for (auto &ip : peerConfig.allowedIPs) allowedIPs.Set(allowedIPs.Length(), ip);
|
|
PeerObject.Set("allowedIPs", allowedIPs);
|
|
}
|
|
|
|
PeersObject.Set(peerPubKey, PeerObject);
|
|
}
|
|
config.Set("peers", PeersObject);
|
|
|
|
// Resolve config json
|
|
getPromise.Resolve(config);
|
|
};
|
|
|
|
// Set platform Execute script
|
|
void Execute() override;
|
|
};
|