mirror of https://github.com/wg-easy/wg-easy
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
209 lines
5.2 KiB
209 lines
5.2 KiB
'use strict';
|
|
|
|
const fs = require('fs').promises;
|
|
const path = require('path');
|
|
|
|
const QRCode = require('qrcode');
|
|
|
|
const Util = require('./Util');
|
|
const ServerError = require('./ServerError');
|
|
|
|
const {
|
|
WG_PATH,
|
|
WG_HOST,
|
|
WG_PORT,
|
|
WG_DEFAULT_DNS,
|
|
WG_DEFAULT_ADDRESS,
|
|
} = require('../config');
|
|
|
|
module.exports = class WireGuard {
|
|
|
|
async getConfig() {
|
|
if (!this.__configPromise) {
|
|
this.__configPromise = Promise.resolve().then(async () => {
|
|
let config;
|
|
try {
|
|
config = await fs.readFile(path.join(WG_PATH, 'wg0.json'), 'utf8');
|
|
config = JSON.parse(config);
|
|
} catch (err) {
|
|
config = {
|
|
server: {
|
|
// TODO: Generate new config
|
|
address: WG_DEFAULT_ADDRESS,
|
|
dns: WG_DEFAULT_DNS,
|
|
},
|
|
clients: {},
|
|
};
|
|
}
|
|
|
|
return config;
|
|
});
|
|
}
|
|
|
|
return this.__configPromise;
|
|
}
|
|
|
|
async saveConfig() {
|
|
const config = await this.getConfig();
|
|
let result = `
|
|
# Note: Do not edit this file directly.
|
|
# Your changes will be overwritten!
|
|
|
|
# Server
|
|
[Interface]
|
|
PrivateKey = ${config.server.privateKey}
|
|
Address = ${config.server.address}
|
|
ListenPort = ${config.server.port}
|
|
DNS = ${config.server.dns}`;
|
|
|
|
for (const [clientId, client] of Object.entries(config.clients)) {
|
|
if (!client.enabled) continue;
|
|
|
|
result += `
|
|
|
|
# Client: ${client.name} (${clientId})
|
|
[Peer]
|
|
PublicKey = ${client.publicKey}
|
|
PresharedKey = ${client.preSharedKey}
|
|
AllowedIPs = ${client.allowedIPs}`;
|
|
}
|
|
|
|
await fs.writeFile(path.join(WG_PATH, 'wg0.json'), JSON.stringify(config, false, 2));
|
|
await fs.writeFile(path.join(WG_PATH, 'wg0.conf'), result);
|
|
}
|
|
|
|
async getClients() {
|
|
const config = await this.getConfig();
|
|
const clients = Object.entries(config.clients).map(([clientId, client]) => ({
|
|
id: clientId,
|
|
name: client.name,
|
|
enabled: client.enabled,
|
|
publicKey: client.publicKey,
|
|
createdAt: new Date(client.createdAt),
|
|
updatedAt: new Date(client.updatedAt),
|
|
allowedIPs: client.allowedIPs,
|
|
|
|
persistentKeepalive: null,
|
|
latestHandshakeAt: null,
|
|
transferRx: null,
|
|
transferTx: null,
|
|
}));
|
|
|
|
// Loop WireGuard status
|
|
const clientsDump = await Util.exec('wg show wg0 dump');
|
|
// const clientsDump = `iOQJS7OUUGPYATsX6nqlL+sOODoiWiN5IOE8Msfw/0o= BkdntwYazhYZzEEHhcYayq6TGw9/YUDQ251s+5bTgC0= 51820 off
|
|
// i8xWKqicnDkNL14I4B+I1zlB8od/booA1joIosWn7X4= MzplKtOQ44/IaAKri2VKqCoIlg4XiVH7TCp5bcYRTQU= 172.17.0.1:60475 10.8.0.2/32 1621679257 7920 7440 off`;
|
|
clientsDump
|
|
.trim()
|
|
.split('\n')
|
|
.slice(1)
|
|
.forEach(line => {
|
|
const [
|
|
publicKey,
|
|
preSharedKey, // eslint-disable-line no-unused-vars
|
|
endpoint,
|
|
allowedIps, // eslint-disable-line no-unused-vars
|
|
latestHandshakeAt,
|
|
transferRx,
|
|
transferTx,
|
|
persistentKeepalive,
|
|
] = line.split('\t');
|
|
|
|
const client = clients.find(client => client.publicKey === publicKey);
|
|
if (!client) return;
|
|
|
|
client.endpoint = endpoint === '(none)'
|
|
? null
|
|
: endpoint;
|
|
client.latestHandshakeAt = latestHandshakeAt === '0'
|
|
? null
|
|
: new Date(Number(`${latestHandshakeAt}000`));
|
|
client.transferRx = Number(transferRx);
|
|
client.transferTx = Number(transferTx);
|
|
client.persistentKeepalive = persistentKeepalive;
|
|
});
|
|
|
|
return clients;
|
|
}
|
|
|
|
async getClient({ clientId }) {
|
|
const config = await this.getConfig();
|
|
const client = config.clients[clientId];
|
|
if (!client) {
|
|
throw new ServerError(`Client Not Found: ${clientId}`, 404);
|
|
}
|
|
|
|
return client;
|
|
}
|
|
|
|
async getClientConfiguration({ clientId }) {
|
|
const config = await this.getConfig();
|
|
const client = await this.getClient({ clientId });
|
|
|
|
return `
|
|
[Interface]
|
|
PrivateKey = ${client.privateKey}
|
|
Address = ${client.address}
|
|
DNS = ${config.server.dns}
|
|
|
|
[Peer]
|
|
PublicKey = ${client.publicKey}
|
|
PresharedKey = ${client.preSharedKey}
|
|
AllowedIPs = ${client.allowedIPs}
|
|
Endpoint = ${WG_HOST}:${WG_PORT}`;
|
|
}
|
|
|
|
async getClientQRCodeSVG({ clientId }) {
|
|
const config = await this.getClientConfiguration({ clientId });
|
|
return QRCode.toString(config, {
|
|
type: 'svg',
|
|
width: 512,
|
|
});
|
|
}
|
|
|
|
async createClient({ name }) {
|
|
if (!name) {
|
|
throw new Error('Missing: Name');
|
|
}
|
|
|
|
// try {
|
|
// await this.getClient({ name });
|
|
// throw new Error(`Duplicate Client: ${name}`);
|
|
// } catch( err ) {
|
|
// if( err.message.startsWith('Duplicate Client') ) {
|
|
// throw err;
|
|
// }
|
|
// }
|
|
|
|
// // TODO: This is unsafe
|
|
// await this.ssh.exec(`pivpn add -n ${name}`);
|
|
|
|
// return this.getClient({ name });
|
|
|
|
await this.saveConfig();
|
|
}
|
|
|
|
async deleteClient({ clientId }) {
|
|
const config = await this.getConfig();
|
|
|
|
if (config.clients[clientId]) {
|
|
delete config.clients[clientId];
|
|
await this.saveConfig();
|
|
}
|
|
}
|
|
|
|
async enableClient({ clientId }) {
|
|
const client = await this.getClient({ clientId });
|
|
client.enabled = true;
|
|
|
|
await this.saveConfig();
|
|
}
|
|
|
|
async disableClient({ clientId }) {
|
|
const client = await this.getClient({ clientId });
|
|
client.enabled = false;
|
|
|
|
await this.saveConfig();
|
|
}
|
|
|
|
};
|
|
|