wg-easy/src/lib/WireGuard.js

184 lines
4.3 KiB
JavaScript

'use strict';
const fs = require('fs').promises;
const path = require('path');
const QRCode = require('qrcode');
const ServerError = require('./ServerError');
const {
WG_PATH,
WG_HOST,
WG_PORT,
WG_DEFAULT_ADDRESS,
} = require('../config');
module.exports = class WireGuard {
constructor() {
Promise.resolve().then(async () => {
try {
const config = await fs.readFile(path.join(WG_PATH, 'wg0.json'), 'utf8');
this.config = JSON.parse(config);
} catch (err) {
this.config = {
// TODO: Generate new config
server: {
address: WG_DEFAULT_ADDRESS,
},
clients: {},
};
// TODO: Save JSON config
}
console.log('this.config', this.config);
await this.saveConfig();
}).catch(err => {
// eslint-disable-next-line no-console
console.error(err);
// eslint-disable-next-line no-process-exit
process.exit(1);
});
}
async saveConfig() {
let result = `
# Note: Do not edit this file directly.
# Your changes will be overwritten!
# Server
[Interface]
PrivateKey = ${this.config.server.privateKey}
Address = ${this.config.server.address}
ListenPort = ${this.config.server.port}
DNS = ${this.config.server.dns}`;
for (const [clientId, client] of Object.entries(this.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(this.config, false, 2));
await fs.writeFile(path.join(WG_PATH, 'wg0.conf'), result);
}
async getClients() {
return Object.entries(this.config.clients).map(([clientId, client]) => ({
id: clientId,
name: client.name,
enabled: client.enabled,
publicKey: client.publicKey,
createdAt: client.createdAt,
updatedAt: client.updatedAt,
allowedIPs: client.allowedIPs,
// TODO:
latestHandshake: new Date(),
transferRx: 0,
transferTx: 0,
}));
// const { stdout } = await Util.exec('sudo cat /etc/wireguard/configs/clients.txt');
// return stdout
// .trim()
// .split('\n')
// .filter(line => {
// return line.length > 0;
// })
// .map(line => {
// const [ name, publicKey, createdAt ] = line.split(' ');
// return {
// name,
// publicKey,
// createdAt: new Date(Number(createdAt + '000')),
// };
// });
}
async getClient({ clientId }) {
const client = this.config.clients[clientId];
if (!client) {
throw new ServerError(`Client Not Found: ${clientId}`, 404);
}
return client;
}
async getClientConfiguration({ clientId }) {
const client = await this.getClient({ clientId });
return `
[Interface]
PrivateKey = ${client.privateKey}
Address = ${client.address}
DNS = ${this.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 }) {
if (this.config.clients[clientId]) {
delete this.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();
}
};