Add firewall rules logic for all hosts
This commit is contained in:
@@ -0,0 +1,191 @@
|
||||
import { execSync } from "node:child_process";
|
||||
import validateIpv4Cidr from "@/src/utils/validate-ipv4-cidr";
|
||||
import detectFirewallManager, {
|
||||
type FirewallManager,
|
||||
} from "./detect-firewall-manager";
|
||||
|
||||
export type AllowSubnetFirewallRulesResult = {
|
||||
success: boolean;
|
||||
manager: FirewallManager | "none";
|
||||
msg: string;
|
||||
added_rules: string[];
|
||||
skipped_rules: string[];
|
||||
};
|
||||
|
||||
type Params = {
|
||||
subnet: string;
|
||||
listen_port: number;
|
||||
};
|
||||
|
||||
type ShellResult = {
|
||||
success: boolean;
|
||||
output: string;
|
||||
};
|
||||
|
||||
const tryShell = ({ command }: { command: string }): ShellResult => {
|
||||
try {
|
||||
const result = execSync(command, {
|
||||
encoding: "utf-8",
|
||||
stdio: "pipe",
|
||||
timeout: 30000,
|
||||
});
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: String(result).trim(),
|
||||
};
|
||||
} catch (error: any) {
|
||||
const stdout = error?.stdout ? String(error.stdout).trim() : "";
|
||||
const stderr = error?.stderr ? String(error.stderr).trim() : "";
|
||||
|
||||
return {
|
||||
success: false,
|
||||
output: [stdout, stderr].filter(Boolean).join("\n").trim(),
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
const isValidPort = ({ port }: { port: number }) =>
|
||||
Number.isInteger(port) && port >= 1 && port <= 65535;
|
||||
|
||||
export default async function allowSubnetFirewallRules({
|
||||
subnet,
|
||||
listen_port,
|
||||
}: Params): Promise<AllowSubnetFirewallRulesResult> {
|
||||
const subnet_trimmed = subnet?.trim();
|
||||
|
||||
if (!validateIpv4Cidr({ value: subnet_trimmed })) {
|
||||
return {
|
||||
success: false,
|
||||
manager: "none",
|
||||
msg: `Invalid subnet "${subnet_trimmed}"`,
|
||||
added_rules: [],
|
||||
skipped_rules: [],
|
||||
};
|
||||
}
|
||||
|
||||
if (!isValidPort({ port: listen_port })) {
|
||||
return {
|
||||
success: false,
|
||||
manager: "none",
|
||||
msg: `Invalid listen port ${listen_port}`,
|
||||
added_rules: [],
|
||||
skipped_rules: [],
|
||||
};
|
||||
}
|
||||
|
||||
const manager = detectFirewallManager();
|
||||
|
||||
const added_rules: string[] = [];
|
||||
const skipped_rules: string[] = [];
|
||||
|
||||
if (manager == "firewalld") {
|
||||
const subnet_rule = `rule family="ipv4" source address="${subnet_trimmed}" accept`;
|
||||
const subnet_add = tryShell({
|
||||
command: `firewall-cmd --permanent --add-rich-rule='${subnet_rule}'`,
|
||||
});
|
||||
|
||||
if (subnet_add.success) {
|
||||
added_rules.push(`allow all traffic from ${subnet_trimmed}`);
|
||||
} else {
|
||||
skipped_rules.push(
|
||||
`firewalld subnet rule not applied: ${subnet_add.output}`,
|
||||
);
|
||||
}
|
||||
|
||||
const port_rule = `${listen_port}/udp`;
|
||||
const port_add = tryShell({
|
||||
command: `firewall-cmd --permanent --add-port=${port_rule}`,
|
||||
});
|
||||
|
||||
if (port_add.success) {
|
||||
added_rules.push(`allow ${port_rule} from anywhere (wireguard)`);
|
||||
} else {
|
||||
skipped_rules.push(
|
||||
`firewalld port rule not applied: ${port_add.output}`,
|
||||
);
|
||||
}
|
||||
|
||||
const reload = tryShell({ command: `firewall-cmd --reload` });
|
||||
|
||||
if (!reload.success) {
|
||||
skipped_rules.push(`firewalld reload failed: ${reload.output}`);
|
||||
}
|
||||
} else if (manager == "ufw") {
|
||||
const ufw_status = tryShell({ command: `ufw status` });
|
||||
|
||||
if (
|
||||
!ufw_status.success ||
|
||||
!ufw_status.output.includes(`Status: active`)
|
||||
) {
|
||||
return {
|
||||
success: false,
|
||||
manager,
|
||||
msg: `ufw is not active — cannot add firewall rules`,
|
||||
added_rules,
|
||||
skipped_rules,
|
||||
};
|
||||
}
|
||||
|
||||
if (ufw_status.output.includes(subnet_trimmed)) {
|
||||
skipped_rules.push(`subnet ${subnet_trimmed} already allowed`);
|
||||
} else {
|
||||
const subnet_add = tryShell({
|
||||
command: `ufw allow from ${subnet_trimmed}`,
|
||||
});
|
||||
|
||||
if (subnet_add.success) {
|
||||
added_rules.push(`allow all traffic from ${subnet_trimmed}`);
|
||||
} else {
|
||||
skipped_rules.push(
|
||||
`ufw subnet rule not applied: ${subnet_add.output}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const port_rule = `${listen_port}/udp`;
|
||||
|
||||
if (ufw_status.output.includes(port_rule)) {
|
||||
skipped_rules.push(`port ${port_rule} already allowed`);
|
||||
} else {
|
||||
const port_add = tryShell({ command: `ufw allow ${port_rule}` });
|
||||
|
||||
if (port_add.success) {
|
||||
added_rules.push(
|
||||
`allow ${port_rule} from anywhere (wireguard)`,
|
||||
);
|
||||
} else {
|
||||
skipped_rules.push(
|
||||
`ufw port rule not applied: ${port_add.output}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (manager == "none") {
|
||||
return {
|
||||
success: true,
|
||||
manager,
|
||||
msg: `no active firewall manager detected (firewalld/ufw) — no rules added; if you use iptables/nftables directly, allow ${subnet_trimmed} and udp port ${listen_port} manually`,
|
||||
added_rules,
|
||||
skipped_rules,
|
||||
};
|
||||
}
|
||||
|
||||
const summary = [
|
||||
added_rules.length
|
||||
? `firewall(${manager}): added — ${added_rules.join("; ")}`
|
||||
: `firewall(${manager}): no new rules added`,
|
||||
skipped_rules.length ? `skipped — ${skipped_rules.join("; ")}` : ``,
|
||||
]
|
||||
.filter(Boolean)
|
||||
.join(` `);
|
||||
|
||||
return {
|
||||
success: true,
|
||||
manager,
|
||||
msg: summary,
|
||||
added_rules,
|
||||
skipped_rules,
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
import { execSync } from "node:child_process";
|
||||
|
||||
export type FirewallManager = "firewalld" | "ufw" | "none";
|
||||
|
||||
export default function detectFirewallManager(): FirewallManager {
|
||||
try {
|
||||
execSync(`command -v firewall-cmd`, {
|
||||
encoding: "utf-8",
|
||||
stdio: "pipe",
|
||||
timeout: 5000,
|
||||
});
|
||||
|
||||
execSync(`systemctl is-active --quiet firewalld`, {
|
||||
encoding: "utf-8",
|
||||
stdio: "pipe",
|
||||
timeout: 5000,
|
||||
});
|
||||
|
||||
return "firewalld";
|
||||
} catch {}
|
||||
|
||||
try {
|
||||
const ufw_status = execSync(`ufw status`, {
|
||||
encoding: "utf-8",
|
||||
stdio: "pipe",
|
||||
timeout: 10000,
|
||||
});
|
||||
|
||||
if (String(ufw_status).includes(`Status: active`)) {
|
||||
return "ufw";
|
||||
}
|
||||
} catch {}
|
||||
|
||||
return "none";
|
||||
}
|
||||
@@ -0,0 +1,276 @@
|
||||
import { execSync } from "node:child_process";
|
||||
import BunSQLite from "@moduletrace/bun-sqlite";
|
||||
import type { BUN_SQLITE_WGUI_HOSTS } from "@/db/types/db";
|
||||
import { AppData } from "@/src/data/app-data";
|
||||
import { SiteData } from "@/src/data/site-data";
|
||||
import type { TableType } from "@/src/types";
|
||||
import validateIpv4Cidr from "@/src/utils/validate-ipv4-cidr";
|
||||
import detectFirewallManager, {
|
||||
type FirewallManager,
|
||||
} from "./detect-firewall-manager";
|
||||
|
||||
export type FirewallRuleKind = "required" | "temporary" | "orphaned" | "other";
|
||||
|
||||
export type FirewallRuleInfo = {
|
||||
id: string;
|
||||
kind: FirewallRuleKind;
|
||||
description: string;
|
||||
delete_command?: string;
|
||||
};
|
||||
|
||||
export type FirewallStatus = {
|
||||
manager: FirewallManager;
|
||||
rules: FirewallRuleInfo[];
|
||||
managed_subnets: string[];
|
||||
managed_ports: string[];
|
||||
dashboard_port: number;
|
||||
hosts_found: boolean;
|
||||
};
|
||||
|
||||
type ShellResult = {
|
||||
success: boolean;
|
||||
output: string;
|
||||
};
|
||||
|
||||
const tryShell = ({ command }: { command: string }): ShellResult => {
|
||||
try {
|
||||
const result = execSync(command, {
|
||||
encoding: "utf-8",
|
||||
stdio: "pipe",
|
||||
timeout: 10000,
|
||||
});
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: String(result).trim(),
|
||||
};
|
||||
} catch (error: any) {
|
||||
const stdout = error?.stdout ? String(error.stdout).trim() : "";
|
||||
const stderr = error?.stderr ? String(error.stderr).trim() : "";
|
||||
|
||||
return {
|
||||
success: false,
|
||||
output: [stdout, stderr].filter(Boolean).join("\n").trim(),
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
const isCidr = ({ value }: { value: string }) => validateIpv4Cidr({ value });
|
||||
|
||||
const stripV6Suffix = ({ value }: { value: string }) =>
|
||||
value.replace(/\s*\(v6\)$/i, "").trim();
|
||||
|
||||
const normalizeSpec = ({ value }: { value: string }) =>
|
||||
stripV6Suffix({ value: value.toLowerCase() });
|
||||
|
||||
type ManagedSpecs = {
|
||||
managed_subnets: string[];
|
||||
managed_ports: string[];
|
||||
dashboard_port: number;
|
||||
};
|
||||
|
||||
type ClassifiedRule = {
|
||||
id: string;
|
||||
kind: FirewallRuleKind;
|
||||
description: string;
|
||||
delete_command?: string;
|
||||
};
|
||||
|
||||
const classifyRule = ({
|
||||
spec,
|
||||
manager,
|
||||
managed,
|
||||
}: {
|
||||
spec: string;
|
||||
manager: "ufw" | "firewalld";
|
||||
managed: ManagedSpecs;
|
||||
}): ClassifiedRule | null => {
|
||||
const normalized = normalizeSpec({ value: spec });
|
||||
|
||||
if (!normalized) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (normalized == `${managed.dashboard_port}/tcp`) {
|
||||
const delete_command =
|
||||
manager == "ufw"
|
||||
? `ufw delete allow ${normalized}`
|
||||
: `firewall-cmd --permanent --remove-port=${normalized} && firewall-cmd --reload`;
|
||||
|
||||
return {
|
||||
id: `${manager}-${normalized}`,
|
||||
kind: "temporary",
|
||||
description: `TCP ${managed.dashboard_port} open to the world — the wg-ui dashboard bootstrap rule (remove once hosts are reachable via the tunnel)`,
|
||||
delete_command,
|
||||
};
|
||||
}
|
||||
|
||||
if (managed.managed_ports.includes(normalized)) {
|
||||
return {
|
||||
id: `${manager}-${normalized}`,
|
||||
kind: "required",
|
||||
description: `${normalized} — wireguard listen port (matches a host)`,
|
||||
};
|
||||
}
|
||||
|
||||
if (isCidr({ value: normalized })) {
|
||||
if (managed.managed_subnets.includes(normalized)) {
|
||||
return {
|
||||
id: `${manager}-${normalized}`,
|
||||
kind: "required",
|
||||
description: `All traffic from ${normalized} — host subnet`,
|
||||
};
|
||||
}
|
||||
|
||||
const delete_command =
|
||||
manager == "ufw"
|
||||
? `ufw delete allow from ${normalized}`
|
||||
: `firewall-cmd --permanent --remove-rich-rule='rule family="ipv4" source address="${normalized}" accept' && firewall-cmd --reload`;
|
||||
|
||||
return {
|
||||
id: `${manager}-${normalized}`,
|
||||
kind: "orphaned",
|
||||
description: `All traffic from ${normalized} — matches no host subnet (stale, safe to remove)`,
|
||||
delete_command,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
id: `${manager}-${normalized}`,
|
||||
kind: "other",
|
||||
description: `${normalized} — unmanaged rule`,
|
||||
};
|
||||
};
|
||||
|
||||
const grabUfwRules = ({
|
||||
managed,
|
||||
}: {
|
||||
managed: ManagedSpecs;
|
||||
}): ClassifiedRule[] => {
|
||||
const status = tryShell({ command: `ufw status numbered` });
|
||||
|
||||
if (!status.success) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const rules: ClassifiedRule[] = [];
|
||||
|
||||
for (const line of status.output.split("\n")) {
|
||||
const stripped = line
|
||||
.replace(/^\[\s*\d+\]\s*/, "")
|
||||
.split(/\s+/)
|
||||
.filter(Boolean);
|
||||
|
||||
const status_index = stripped.indexOf("ALLOW");
|
||||
|
||||
if (status_index < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const spec = stripped.slice(0, status_index).join(" ");
|
||||
const rule = classifyRule({ spec, manager: "ufw", managed });
|
||||
|
||||
if (rule) {
|
||||
rules.push(rule);
|
||||
}
|
||||
}
|
||||
|
||||
return rules;
|
||||
};
|
||||
|
||||
const grabFirewalldRules = ({
|
||||
managed,
|
||||
}: {
|
||||
managed: ManagedSpecs;
|
||||
}): ClassifiedRule[] => {
|
||||
const rules: ClassifiedRule[] = [];
|
||||
const port_res = tryShell({ command: `firewall-cmd --permanent --list-ports` });
|
||||
|
||||
if (port_res.success) {
|
||||
for (const spec of port_res.output.split(/\s+/).filter(Boolean)) {
|
||||
const rule = classifyRule({ spec, manager: "firewalld", managed });
|
||||
|
||||
if (rule) {
|
||||
rules.push(rule);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const rich_res = tryShell({
|
||||
command: `firewall-cmd --permanent --list-rich-rules`,
|
||||
});
|
||||
|
||||
if (rich_res.success) {
|
||||
for (const line of rich_res.output.split("\n")) {
|
||||
const source_match = line.match(/source\s+address="([^"]+)"/);
|
||||
|
||||
if (!source_match?.[1]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const rule = classifyRule({
|
||||
spec: source_match[1],
|
||||
manager: "firewalld",
|
||||
managed,
|
||||
});
|
||||
|
||||
if (rule) {
|
||||
rules.push(rule);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return rules;
|
||||
};
|
||||
|
||||
export default async function grabFirewallStatus(): Promise<FirewallStatus> {
|
||||
const manager = detectFirewallManager();
|
||||
|
||||
const hosts_res = await BunSQLite.select<BUN_SQLITE_WGUI_HOSTS, TableType>({
|
||||
table: "hosts",
|
||||
});
|
||||
|
||||
const hosts = hosts_res.payload || [];
|
||||
const managed_subnets: string[] = [];
|
||||
const managed_ports: string[] = [];
|
||||
|
||||
for (const host of hosts) {
|
||||
if (host?.wg_ip_address) {
|
||||
managed_subnets.push(
|
||||
`${host.wg_ip_address.split(".").slice(0, 3).join(".")}.0/24`,
|
||||
);
|
||||
}
|
||||
|
||||
const listen_port =
|
||||
host?.listen_port || AppData["DefaultWGListenPort"];
|
||||
|
||||
const port_spec = `${listen_port}/udp`;
|
||||
|
||||
if (!managed_ports.includes(port_spec)) {
|
||||
managed_ports.push(port_spec);
|
||||
}
|
||||
}
|
||||
|
||||
const managed: ManagedSpecs = {
|
||||
managed_subnets,
|
||||
managed_ports,
|
||||
dashboard_port: SiteData["ServerPort"],
|
||||
};
|
||||
|
||||
let rules: ClassifiedRule[] = [];
|
||||
|
||||
if (manager == "ufw") {
|
||||
rules = grabUfwRules({ managed });
|
||||
} else if (manager == "firewalld") {
|
||||
rules = grabFirewalldRules({ managed });
|
||||
}
|
||||
|
||||
return {
|
||||
manager,
|
||||
rules,
|
||||
managed_subnets,
|
||||
managed_ports,
|
||||
dashboard_port: SiteData["ServerPort"],
|
||||
hosts_found: hosts.length > 0,
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,174 @@
|
||||
import { execSync } from "node:child_process";
|
||||
import validateIpv4Cidr from "@/src/utils/validate-ipv4-cidr";
|
||||
import detectFirewallManager, {
|
||||
type FirewallManager,
|
||||
} from "./detect-firewall-manager";
|
||||
|
||||
export type RemoveSubnetFirewallRulesResult = {
|
||||
success: boolean;
|
||||
manager: FirewallManager | "none";
|
||||
msg: string;
|
||||
removed_rules: string[];
|
||||
skipped_rules: string[];
|
||||
};
|
||||
|
||||
type Params = {
|
||||
subnet: string;
|
||||
listen_port: number;
|
||||
};
|
||||
|
||||
type ShellResult = {
|
||||
success: boolean;
|
||||
output: string;
|
||||
};
|
||||
|
||||
const tryShell = ({ command }: { command: string }): ShellResult => {
|
||||
try {
|
||||
const result = execSync(command, {
|
||||
encoding: "utf-8",
|
||||
stdio: "pipe",
|
||||
timeout: 30000,
|
||||
});
|
||||
|
||||
return {
|
||||
success: true,
|
||||
output: String(result).trim(),
|
||||
};
|
||||
} catch (error: any) {
|
||||
const stdout = error?.stdout ? String(error.stdout).trim() : "";
|
||||
const stderr = error?.stderr ? String(error.stderr).trim() : "";
|
||||
|
||||
return {
|
||||
success: false,
|
||||
output: [stdout, stderr].filter(Boolean).join("\n").trim(),
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
const isValidPort = ({ port }: { port: number }) =>
|
||||
Number.isInteger(port) && port >= 1 && port <= 65535;
|
||||
|
||||
export default async function removeSubnetFirewallRules({
|
||||
subnet,
|
||||
listen_port,
|
||||
}: Params): Promise<RemoveSubnetFirewallRulesResult> {
|
||||
const subnet_trimmed = subnet?.trim();
|
||||
|
||||
if (!validateIpv4Cidr({ value: subnet_trimmed })) {
|
||||
return {
|
||||
success: false,
|
||||
manager: "none",
|
||||
msg: `Invalid subnet "${subnet_trimmed}"`,
|
||||
removed_rules: [],
|
||||
skipped_rules: [],
|
||||
};
|
||||
}
|
||||
|
||||
if (!isValidPort({ port: listen_port })) {
|
||||
return {
|
||||
success: false,
|
||||
manager: "none",
|
||||
msg: `Invalid listen port ${listen_port}`,
|
||||
removed_rules: [],
|
||||
skipped_rules: [],
|
||||
};
|
||||
}
|
||||
|
||||
const manager = detectFirewallManager();
|
||||
const removed_rules: string[] = [];
|
||||
const skipped_rules: string[] = [];
|
||||
|
||||
if (manager == "firewalld") {
|
||||
const subnet_rule = `rule family="ipv4" source address="${subnet_trimmed}" accept`;
|
||||
const subnet_remove = tryShell({
|
||||
command: `firewall-cmd --permanent --remove-rich-rule='${subnet_rule}'`,
|
||||
});
|
||||
|
||||
if (subnet_remove.success) {
|
||||
removed_rules.push(`removed subnet allow for ${subnet_trimmed}`);
|
||||
} else {
|
||||
skipped_rules.push(
|
||||
`firewalld subnet rule not removed: ${subnet_remove.output}`,
|
||||
);
|
||||
}
|
||||
|
||||
const port_rule = `${listen_port}/udp`;
|
||||
const port_remove = tryShell({
|
||||
command: `firewall-cmd --permanent --remove-port=${port_rule}`,
|
||||
});
|
||||
|
||||
if (port_remove.success) {
|
||||
removed_rules.push(`removed ${port_rule} allow`);
|
||||
} else {
|
||||
skipped_rules.push(`firewalld port rule not removed: ${port_remove.output}`);
|
||||
}
|
||||
|
||||
const reload = tryShell({ command: `firewall-cmd --reload` });
|
||||
|
||||
if (!reload.success) {
|
||||
skipped_rules.push(`firewalld reload failed: ${reload.output}`);
|
||||
}
|
||||
} else if (manager == "ufw") {
|
||||
const ufw_status = tryShell({ command: `ufw status` });
|
||||
const ufw_rules = ufw_status.success ? ufw_status.output : "";
|
||||
|
||||
if (ufw_rules.includes(subnet_trimmed)) {
|
||||
const subnet_remove = tryShell({
|
||||
command: `ufw delete allow from ${subnet_trimmed}`,
|
||||
});
|
||||
|
||||
if (subnet_remove.success) {
|
||||
removed_rules.push(`removed subnet allow for ${subnet_trimmed}`);
|
||||
} else {
|
||||
skipped_rules.push(
|
||||
`ufw subnet rule not removed: ${subnet_remove.output}`,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
skipped_rules.push(`subnet ${subnet_trimmed} not present — nothing to remove`);
|
||||
}
|
||||
|
||||
const port_rule = `${listen_port}/udp`;
|
||||
|
||||
if (ufw_rules.includes(port_rule)) {
|
||||
const port_remove = tryShell({
|
||||
command: `ufw delete allow ${port_rule}`,
|
||||
});
|
||||
|
||||
if (port_remove.success) {
|
||||
removed_rules.push(`removed ${port_rule} allow`);
|
||||
} else {
|
||||
skipped_rules.push(`ufw port rule not removed: ${port_remove.output}`);
|
||||
}
|
||||
} else {
|
||||
skipped_rules.push(`port ${port_rule} not present — nothing to remove`);
|
||||
}
|
||||
}
|
||||
|
||||
if (manager == "none") {
|
||||
return {
|
||||
success: true,
|
||||
manager,
|
||||
msg: `no active firewall manager detected (firewalld/ufw) — no rules removed; if you use iptables/nftables directly, remove ${subnet_trimmed} and udp port ${listen_port} rules manually`,
|
||||
removed_rules,
|
||||
skipped_rules,
|
||||
};
|
||||
}
|
||||
|
||||
const summary = [
|
||||
removed_rules.length
|
||||
? `firewall(${manager}): removed — ${removed_rules.join("; ")}`
|
||||
: `firewall(${manager}): no rules removed`,
|
||||
skipped_rules.length ? `skipped — ${skipped_rules.join("; ")}` : ``,
|
||||
]
|
||||
.filter(Boolean)
|
||||
.join(` `);
|
||||
|
||||
return {
|
||||
success: true,
|
||||
manager,
|
||||
msg: summary,
|
||||
removed_rules,
|
||||
skipped_rules,
|
||||
};
|
||||
}
|
||||
@@ -9,6 +9,8 @@ import type { TableType, User } from "@/src/types";
|
||||
import manageWireguardHost from "./manage-wireguard-host";
|
||||
import grabHostDirnames from "./grab-host-dir-names";
|
||||
import grabClientDirnames from "./grab-client-dir-names";
|
||||
import removeSubnetFirewallRules from "../firewall/remove-subnet-firewall-rules";
|
||||
import { AppData } from "@/src/data/app-data";
|
||||
import { execSync } from "node:child_process";
|
||||
|
||||
type Params = {
|
||||
@@ -74,6 +76,41 @@ export default async function deleteWireguardHost({
|
||||
});
|
||||
} catch {}
|
||||
|
||||
try {
|
||||
const host_res = await BunSQLite.select<
|
||||
BUN_SQLITE_WGUI_HOSTS,
|
||||
TableType
|
||||
>({
|
||||
table: "hosts",
|
||||
targetId: host_id,
|
||||
});
|
||||
|
||||
const host = host_res.singleRes;
|
||||
|
||||
if (host?.wg_ip_address) {
|
||||
const host_subnet = `${host.wg_ip_address
|
||||
.split(".")
|
||||
.slice(0, 3)
|
||||
.join(".")}.0/24`;
|
||||
|
||||
const firewall_res = await removeSubnetFirewallRules({
|
||||
subnet: host_subnet,
|
||||
listen_port:
|
||||
host.listen_port || AppData["DefaultWGListenPort"],
|
||||
});
|
||||
|
||||
if (!firewall_res.success) {
|
||||
console.log(
|
||||
`Warning removing firewall rules for host ${host_id} => ${firewall_res.msg}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
} catch (error: any) {
|
||||
console.log(
|
||||
`Warning removing firewall rules for host ${host_id} => ${error.message}`,
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
execSync(`rm -rf ${HOST_CONFIG_DIR}`, { encoding: "utf-8" });
|
||||
} catch {}
|
||||
|
||||
@@ -14,6 +14,7 @@ import manageWireguardHost from "./manage-wireguard-host";
|
||||
import grabHostDirnames from "./grab-host-dir-names";
|
||||
import grabClientDirnames from "./grab-client-dir-names";
|
||||
import buildHostIptablesScripts from "./build-host-iptables-scripts";
|
||||
import allowSubnetFirewallRules from "../firewall/allow-subnet-firewall-rules";
|
||||
import { AppData } from "@/src/data/app-data";
|
||||
|
||||
const { WIREGUARD_PRIVATE_KEY_FILE_NAME, WIREGUARD_PUBLIC_KEY_FILE_NAME } =
|
||||
@@ -267,9 +268,20 @@ export default async function setupWireguardHost({
|
||||
};
|
||||
}
|
||||
|
||||
const firewall_res = await allowSubnetFirewallRules({
|
||||
subnet: HOST_SUBNET,
|
||||
listen_port: host?.listen_port || AppData["DefaultWGListenPort"],
|
||||
});
|
||||
|
||||
if (!firewall_res.success) {
|
||||
console.log(
|
||||
`Warning setting up firewall rules for host ${HOST_ID} => ${firewall_res.msg}`,
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
success: true,
|
||||
msg: [exec.trim(), manage_res.msg].join("\n\n"),
|
||||
msg: [exec.trim(), manage_res.msg, firewall_res.msg].join("\n\n"),
|
||||
};
|
||||
} catch (error: any) {
|
||||
console.log(
|
||||
|
||||
Reference in New Issue
Block a user