WireguardConfigGen/gen.js

190 lines
5.6 KiB
JavaScript

#!node
const fs = require("fs");
const p = require("path");
const qrimage = require("./qr/qr");
const crypto = require("crypto");
const deleteRec = (path) => {
path = p.resolve(path);
if (fs.existsSync(path)) {
if (fs.statSync(path).isDirectory()) {
fs.readdirSync(path).forEach(entry => deleteRec(p.join(path, entry)));
fs.rmdirSync(path);
} else {
fs.unlinkSync(path);
}
}
}
const config = fs.existsSync("config.json") ? JSON.parse(fs.readFileSync("config.json").toString()) : {};
const child = require("child_process");
const getPrivate = () => {
return child.execSync("wg genkey").toString().replace("\n", "").replace("\r", "").trim();
}
const getPublic = (private) => {
return child.execSync(`echo ${private} | wg pubkey`).toString().replace("\n", "").replace("\r", "").trim();
}
const keyPair = () => {
const private = getPrivate();
const public = getPublic(private);
return { private, public };
}
const clientArray = (clients) => Object.keys(clients).map(key => ({ ...clients[key], name: key }))
const ipTablesPostUP = [
"iptables -A FORWARD -i %i -j ACCEPT",
"iptables -A FORWARD -o %i -j ACCEPT",
"iptables -t nat -A POSTROUTING -o %i -j MASQUERADE",
"iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE",
"iptables -t nat -A POSTROUTING -o wg0 -j MASQUERADE"
].join("; ");
const ipTablesPostDOWN = [
"iptables -D FORWARD -i %i -j ACCEPT",
"iptables -D FORWARD -o %i -j ACCEPT",
"iptables -t nat -D POSTROUTING -o %i -j MASQUERADE",
"iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE",
"iptables -t nat -D POSTROUTING -o wg0 -j MASQUERADE"
].join("; ");
function makeServer({ port, subnet, subnet6, server, clients }) {
const base = `[Interface] #Server
ListenPort = ${port}
Address = ${subnet}1/32,${subnet6}1/48
PrivateKey = ${server.private}
PostUp = ${ipTablesPostUP}
PostDown = ${ipTablesPostDOWN}
# ---------------------------
`
let peers = clientArray(clients).map(client => {
return `[Peer] #${client.name}
PublicKey = ${client.public}
AllowedIPs = ${subnet}${client.ip}/32,${subnet6}${client.ip}/128
` + (client.endpoint ? "\nEndpoint = " + client.endpoint + ":" + port : "");
}).join("\n\n");
fs.writeFileSync("out/server/server.conf", base + peers);
fs.writeFileSync("out/server/server.public", server.public);
}
function makeClients({ port, subnet, subnet6, server, clients }) {
clientArray(clients).map(client => {
const config = `[Interface]
ListenPort = ${port}
Address = ${subnet}${client.ip}/32, ${subnet6}${client.ip}/128
PrivateKey = ${client.private}
DNS = 1.1.1.1
[Peer] #Server
PublicKey = ${server.public}
AllowedIPs = 0.0.0.0/0, ::0/0
Endpoint = ${server.endpoint}:${port}
`
fs.writeFileSync(`out/clients/${client.name}.conf`, config);
fs.writeFileSync(`out/clients/${client.name}.public`, client.public);
var qr_svg = qrimage.image(config, { type: 'png' });
qr_svg.pipe(require('fs').createWriteStream(`out/clients/${client.name}.png`));
})
}
try {
if (!config.subnet6) {
let sn = crypto.randomBytes(5).toString("hex");
let s1 = sn.substr(0, 2);
let s23 = sn.substr(2, 4);
let s45 = sn.substr(6, 4);
config.subnet6 = `fd${s1}:${s23}:${s45}::`;
}
switch (process.argv[2]) {
case "init": {
const hostname = process.argv[3];
let subnet = process.argv[4];
const port = Number(process.argv[5]) | 51823;
if (!hostname)
throw new Error("Hostname required");
if (!subnet) {
let randomIP1 = Math.floor(Math.random() * 256);
let randomIP2 = Math.floor(Math.random() * 256);
subnet = `10.${randomIP1}.${randomIP2}.`;
} else {
if (!subnet.endsWith("."))
subnet += ".";
}
config.subnet = subnet;
config.port = port;
config.server = {
endpoint: hostname,
...keyPair()
}
config.clients = {};
console.log("Created new configuration");
console.log("Server Hostname:", hostname);
console.log(" Port:", port);
console.log(" Subnet:", subnet + "0/24");
break;
}
case "generate": {
deleteRec("./out");
fs.mkdirSync("./out")
fs.mkdirSync("./out/server")
fs.mkdirSync("./out/clients")
makeServer(config)
makeClients(config)
break;
}
case "add": {
const name = process.argv[3];
const endpoint = process.argv[4];
if (!name)
throw new Error("No name!");
if (config.clients[name]) {
throw new Error("A device with this name exists already!\n Remove with 'remove <name>'");
}
let freeIP = 2;
clientArray(config.clients).forEach(c => c.ip >= freeIP ? freeIP = c.ip + 1 : undefined);
config.clients[name] = {
ip: freeIP,
endpoint,
...keyPair()
}
console.log("Peer added:")
console.log(`IP: ${config.subnet}${freeIP}`)
break;
}
case "remove": {
const name = process.argv[3];
if (!name)
throw new Error("No name!");
delete config.clients[name];
break;
}
default: {
console.log("Wireguard VPN Config generator v0.1");
console.log("Usage:")
console.log("generate, add, remove")
}
}
} catch (err) {
console.error(err);
console.error(err.message);
}
fs.writeFileSync("config.json", JSON.stringify(config, undefined, " "));