Updates
This commit is contained in:
@@ -0,0 +1,35 @@
|
||||
import QRCode from "qrcode";
|
||||
|
||||
type Params = {
|
||||
config?: string | null;
|
||||
width?: number;
|
||||
};
|
||||
|
||||
export default async function generateWireguardClientQR({
|
||||
config,
|
||||
width = 320,
|
||||
}: Params) {
|
||||
if (!config) {
|
||||
return {
|
||||
qr_data_uri: null,
|
||||
};
|
||||
}
|
||||
|
||||
try {
|
||||
const svg = await QRCode.toString(config, {
|
||||
type: "svg",
|
||||
errorCorrectionLevel: "M",
|
||||
width,
|
||||
});
|
||||
|
||||
const qr_data_uri = `data:image/svg+xml;base64,${Buffer.from(svg).toString("base64")}`;
|
||||
|
||||
return {
|
||||
qr_data_uri,
|
||||
};
|
||||
} catch (error) {
|
||||
return {
|
||||
qr_data_uri: null,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
import type { BUN_SQLITE_WGUI_CLIENTS } from "@/db/types/db";
|
||||
import path from "path";
|
||||
import grabDirNames from "@/src/utils/grab-dir-names";
|
||||
import { execSync } from "child_process";
|
||||
|
||||
type Params = {
|
||||
client: BUN_SQLITE_WGUI_CLIENTS;
|
||||
host_id?: number;
|
||||
};
|
||||
|
||||
const {
|
||||
WGUI_LIB_HOSTS_CONFIGS_DIR,
|
||||
WGUI_LIB_HOST_CLIENTS_DIR_NAME,
|
||||
WIREGUARD_PRIVATE_KEY_FILE_NAME,
|
||||
WIREGUARD_PUBLIC_KEY_FILE_NAME,
|
||||
WIREGUARD_CLIENT_CONFIG_FILE_NAME,
|
||||
} = grabDirNames();
|
||||
|
||||
export default function grabClientDirnames({
|
||||
client,
|
||||
host_id: passed_host_id,
|
||||
}: Params) {
|
||||
const host_id = passed_host_id || 0;
|
||||
|
||||
const CLIENT_WG_IP = client?.wg_ip_address;
|
||||
|
||||
const HOST_CONFIG_DIR = path.join(
|
||||
WGUI_LIB_HOSTS_CONFIGS_DIR,
|
||||
String(host_id),
|
||||
);
|
||||
|
||||
const HOST_CLIENTS_DIR = path.join(
|
||||
HOST_CONFIG_DIR,
|
||||
WGUI_LIB_HOST_CLIENTS_DIR_NAME,
|
||||
);
|
||||
|
||||
const CLIENT_DIR = path.join(HOST_CLIENTS_DIR, `${client.id}`);
|
||||
|
||||
const CLIENT_PRIVATE_KEY_FILE = path.join(
|
||||
CLIENT_DIR,
|
||||
WIREGUARD_PRIVATE_KEY_FILE_NAME,
|
||||
);
|
||||
const CLIENT_PUBLIC_KEY_FILE = path.join(
|
||||
CLIENT_DIR,
|
||||
WIREGUARD_PUBLIC_KEY_FILE_NAME,
|
||||
);
|
||||
const CLIENT_CONFIG_FILE = path.join(
|
||||
CLIENT_DIR,
|
||||
WIREGUARD_CLIENT_CONFIG_FILE_NAME,
|
||||
);
|
||||
|
||||
const CLIENT_PRIVATE_KEY = execSync(`cat ${CLIENT_PRIVATE_KEY_FILE}`, {
|
||||
encoding: "utf-8",
|
||||
}).trim();
|
||||
|
||||
const CLIENT_PUBLIC_KEY = execSync(`cat ${CLIENT_PUBLIC_KEY_FILE}`, {
|
||||
encoding: "utf-8",
|
||||
}).trim();
|
||||
|
||||
const HOST_PUBLIC_KEY = execSync(
|
||||
`cat ${path.join(HOST_CONFIG_DIR, WIREGUARD_PUBLIC_KEY_FILE_NAME)}`,
|
||||
{ encoding: "utf-8" },
|
||||
).trim();
|
||||
|
||||
return {
|
||||
CLIENT_WG_IP,
|
||||
HOST_CLIENTS_DIR,
|
||||
HOST_CONFIG_DIR,
|
||||
CLIENT_DIR,
|
||||
CLIENT_PRIVATE_KEY_FILE,
|
||||
CLIENT_PUBLIC_KEY_FILE,
|
||||
CLIENT_CONFIG_FILE,
|
||||
CLIENT_PRIVATE_KEY,
|
||||
CLIENT_PUBLIC_KEY,
|
||||
HOST_PUBLIC_KEY,
|
||||
};
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import deriveWireguardInterfaceName from "@/src/utils/derive-wireguard-interface
|
||||
import type { APIResponseObject } from "@moduletrace/bunext/types";
|
||||
import { execSync } from "node:child_process";
|
||||
import path from "node:path";
|
||||
import grabHostDirnames from "./grab-host-dir-names";
|
||||
|
||||
const { WGUI_LIB_HOSTS_CONFIGS_DIR, WGUI_WG_QUICK_MANAGE_SCRIPT } =
|
||||
grabDirNames();
|
||||
@@ -19,11 +20,9 @@ export default function manageWireguardHost({
|
||||
action,
|
||||
host_id = AppData["WireguardHostID"],
|
||||
}: Params): APIResponseObject {
|
||||
const INTERFACE_NAME = deriveWireguardInterfaceName({ host_id });
|
||||
const HOST_CONFIG_PATH = path.join(
|
||||
WGUI_LIB_HOSTS_CONFIGS_DIR,
|
||||
`${INTERFACE_NAME}.conf`,
|
||||
);
|
||||
const { HOST_CONFIG_FILE, INTERFACE_NAME } = grabHostDirnames({
|
||||
host: { id: host_id },
|
||||
});
|
||||
|
||||
const IS_ROOT =
|
||||
typeof process.getuid === "function" && process.getuid() === 0;
|
||||
@@ -35,7 +34,7 @@ export default function manageWireguardHost({
|
||||
};
|
||||
}
|
||||
|
||||
const MANAGE_COMMAND = `${WGUI_WG_QUICK_MANAGE_SCRIPT} ${action} ${INTERFACE_NAME} ${HOST_CONFIG_PATH}`;
|
||||
const MANAGE_COMMAND = `${WGUI_WG_QUICK_MANAGE_SCRIPT} ${action} ${INTERFACE_NAME} ${HOST_CONFIG_FILE}`;
|
||||
|
||||
try {
|
||||
const output = execSync(MANAGE_COMMAND, { encoding: "utf-8" }).trim();
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
import path from "node:path";
|
||||
import grabDirNames from "@/src/utils/grab-dir-names";
|
||||
import grabHostDirnames from "./grab-host-dir-names";
|
||||
|
||||
const { WIREGUARD_CLIENT_CONFIG_FILE_NAME } = grabDirNames();
|
||||
|
||||
type Params = {
|
||||
client_id?: string | number;
|
||||
host_id?: string | number;
|
||||
};
|
||||
|
||||
export default async function readWireguardClientConfig({
|
||||
client_id,
|
||||
host_id,
|
||||
}: Params) {
|
||||
if (!client_id) {
|
||||
return {
|
||||
config: null,
|
||||
config_path: null,
|
||||
};
|
||||
}
|
||||
|
||||
const { HOST_CLIENTS_DIR } = grabHostDirnames({
|
||||
host: host_id ? { id: Number(host_id) } : undefined,
|
||||
});
|
||||
|
||||
const config_path = path.join(
|
||||
HOST_CLIENTS_DIR,
|
||||
String(client_id),
|
||||
WIREGUARD_CLIENT_CONFIG_FILE_NAME,
|
||||
);
|
||||
|
||||
try {
|
||||
const config_file = Bun.file(config_path);
|
||||
|
||||
if (!(await config_file.exists())) {
|
||||
return {
|
||||
config: null,
|
||||
config_path,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
config: await config_file.text(),
|
||||
config_path,
|
||||
};
|
||||
} catch (error) {
|
||||
return {
|
||||
config: null,
|
||||
config_path,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -12,6 +12,7 @@ import setupWireguardHost from "./setup-wireguard-host";
|
||||
import type { APIResponseObject } from "@moduletrace/bunext/types";
|
||||
import BunSQLite from "@moduletrace/bun-sqlite";
|
||||
import type { TableType, User } from "@/src/types";
|
||||
import grabClientDirnames from "./grab-client-dir-names";
|
||||
|
||||
const {
|
||||
WGUI_LIB_HOSTS_CONFIGS_DIR,
|
||||
@@ -25,6 +26,12 @@ type Params = {
|
||||
client: BUN_SQLITE_WGUI_CLIENTS;
|
||||
host?: BUN_SQLITE_WGUI_HOSTS;
|
||||
user: User;
|
||||
/**
|
||||
* Skip the host setup/restart at the end. Use when
|
||||
* regenerating multiple clients and restarting the
|
||||
* host once afterwards instead.
|
||||
*/
|
||||
skip_host_setup?: boolean;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -38,6 +45,7 @@ export default async function setupWireguardClient({
|
||||
client,
|
||||
host,
|
||||
user,
|
||||
skip_host_setup,
|
||||
}: Params): Promise<APIResponseObject> {
|
||||
const host_id = host?.id || AppData["WireguardHostID"];
|
||||
|
||||
@@ -50,7 +58,18 @@ export default async function setupWireguardClient({
|
||||
|
||||
const variables = variables_res.payload;
|
||||
|
||||
const CLIENT_WG_IP = client?.wg_ip_address;
|
||||
const {
|
||||
CLIENT_WG_IP,
|
||||
CLIENT_CONFIG_FILE,
|
||||
CLIENT_DIR,
|
||||
CLIENT_PRIVATE_KEY_FILE,
|
||||
CLIENT_PUBLIC_KEY_FILE,
|
||||
HOST_CLIENTS_DIR,
|
||||
HOST_CONFIG_DIR,
|
||||
CLIENT_PRIVATE_KEY,
|
||||
CLIENT_PUBLIC_KEY,
|
||||
HOST_PUBLIC_KEY,
|
||||
} = grabClientDirnames({ client, host_id });
|
||||
|
||||
if (!CLIENT_WG_IP) {
|
||||
return {
|
||||
@@ -59,18 +78,6 @@ export default async function setupWireguardClient({
|
||||
};
|
||||
}
|
||||
|
||||
const HOST_CONFIG_DIR = path.join(
|
||||
WGUI_LIB_HOSTS_CONFIGS_DIR,
|
||||
String(host_id),
|
||||
);
|
||||
|
||||
const HOST_CLIENTS_DIR = path.join(
|
||||
HOST_CONFIG_DIR,
|
||||
WGUI_LIB_HOST_CLIENTS_DIR_NAME,
|
||||
);
|
||||
|
||||
const CLIENT_DIR = path.join(HOST_CLIENTS_DIR, `${client.id}`);
|
||||
|
||||
const HOST_WG_IP = host?.id
|
||||
? host?.wg_ip_address
|
||||
: variables?.find((v) => v.key == "main_host_wg_ip_address")?.value;
|
||||
@@ -82,19 +89,6 @@ export default async function setupWireguardClient({
|
||||
};
|
||||
}
|
||||
|
||||
const CLIENT_PRIVATE_KEY_FILE = path.join(
|
||||
CLIENT_DIR,
|
||||
WIREGUARD_PRIVATE_KEY_FILE_NAME,
|
||||
);
|
||||
const CLIENT_PUBLIC_KEY_FILE = path.join(
|
||||
CLIENT_DIR,
|
||||
WIREGUARD_PUBLIC_KEY_FILE_NAME,
|
||||
);
|
||||
const CLIENT_CONFIG_FILE = path.join(
|
||||
CLIENT_DIR,
|
||||
WIREGUARD_CLIENT_CONFIG_FILE_NAME,
|
||||
);
|
||||
|
||||
let pre_sh = ``;
|
||||
|
||||
pre_sh += `mkdir -p ${CLIENT_DIR}\n`;
|
||||
@@ -112,20 +106,10 @@ export default async function setupWireguardClient({
|
||||
}
|
||||
|
||||
try {
|
||||
const CLIENT_PRIVATE_KEY = execSync(`cat ${CLIENT_PRIVATE_KEY_FILE}`, {
|
||||
encoding: "utf-8",
|
||||
}).trim();
|
||||
|
||||
const CLIENT_PUBLIC_KEY = execSync(`cat ${CLIENT_PUBLIC_KEY_FILE}`, {
|
||||
encoding: "utf-8",
|
||||
}).trim();
|
||||
|
||||
const HOST_PUBLIC_KEY = execSync(
|
||||
`cat ${path.join(HOST_CONFIG_DIR, WIREGUARD_PUBLIC_KEY_FILE_NAME)}`,
|
||||
{ encoding: "utf-8" },
|
||||
).trim();
|
||||
|
||||
const PUBLIC_IP_ADDRESS =
|
||||
host?.public_ip_address ||
|
||||
variables?.find((v) => v.key == "main_host_public_ip_address")
|
||||
?.value ||
|
||||
(await grabHostPublicIPAddress()) ||
|
||||
client?.public_ip_address ||
|
||||
HOST_WG_IP;
|
||||
@@ -138,26 +122,38 @@ export default async function setupWireguardClient({
|
||||
sh += `[Interface]\n`;
|
||||
sh += `Address = ${CLIENT_WG_IP}/32\n`;
|
||||
sh += `PrivateKey = ${CLIENT_PRIVATE_KEY}\n`;
|
||||
sh += `DNS = 1.1.1.1\n`;
|
||||
// sh += `DNS = 1.1.1.1\n`;
|
||||
sh += `\n`;
|
||||
sh += `[Peer]\n`;
|
||||
sh += `PublicKey = ${HOST_PUBLIC_KEY}\n`;
|
||||
sh += `Endpoint = ${PUBLIC_IP_ADDRESS}:51820\n`;
|
||||
|
||||
if (client?.allowed_ips) {
|
||||
if (client?.allow_all_ips == 1) {
|
||||
sh += `AllowedIPs = 0.0.0.0/0, ::/0\n`;
|
||||
} else if (client?.allowed_ips) {
|
||||
sh += `AllowedIPs = ${client.allowed_ips}\n`;
|
||||
}
|
||||
|
||||
sh += `PersistentKeepalive = 25\n`;
|
||||
|
||||
sh += `EOF\n`;
|
||||
sh += `\n`;
|
||||
|
||||
const exec = execSync(sh, { encoding: "utf-8" });
|
||||
const exec = execSync(sh, {
|
||||
encoding: "utf-8",
|
||||
});
|
||||
|
||||
const CLIENT_CONFIG = execSync(`cat ${CLIENT_CONFIG_FILE}`, {
|
||||
encoding: "utf-8",
|
||||
});
|
||||
|
||||
const host_setup_res = await setupWireguardHost({ host, user });
|
||||
const host_setup_res = skip_host_setup
|
||||
? { success: true }
|
||||
: await setupWireguardHost({
|
||||
host,
|
||||
user,
|
||||
is_update_after_client_setup: true,
|
||||
});
|
||||
|
||||
if (!host_setup_res.success) {
|
||||
return {
|
||||
@@ -172,6 +168,11 @@ export default async function setupWireguardClient({
|
||||
stringRes: CLIENT_CONFIG,
|
||||
};
|
||||
} catch (error: any) {
|
||||
console.log(
|
||||
`Error setting up wireguard client ${client.id} for host ${host_id} =>`,
|
||||
error.message,
|
||||
);
|
||||
|
||||
return {
|
||||
success: false,
|
||||
msg: error.message,
|
||||
|
||||
@@ -12,6 +12,8 @@ import type { TableType, User } from "@/src/types";
|
||||
import checkPrivateIPAvailability from "./check-private-ip-availability";
|
||||
import manageWireguardHost from "./manage-wireguard-host";
|
||||
import grabHostDirnames from "./grab-host-dir-names";
|
||||
import path from "node:path";
|
||||
import grabClientDirnames from "./grab-client-dir-names";
|
||||
|
||||
const { WIREGUARD_PRIVATE_KEY_FILE_NAME, WIREGUARD_PUBLIC_KEY_FILE_NAME } =
|
||||
grabDirNames();
|
||||
@@ -20,12 +22,14 @@ type Params = {
|
||||
host?: BUN_SQLITE_WGUI_HOSTS;
|
||||
wg_subnet_ip?: string;
|
||||
user: User;
|
||||
is_update_after_client_setup?: boolean;
|
||||
};
|
||||
|
||||
export default async function setupWireguardHost({
|
||||
host,
|
||||
wg_subnet_ip,
|
||||
user,
|
||||
is_update_after_client_setup,
|
||||
}: Params): Promise<APIResponseObject> {
|
||||
const {
|
||||
HOST_CLIENTS_DIR,
|
||||
@@ -57,7 +61,7 @@ export default async function setupWireguardHost({
|
||||
query: {
|
||||
query: {
|
||||
host_id: {
|
||||
value: HOST_ID,
|
||||
value: String(HOST_ID),
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -78,35 +82,39 @@ export default async function setupWireguardHost({
|
||||
};
|
||||
}
|
||||
|
||||
const is_ip_available = await checkPrivateIPAvailability({
|
||||
ip_address: HOST_WG_IP,
|
||||
});
|
||||
const is_ip_available = is_update_after_client_setup
|
||||
? { success: true }
|
||||
: await checkPrivateIPAvailability({
|
||||
ip_address: HOST_WG_IP,
|
||||
});
|
||||
|
||||
if (!is_ip_available.success) {
|
||||
if (!is_ip_available.success && !is_update_after_client_setup) {
|
||||
return {
|
||||
success: false,
|
||||
msg: `IP not available`,
|
||||
};
|
||||
}
|
||||
|
||||
let pre_sh = ``;
|
||||
if (!is_update_after_client_setup) {
|
||||
let pre_sh = ``;
|
||||
|
||||
pre_sh += `set -e\n`;
|
||||
pre_sh += `mkdir -p ${HOST_CONFIG_DIR}\n`;
|
||||
pre_sh += `mkdir -p ${HOST_CLIENTS_DIR}\n`;
|
||||
pre_sh += `mkdir -p ${HOST_IPTABLES_DIR}\n`;
|
||||
pre_sh += `cd ${HOST_CONFIG_DIR}\n`;
|
||||
pre_sh += `if [ ! -f ${WIREGUARD_PRIVATE_KEY_FILE_NAME} ]; then\n`;
|
||||
pre_sh += ` wg genkey | tee ${WIREGUARD_PRIVATE_KEY_FILE_NAME} | wg pubkey > ${WIREGUARD_PUBLIC_KEY_FILE_NAME}\n`;
|
||||
pre_sh += `fi\n`;
|
||||
pre_sh += `set -e\n`;
|
||||
pre_sh += `mkdir -p ${HOST_CONFIG_DIR}\n`;
|
||||
pre_sh += `mkdir -p ${HOST_CLIENTS_DIR}\n`;
|
||||
pre_sh += `mkdir -p ${HOST_IPTABLES_DIR}\n`;
|
||||
pre_sh += `cd ${HOST_CONFIG_DIR}\n`;
|
||||
pre_sh += `if [ ! -f ${WIREGUARD_PRIVATE_KEY_FILE_NAME} ]; then\n`;
|
||||
pre_sh += ` wg genkey | tee ${WIREGUARD_PRIVATE_KEY_FILE_NAME} | wg pubkey > ${WIREGUARD_PUBLIC_KEY_FILE_NAME}\n`;
|
||||
pre_sh += `fi\n`;
|
||||
|
||||
try {
|
||||
const exec_pre_setup = execSync(pre_sh, { encoding: "utf-8" });
|
||||
} catch (error: any) {
|
||||
return {
|
||||
success: false,
|
||||
msg: error.message,
|
||||
};
|
||||
try {
|
||||
const exec_pre_setup = execSync(pre_sh, { encoding: "utf-8" });
|
||||
} catch (error: any) {
|
||||
return {
|
||||
success: false,
|
||||
msg: error.message,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -118,7 +126,7 @@ export default async function setupWireguardHost({
|
||||
encoding: "utf-8",
|
||||
}).trim();
|
||||
|
||||
if (HOST_ID == 0) {
|
||||
if (HOST_ID == 0 && !is_update_after_client_setup) {
|
||||
const update_variables = await BunSQLite.insert<
|
||||
BUN_SQLITE_WGUI_VARIABLES,
|
||||
TableType
|
||||
@@ -140,7 +148,7 @@ export default async function setupWireguardHost({
|
||||
if (!update_variables.success) {
|
||||
throw new Error(`Couldn't update host variables`);
|
||||
}
|
||||
} else if (HOST_ID) {
|
||||
} else if (HOST_ID && !is_update_after_client_setup) {
|
||||
const update_host = await BunSQLite.insert<
|
||||
BUN_SQLITE_WGUI_HOSTS,
|
||||
TableType
|
||||
@@ -208,10 +216,15 @@ export default async function setupWireguardHost({
|
||||
if (clients[0]) {
|
||||
for (let i = 0; i < clients.length; i++) {
|
||||
const client = clients[i];
|
||||
if (!client?.id || !client.public_key) continue;
|
||||
if (!client?.id) continue;
|
||||
|
||||
const { CLIENT_PUBLIC_KEY } = grabClientDirnames({
|
||||
client,
|
||||
host_id: HOST_ID,
|
||||
});
|
||||
|
||||
sh += `[Peer]\n`;
|
||||
sh += `PublicKey = ${client.public_key}\n`;
|
||||
sh += `PublicKey = ${CLIENT_PUBLIC_KEY}\n`;
|
||||
sh += `AllowedIPs = ${client.allowed_ips}\n`;
|
||||
sh += `\n`;
|
||||
}
|
||||
@@ -219,6 +232,8 @@ export default async function setupWireguardHost({
|
||||
|
||||
sh += `EOF\n`;
|
||||
|
||||
sh += `chmod 600 ${INTERFACE_NAME}.conf\n`;
|
||||
|
||||
sh += `\n`;
|
||||
|
||||
const exec = execSync(sh, { encoding: "utf-8" });
|
||||
@@ -240,6 +255,11 @@ export default async function setupWireguardHost({
|
||||
msg: [exec.trim(), manage_res.msg].join("\n\n"),
|
||||
};
|
||||
} catch (error: any) {
|
||||
console.log(
|
||||
`Error setting up wireguard host ${HOST_ID} =>`,
|
||||
error.message,
|
||||
);
|
||||
|
||||
return {
|
||||
success: false,
|
||||
msg: error.message,
|
||||
|
||||
@@ -8,6 +8,7 @@ import type {
|
||||
} from "@/db/types/db";
|
||||
import type { TableType } from "@/src/types";
|
||||
import { AppData } from "@/src/data/app-data";
|
||||
import bunext from "@moduletrace/bunext";
|
||||
|
||||
const HOST_CONFIG_FILE_NAME_PATTERN = /^wgui(\d+)\.conf$/;
|
||||
|
||||
@@ -50,7 +51,7 @@ export default async function syncWireguardHosts() {
|
||||
|
||||
const res = manageWireguardHost({ action: "up", host_id });
|
||||
|
||||
console.log(
|
||||
bunext.bunextLog.info(
|
||||
`[wgui] wireguard host ${host_config_file_name}: ${
|
||||
res.success ? `up` : `failed — ${res.msg}`
|
||||
}`,
|
||||
|
||||
@@ -0,0 +1,174 @@
|
||||
import type {
|
||||
BUN_SQLITE_WGUI_CLIENTS,
|
||||
BUN_SQLITE_WGUI_HOSTS,
|
||||
BUN_SQLITE_WGUI_VARIABLES,
|
||||
} from "@/db/types/db";
|
||||
import { AppData } from "@/src/data/app-data";
|
||||
import BunSQLite from "/home/archben/Projects/Git/moduletrace/bun-sqlite";
|
||||
// import BunSQLite from "@moduletrace/bun-sqlite";
|
||||
import type { APIResponseObject } from "@moduletrace/bunext/types";
|
||||
import type { TableType, User } from "@/src/types";
|
||||
import setupWireguardClient from "./setup-wireguard-client";
|
||||
import setupWireguardHost from "./setup-wireguard-host";
|
||||
|
||||
const IP_V4_REGEX = /^\d{1,3}(\.\d{1,3}){3}$/;
|
||||
|
||||
type Params = {
|
||||
host_id?: string | number | null;
|
||||
public_ip_address?: string | null;
|
||||
user: User;
|
||||
};
|
||||
|
||||
/**
|
||||
* Update the public IP address of a host and regenerate
|
||||
* every client config of that host with the new Endpoint.
|
||||
* @param param0
|
||||
* @returns
|
||||
*/
|
||||
export default async function updateWireguardHostPublicIP({
|
||||
host_id,
|
||||
public_ip_address,
|
||||
user,
|
||||
}: Params): Promise<APIResponseObject> {
|
||||
const final_host_id = Number(host_id || AppData["WireguardHostID"]);
|
||||
const ip = (public_ip_address || "").trim();
|
||||
|
||||
if (!ip || !IP_V4_REGEX.test(ip)) {
|
||||
return {
|
||||
success: false,
|
||||
msg: `Invalid public IP address provided`,
|
||||
};
|
||||
}
|
||||
|
||||
let host: BUN_SQLITE_WGUI_HOSTS | undefined;
|
||||
|
||||
try {
|
||||
if (final_host_id == AppData["WireguardHostID"]) {
|
||||
const update_variables = await BunSQLite.insert<
|
||||
BUN_SQLITE_WGUI_VARIABLES,
|
||||
TableType
|
||||
>({
|
||||
table: "variables",
|
||||
data: [
|
||||
{
|
||||
key: "main_host_public_ip_address",
|
||||
value: ip,
|
||||
},
|
||||
],
|
||||
update_on_duplicate: true,
|
||||
});
|
||||
|
||||
// console.log("update_variables", update_variables);
|
||||
|
||||
// if (!update_variables.success) {
|
||||
// throw new Error(`Couldn't update host public IP variable`);
|
||||
// }
|
||||
} else {
|
||||
const host_res = await BunSQLite.select<
|
||||
BUN_SQLITE_WGUI_HOSTS,
|
||||
TableType
|
||||
>({
|
||||
table: "hosts",
|
||||
targetId: final_host_id,
|
||||
});
|
||||
|
||||
host = host_res.singleRes || undefined;
|
||||
|
||||
if (!host) {
|
||||
return {
|
||||
success: false,
|
||||
msg: `Host record not found`,
|
||||
};
|
||||
}
|
||||
|
||||
const update_host = await BunSQLite.insert<
|
||||
BUN_SQLITE_WGUI_HOSTS,
|
||||
TableType
|
||||
>({
|
||||
table: "hosts",
|
||||
data: [
|
||||
{
|
||||
id: host.id,
|
||||
user_id: user.id,
|
||||
public_ip_address: ip,
|
||||
},
|
||||
],
|
||||
update_on_duplicate: true,
|
||||
});
|
||||
|
||||
if (!update_host.success) {
|
||||
throw new Error(`Couldn't update host record`);
|
||||
}
|
||||
|
||||
host.public_ip_address = ip;
|
||||
}
|
||||
} catch (error: any) {
|
||||
return {
|
||||
success: false,
|
||||
msg: error.message,
|
||||
};
|
||||
}
|
||||
|
||||
const host_clients_res = await BunSQLite.select<
|
||||
BUN_SQLITE_WGUI_CLIENTS,
|
||||
TableType
|
||||
>({
|
||||
table: "clients",
|
||||
query: {
|
||||
query: {
|
||||
host_id: {
|
||||
value: String(final_host_id),
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const clients = host_clients_res.payload || [];
|
||||
|
||||
let updated_count = 0;
|
||||
const client_errors: string[] = [];
|
||||
|
||||
for (let i = 0; i < clients.length; i++) {
|
||||
const client = clients[i];
|
||||
|
||||
if (!client?.id) continue;
|
||||
|
||||
const client_setup_res = await setupWireguardClient({
|
||||
client,
|
||||
host,
|
||||
user,
|
||||
skip_host_setup: true,
|
||||
});
|
||||
|
||||
console.log("client_setup_res", client_setup_res);
|
||||
|
||||
if (client_setup_res.success) {
|
||||
updated_count++;
|
||||
} else {
|
||||
client_errors.push(
|
||||
`Client ${client.name || `#${client.id}`}: ${client_setup_res.msg}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const host_setup_res = await setupWireguardHost({
|
||||
host,
|
||||
user,
|
||||
is_update_after_client_setup: true,
|
||||
});
|
||||
|
||||
if (!host_setup_res.success) {
|
||||
return {
|
||||
success: false,
|
||||
msg: `${updated_count} client config(s) updated, but the host could not be restarted: ${host_setup_res.msg}`,
|
||||
numberRes: updated_count,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
msg: `Host IP updated to ${ip}. ${updated_count} client config(s) regenerated.`,
|
||||
numberRes: updated_count,
|
||||
stringRes: client_errors[0] ? client_errors.join("; ") : null,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user