import fs from "fs"; import { execSync } from "child_process"; const WG_CONF = "/etc/wireguard/wg0.conf"; const PEER_DB = "/etc/wireguard/peers.json"; const CLIENT_DIR = "/etc/wireguard/clients"; const SERVER_PUBLIC_KEY = ""; const SERVER_IP = ""; function loadDb() { try { return JSON.parse(fs.readFileSync(PEER_DB, "utf8")); } catch { const initial = { lastIp: 1, active: {}, free: [] }; fs.writeFileSync(PEER_DB, JSON.stringify(initial, null, 2)); return initial; } } function saveDb(db) { fs.writeFileSync(PEER_DB, JSON.stringify(db, null, 2)); } function allocateIp(db) { if (db.free.length > 0) { return db.free.shift(); // reuse old IP } db.lastIp++; if (db.lastIp >= 255) db.lastIp = 2; return `10.0.0.${db.lastIp}`; } function generateKeyPair() { const privateKey = execSync("wg genkey").toString().trim(); const publicKey = execSync(`echo ${privateKey} | wg pubkey`).toString().trim(); return { privateKey, publicKey }; } // function addPeerToServer(publicKey, ip) { // const ipLast = ip.split(".")[3]; // const peerEntry = ` // [Peer] // PublicKey = ${publicKey} // AllowedIPs = 10.0.0.${ipLast}/32 // `; // fs.appendFileSync(WG_CONF, peerEntry); // // apply config instantly // // execSync(`wg syncconf wg0 <(wg-quick strip wg0)`, { shell: "/bin/bash" }); // execSync(`wg-quick strip wg0 > /tmp/wg0.tmp`); // execSync(`wg syncconf wg0 /tmp/wg0.tmp`); // } function addPeerToServer(publicKey, ip) { // const peerEntry = ` // [Peer] // PublicKey = ${publicKey} // AllowedIPs = ${ip}/32 // `; // fs.appendFileSync(WG_CONF, peerEntry); // execSync("wg-quick strip wg0 > /tmp/wg0.tmp"); // execSync("wg syncconf wg0 /tmp/wg0.tmp"); // execSync("rm -f /tmp/wg0.tmp"); execSync( `wg set wg0 peer ${publicKey} allowed-ips ${ip}/32`, { stdio: "inherit" } ); } function generateClientConf(privateKey, ip) { return ` [Interface] PrivateKey = ${privateKey} Address = ${ip}/32 DNS = 1.1.1.1 [Peer] PublicKey = ${SERVER_PUBLIC_KEY} Endpoint = ${SERVER_IP}:51820 AllowedIPs = 10.0.0.0/24 PersistentKeepalive = 25 `; } export function createWireGuardConnection() { let db = loadDb(); // 1. allocate IP const ip = allocateIp(db); // 2. generate keys const { privateKey, publicKey } = generateKeyPair(); // 3. update server config addPeerToServer(publicKey, ip); // 4. update DB db.active[ip] = publicKey; saveDb(db); // 5. prepare client.conf const clientConf = generateClientConf(privateKey, ip); // (optional) save it if (!fs.existsSync(CLIENT_DIR)) fs.mkdirSync(CLIENT_DIR); fs.writeFileSync(`${CLIENT_DIR}/client-${ip}.conf`, clientConf); // 6. return to Electron app return { ip, publicKey, clientConf }; } // -------- Disconnect VPN PART START ----------- const removePeerFromConf = (publicKey) => { const conf = fs.readFileSync(WG_CONF, "utf8"); const peerRegex = new RegExp( `\\n\\[Peer\\][\\s\\S]*?PublicKey = ${publicKey}[\\s\\S]*?(?=\\n\\[Peer\\]|$)`, "g" ); const updated = conf.replace(peerRegex, "\n"); fs.writeFileSync(WG_CONF, updated); } function syncWireGuard() { execSync("wg-quick strip wg0 > /tmp/wg0.tmp"); execSync("wg syncconf wg0 /tmp/wg0.tmp"); execSync("rm -f /tmp/wg0.tmp"); } export function disconnectWireGuardConnection(ip) { const db = loadDb(); const publicKey = db.active[ip]; if (!db.active[ip]) { return { success: false, message: "VPN already disconnected" }; } // 1️⃣ Remove peer from live kernel execSync(`wg set wg0 peer ${publicKey} remove`); // 2️⃣ Remove from config file removePeerFromConf(publicKey); // 3️⃣ Sync config syncWireGuard(); // 4️⃣ Update DB (free IP) delete db.active[ip]; db.free.push(ip); saveDb(db); return { success: true, message: "VPN disconnected", ip }; }