Fix client access scope
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import type { BUN_SQLITE_WGUI_CLIENT_RULES } from "@/db/types/db";
|
||||
import parsePortList from "@/src/utils/parse-port-list";
|
||||
import validateIpv4 from "@/src/utils/validate-ipv4";
|
||||
import validateIpv4Cidr from "@/src/utils/validate-ipv4-cidr";
|
||||
import deriveIptablesChainNames from "./derive-iptables-chain-names";
|
||||
import normalizeIptablesDestination from "./normalize-iptables-destination";
|
||||
import validateClientRule from "./validate-client-rule";
|
||||
@@ -15,6 +16,7 @@ type Params = {
|
||||
host_id: number;
|
||||
interface_name: string;
|
||||
target_interface: string;
|
||||
host_subnet?: string;
|
||||
clients?: HostIptablesClient[];
|
||||
};
|
||||
|
||||
@@ -123,6 +125,7 @@ export default function buildHostIptablesScripts({
|
||||
host_id,
|
||||
interface_name,
|
||||
target_interface,
|
||||
host_subnet,
|
||||
clients,
|
||||
}: Params) {
|
||||
if (!Number.isInteger(host_id) || host_id < 0) {
|
||||
@@ -146,6 +149,15 @@ export default function buildHostIptablesScripts({
|
||||
};
|
||||
}
|
||||
|
||||
const scoped_subnet = host_subnet?.trim();
|
||||
|
||||
if (scoped_subnet && !validateIpv4Cidr({ value: scoped_subnet })) {
|
||||
return {
|
||||
success: false,
|
||||
msg: `Invalid host subnet "${scoped_subnet}"`,
|
||||
};
|
||||
}
|
||||
|
||||
const { forward, input } = deriveIptablesChainNames({ host_id });
|
||||
const accept_lines: string[] = [];
|
||||
const host_clients = clients || [];
|
||||
@@ -193,12 +205,19 @@ export default function buildHostIptablesScripts({
|
||||
}
|
||||
|
||||
if (rule.rule_type == "all") {
|
||||
accept_lines.push(
|
||||
`iptables -A ${forward} -s ${source} -j ACCEPT`,
|
||||
);
|
||||
accept_lines.push(
|
||||
`iptables -A ${input} -s ${source} -j ACCEPT`,
|
||||
);
|
||||
if (scoped_subnet) {
|
||||
accept_lines.push(
|
||||
`iptables -A ${forward} -s ${source} -d ${scoped_subnet} -j ACCEPT`,
|
||||
`iptables -A ${forward} -s ${source} -o ${target_interface} -j ACCEPT`,
|
||||
`iptables -A ${input} -s ${source} -d ${scoped_subnet} -j ACCEPT`,
|
||||
);
|
||||
} else {
|
||||
accept_lines.push(
|
||||
`iptables -A ${forward} -s ${source} -j ACCEPT`,
|
||||
`iptables -A ${input} -s ${source} -j ACCEPT`,
|
||||
);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -172,10 +172,13 @@ export default async function setupWireguardHost({
|
||||
|
||||
sh += `cd ${HOST_CONFIG_DIR}\n`;
|
||||
|
||||
const HOST_SUBNET = `${HOST_WG_IP.split(".").slice(0, 3).join(".")}.0/24`;
|
||||
|
||||
const iptables_scripts = buildHostIptablesScripts({
|
||||
host_id: Number(HOST_ID),
|
||||
interface_name: INTERFACE_NAME,
|
||||
target_interface: TARGET_INTERFACE || "eth0",
|
||||
host_subnet: HOST_SUBNET,
|
||||
clients: clients.map((client) => ({
|
||||
id: client.id,
|
||||
wg_ip_address: client.wg_ip_address,
|
||||
|
||||
@@ -1,142 +0,0 @@
|
||||
import { useContext, useState } from "react";
|
||||
import { CircleCheck, TriangleAlert } from "lucide-react";
|
||||
import AdminCard from "@/src/components/general/admin-card";
|
||||
import HostWgIpField, {
|
||||
type HostWgIpFieldStatus,
|
||||
} from "@/src/components/general/host-wg-ip-field";
|
||||
import useStatus from "@/src/components/twui/hooks/useStatus";
|
||||
import fetchApi from "@/src/components/twui/utils/fetch/fetchApi";
|
||||
import H3 from "@/src/components/twui/layout/H3";
|
||||
import P from "@/src/components/twui/layout/P";
|
||||
import Row from "@/src/components/twui/layout/Row";
|
||||
import Span from "@/src/components/twui/layout/Span";
|
||||
import Stack from "@/src/components/twui/layout/Stack";
|
||||
import Tag from "@/src/components/twui/elements/Tag";
|
||||
import Button from "@/src/components/twui/layout/Button";
|
||||
import { AppContext } from "@/src/pages/__root";
|
||||
import HostPublicIpSection from "../../../(sections)/host-public-ip-section";
|
||||
import type { ApiReqParams } from "@/src/types";
|
||||
import type { APIResponseObject } from "@moduletrace/bunext/types";
|
||||
|
||||
export default function EditHostFormSection() {
|
||||
const { pageProps, query } = useContext(AppContext);
|
||||
|
||||
const host_id = Number(query?.host_id || pageProps?.host?.id || 0);
|
||||
const host = pageProps?.host;
|
||||
|
||||
const { loading, setLoading, status, setStatus } = useStatus();
|
||||
|
||||
const [wgIP, setWgIP] = useState<string>(host?.wg_ip_address || "");
|
||||
const [ipStatus, setIpStatus] = useState<HostWgIpFieldStatus>("checking");
|
||||
|
||||
function handleSave() {
|
||||
if (!window.confirm("Update this host configuration?")) return;
|
||||
|
||||
setStatus(undefined);
|
||||
setLoading(true);
|
||||
|
||||
fetchApi<ApiReqParams, APIResponseObject>(
|
||||
`/api/admin/update-host-wg-ip`,
|
||||
{
|
||||
method: "POST",
|
||||
body: {
|
||||
host_id,
|
||||
wg_ip_address: wgIP,
|
||||
},
|
||||
},
|
||||
)
|
||||
.then((res) => {
|
||||
if (res.success) {
|
||||
window.location.pathname = `/admin/hosts/${host_id}`;
|
||||
return;
|
||||
}
|
||||
|
||||
setStatus({
|
||||
error: true,
|
||||
success: false,
|
||||
msg: res.msg || "Could not update the host",
|
||||
});
|
||||
})
|
||||
.catch((error: any) => {
|
||||
setStatus({
|
||||
error: true,
|
||||
success: false,
|
||||
msg: error.message || "Could not update the host",
|
||||
});
|
||||
})
|
||||
.finally(() => {
|
||||
setLoading(false);
|
||||
});
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<AdminCard className="w-full p-5 flex flex-col gap-4">
|
||||
<Stack className="gap-1">
|
||||
<H3 className="text-[14px] font-semibold mb-0!">
|
||||
WireGuard subnet
|
||||
</H3>
|
||||
<P
|
||||
noMargin
|
||||
className="text-[12.5px] text-foreground-light/45 dark:text-foreground-dark/45"
|
||||
>
|
||||
The private subnet the host listens on (e.g.
|
||||
10.1.0.1/24). Updating it rewrites the host config and
|
||||
restarts the tunnel.
|
||||
</P>
|
||||
</Stack>
|
||||
|
||||
{/* <HostWgIpField
|
||||
value={wgIP}
|
||||
onChange={setWgIP}
|
||||
onStatus={setIpStatus}
|
||||
current_value={host?.wg_ip_address || ""}
|
||||
autoFocus
|
||||
/> */}
|
||||
|
||||
{status?.error && status.msg ? (
|
||||
<Tag
|
||||
variant="outlined"
|
||||
color="error"
|
||||
className="w-full py-1.5 outline-error/50 bg-error/5!"
|
||||
>
|
||||
<Row>
|
||||
<TriangleAlert size={15} />
|
||||
<Span>{status.msg}</Span>
|
||||
</Row>
|
||||
</Tag>
|
||||
) : null}
|
||||
{status?.success && status.msg ? (
|
||||
<Tag
|
||||
variant="outlined"
|
||||
color="success"
|
||||
className="w-full py-1.5 outline-success/50 bg-success/5!"
|
||||
>
|
||||
<Row>
|
||||
<CircleCheck size={15} />
|
||||
<Span>{status.msg}</Span>
|
||||
</Row>
|
||||
</Tag>
|
||||
) : null}
|
||||
|
||||
<Row className="w-full items-center gap-2">
|
||||
<Button
|
||||
title="Save Changes"
|
||||
disabled={
|
||||
ipStatus !== "available" && ipStatus !== "current"
|
||||
}
|
||||
loading={loading}
|
||||
onClick={handleSave}
|
||||
>
|
||||
Save Changes
|
||||
</Button>
|
||||
</Row>
|
||||
</AdminCard>
|
||||
|
||||
<HostPublicIpSection
|
||||
host_id={host_id}
|
||||
current_ip={host?.public_ip_address || ""}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -8,7 +8,6 @@ import EmptyContent from "@/src/components/twui/elements/EmptyContent";
|
||||
import { ArrowLeft } from "lucide-react";
|
||||
import { useContext } from "react";
|
||||
import { AppContext } from "@/src/pages/__root";
|
||||
import EditHostFormSection from "./(sections)/edit-host-form-section";
|
||||
import AddHostForm from "../../add/(partials)/add-host-form/add-host-form";
|
||||
import _ from "lodash";
|
||||
import type { BUN_SQLITE_WGUI_HOSTS_JOIN } from "@/src/types/sql-joins";
|
||||
|
||||
Reference in New Issue
Block a user