173 lines
4.0 KiB
JavaScript
173 lines
4.0 KiB
JavaScript
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 = "<SERVER_PUBLIC_KEY>";
|
||
const SERVER_IP = "<SERVER_PUBLIC_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
|
||
};
|
||
}
|
||
|
||
|
||
|