#!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 '"); } 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, " "));