This commit is contained in:
Emile Nijssen 2021-05-22 23:29:01 +02:00
parent 650128cacb
commit 18b6ce7c78
8 changed files with 77 additions and 37 deletions

View File

@ -7,10 +7,15 @@
PrivateKey = iOQJS7OUUGPYATsX6nqlL+sOODoiWiN5IOE8Msfw/0o=
Address = 10.8.0.1/24
ListenPort = 51820
DNS = 1.1.1.1
# Client: Emile (af3111a4-7343-4380-a293-ed498d9aa3b8)
[Peer]
PublicKey = i8xWKqicnDkNL14I4B+I1zlB8od/booA1joIosWn7X4=
PresharedKey = MzplKtOQ44/IaAKri2VKqCoIlg4XiVH7TCp5bcYRTQU=
AllowedIPs = 10.8.0.2/32
AllowedIPs = 10.8.0.2/32
# Client: Test 2 (c3ff2018-b2a8-4276-a16e-788e9a7e1aa6)
[Peer]
PublicKey =
PresharedKey =
AllowedIPs = 10.8.0.4/32

View File

@ -2,7 +2,7 @@
"server": {
"privateKey": "iOQJS7OUUGPYATsX6nqlL+sOODoiWiN5IOE8Msfw/0o=",
"publicKey": "BkdntwYazhYZzEEHhcYayq6TGw9/YUDQ251s+5bTgC0=",
"address": "10.8.0.1/24",
"address": "10.8.0.1",
"port": "51820",
"dns": "1.1.1.1"
},
@ -14,8 +14,17 @@
"privateKey": "sHUUDbaZBQshfOvvF8HeebhhXq3rDKWlW1Vm+6XMklU=",
"publicKey": "i8xWKqicnDkNL14I4B+I1zlB8od/booA1joIosWn7X4=",
"preSharedKey": "MzplKtOQ44/IaAKri2VKqCoIlg4XiVH7TCp5bcYRTQU=",
"address": "10.8.0.2/32",
"allowedIPs": "10.8.0.2/32",
"address": "10.8.0.2",
"enabled": true
},
"c3ff2018-b2a8-4276-a16e-788e9a7e1aa6": {
"name": "Test 2",
"address": "10.8.0.4",
"privateKey": "",
"publicKey": "",
"preSharedKey": "",
"createdAt": "2021-05-22T21:26:28.552Z",
"updatedAt": "2021-05-22T21:26:28.552Z",
"enabled": true
}
}

View File

@ -5,5 +5,5 @@ module.exports.PASSWORD = process.env.PASSWORD || 'wireguard';
module.exports.WG_PATH = process.env.WG_PATH || '/etc/wireguard/';
module.exports.WG_HOST = process.env.WG_HOST || '127.0.0.1';
module.exports.WG_PORT = process.env.WG_PORT || 51820;
module.exports.WG_DEFAULT_ADDRESS = process.env.WG_DEFAULT_ADDRESS || '10.6.0.1/32';
module.exports.WG_DEFAULT_ADDRESS = process.env.WG_DEFAULT_ADDRESS || '10.8.0.x';
module.exports.WG_DEFAULT_DNS = process.env.WG_DEFAULT_DNS || '1.1.1.1';

View File

@ -1,8 +1,6 @@
'use strict';
const { rejects } = require('assert');
const childProcess = require('child_process');
const { resolve } = require('path');
module.exports = class Util {

View File

@ -3,6 +3,7 @@
const fs = require('fs').promises;
const path = require('path');
const uuid = require('uuid');
const QRCode = require('qrcode');
const Util = require('./Util');
@ -28,9 +29,8 @@ module.exports = class WireGuard {
} catch (err) {
config = {
server: {
// TODO: Generate new config
address: WG_DEFAULT_ADDRESS,
dns: WG_DEFAULT_DNS,
privateKey: await Util.exec('wg genkey'),
address: `${WG_DEFAULT_ADDRESS.replace('x', '1')}/24`,
},
clients: {},
};
@ -52,9 +52,8 @@ module.exports = class WireGuard {
# Server
[Interface]
PrivateKey = ${config.server.privateKey}
Address = ${config.server.address}
ListenPort = ${config.server.port}
DNS = ${config.server.dns}`;
Address = ${config.server.address}/24
ListenPort = 51820`;
for (const [clientId, client] of Object.entries(config.clients)) {
if (!client.enabled) continue;
@ -65,7 +64,7 @@ DNS = ${config.server.dns}`;
[Peer]
PublicKey = ${client.publicKey}
PresharedKey = ${client.preSharedKey}
AllowedIPs = ${client.allowedIPs}`;
AllowedIPs = ${client.address}/32`;
}
await fs.writeFile(path.join(WG_PATH, 'wg0.json'), JSON.stringify(config, false, 2));
@ -78,6 +77,7 @@ AllowedIPs = ${client.allowedIPs}`;
id: clientId,
name: client.name,
enabled: client.enabled,
address: client.address,
publicKey: client.publicKey,
createdAt: new Date(client.createdAt),
updatedAt: new Date(client.updatedAt),
@ -90,10 +90,8 @@ AllowedIPs = ${client.allowedIPs}`;
}));
// 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
const dump = await Util.exec('wg show wg0 dump');
dump
.trim()
.split('\n')
.slice(1)
@ -137,19 +135,18 @@ AllowedIPs = ${client.allowedIPs}`;
}
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}
Address = ${client.address}/24
DNS = ${WG_DEFAULT_DNS}
[Peer]
PublicKey = ${client.publicKey}
PresharedKey = ${client.preSharedKey}
AllowedIPs = ${client.allowedIPs}
AllowedIPs = 0.0.0.0/0, ::/0
Endpoint = ${WG_HOST}:${WG_PORT}`;
}
@ -166,19 +163,45 @@ Endpoint = ${WG_HOST}:${WG_PORT}`;
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;
// }
// }
const config = await this.getConfig();
// // TODO: This is unsafe
// await this.ssh.exec(`pivpn add -n ${name}`);
const privateKey = await Util.exec('wg genkey');
const publicKey = await Util.exec(`echo ${privateKey} | wg pubkey`);
const preSharedKey = await Util.exec('wg genpsk');
// return this.getClient({ name });
// Calculate next IP
let address;
for (let i = 2; i < 255; i++) {
const client = Object.values(config.clients).find(client => {
return client.address === WG_DEFAULT_ADDRESS.replace('x', i);
});
if (!client) {
address = WG_DEFAULT_ADDRESS.replace('x', i);
break;
}
}
if (!address) {
throw new Error('Maximum number of clients reached.');
}
// Create Client
const clientId = uuid.v4();
const client = {
name,
address,
privateKey,
publicKey,
preSharedKey,
createdAt: new Date(),
updatedAt: new Date(),
enabled: true,
};
config.clients[clientId] = client;
await this.saveConfig();
}
@ -194,14 +217,18 @@ Endpoint = ${WG_HOST}:${WG_PORT}`;
async enableClient({ clientId }) {
const client = await this.getClient({ clientId });
client.enabled = true;
client.updatedAt = new Date();
await this.saveConfig();
}
async disableClient({ clientId }) {
const client = await this.getClient({ clientId });
client.enabled = false;
client.updatedAt = new Date();
await this.saveConfig();
}

1
src/www/css/vendor/tailwind.min.css vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -3,7 +3,7 @@
<head>
<title>WireGuard</title>
<link href="https://unpkg.com/tailwindcss@^2/dist/tailwind.min.css" rel="stylesheet">
<link href="css/vendor/tailwind.min.css" rel="stylesheet">
<link rel="manifest" href="manifest.json">
<link rel="icon" type="image/png" href="img/favicon.png">
<link rel="apple-touch-icon" href="img/apple-touch-icon.png">
@ -61,7 +61,7 @@
<div class="flex-grow">
<div class="text-gray-700" :title="'Created at ' + dateTime(new Date(client.createdAt))">{{client.name}}
</div>
<div v-if="client.allowedIPs" class="text-gray-300 text-xs">{{client.allowedIPs.split('/')[0]}}
<div class="text-gray-300 text-xs">{{client.address}}
<span v-if="client.transferTx" title="Download">
·
<svg class="align-middle h-3 inline" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"

View File

@ -84,7 +84,7 @@ new Vue({
.catch(err => alert(err.message || err.toString()))
.finally(() => this.refresh().catch(console.error));
},
deleteClient(clientId) {
deleteClient(client) {
this.api.deleteClient({ clientId: client.id })
.catch(err => alert(err.message || err.toString()))
.finally(() => this.refresh().catch(console.error));