Fix iptables internet forwarding bug. Update UI errors.

This commit is contained in:
2026-09-27 06:08:07 +01:00
parent dc8700feaa
commit 400831246f
16 changed files with 136 additions and 97 deletions
+1 -1
View File
@@ -88,7 +88,7 @@ export default function HostWgIpField({
<Stack className="w-full gap-2">
<Row className="w-full flex-nowrap">
<Input
value={value}
defaultValue={value}
changeHandler={(v) => {
onChange?.(v);
}}
@@ -25,13 +25,6 @@ export default function SetupMainHostButton({ button_props }: Props) {
return (
<Stack className="w-full items-stretch gap-3">
{/* <HostWgIpField
value={wgIP}
onChange={setWgIP}
onStatus={setIpStatus}
autoFocus
/> */}
{status?.error && status.msg ? (
<Tag
variant="outlined"
+1 -1
View File
@@ -19,5 +19,5 @@ export const AppData = {
WireguardMainHostID: 0,
DefaultPrivateIP: `10.1.0.1`,
DefaultWGListenPort: 51820,
DefaultWGListenPort: 51821,
} as const;
@@ -216,6 +216,7 @@ export default function buildHostIptablesScripts({
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} -j ACCEPT`,
);
} else {
@@ -20,7 +20,7 @@ export default function AddClientFormAllowedIps({
allowed_ips: e.target.value,
}));
}}
value={form.allowed_ips}
defaultValue={form.allowed_ips}
showLabel
/>
)}
@@ -0,0 +1,45 @@
import type { BUN_SQLITE_WGUI_HOSTS } from "@/db/types/db";
import fetchApi from "@/src/components/twui/utils/fetch/fetchApi";
import type useFormInit from "@/src/hooks/use-form-init";
import type { ApiReqParams } from "@/src/types";
import type { APIResponseObject } from "@moduletrace/bunext/types";
import type { Dispatch, SetStateAction } from "react";
type Params = {
iface: string;
local: boolean;
setLoading: Dispatch<SetStateAction<boolean>>;
setForm: Dispatch<SetStateAction<BUN_SQLITE_WGUI_HOSTS>>;
};
export default async function clientFetchIP({
iface,
local,
setLoading,
setForm,
}: Params) {
if (!iface) return;
const endpoint = local
? `/api/admin/interface-local-ip?interface=${iface}`
: `/api/admin/public-ip?interface=${iface}`;
setLoading(true);
fetchApi<ApiReqParams, APIResponseObject>(endpoint, {
method: "GET",
})
.then((res) => {
if (res.success && res.stringRes) {
setForm((prev) => ({
...prev,
public_ip_address: res.stringRes!,
}));
}
})
.finally(() => {
setTimeout(() => {
setLoading(false);
}, 1000);
});
}
@@ -13,7 +13,9 @@ export default async function submitAddHostForm({
existing_full,
}: ReturnType<typeof useFormInit<BUN_SQLITE_WGUI_HOSTS>>) {
try {
const confirm_msg = existing_full?.id
const is_updating_host = typeof existing_full?.id == "number";
const confirm_msg = is_updating_host
? `Update this host?`
: `Create this new host?`;
@@ -24,12 +26,10 @@ export default async function submitAddHostForm({
setLoading(true);
const res = await fetchApi<ApiReqParams, APIResponseObject>(
existing_full?.id
? `/api/admin/update-host`
: `/api/admin/add-host`,
is_updating_host ? `/api/admin/update-host` : `/api/admin/add-host`,
{
method: "POST",
body: existing_full?.id
body: is_updating_host
? {
host_id: existing_full.id,
update_data: form,
@@ -49,10 +49,7 @@ export default async function submitAddHostForm({
},
);
const host_id =
typeof existing_full?.id == "number"
? existing_full.id
: res.numberRes;
const host_id = is_updating_host ? existing_full.id : res.numberRes;
if (res.success) {
clearLocalForm();
@@ -16,13 +16,15 @@ export default function AddHostFormAction({
return null;
}
const is_updating_host = typeof existing_full?.id == "number";
return (
<Button
title="Create Host"
type="submit"
disabled={existing_full?.id ? false : ipStatus !== "available"}
disabled={is_updating_host ? false : ipStatus !== "available"}
>
{existing_full?.id ? "Update Host" : "Create Host"}
{is_updating_host ? "Update Host" : "Create Host"}
</Button>
);
}
@@ -17,7 +17,7 @@ export default function AddHostFormInterface({
if (existing_full?.interface) {
return (
<Input
value={existing_full.interface || "N/A"}
defaultValue={existing_full.interface || "N/A"}
title="Network Interface"
readOnly
showLabel
@@ -22,7 +22,7 @@ export default function AddHostFormListenPort({
if (existing_full?.listen_port) {
return (
<Input
value={existing_full.listen_port || "N/A"}
defaultValue={existing_full.listen_port || "N/A"}
title="Listen Port"
readOnly
showLabel
@@ -57,7 +57,7 @@ export default function AddHostFormListenPort({
label="Listen Port"
showLabel
placeholder={String(AppData["DefaultWGListenPort"])}
value={
defaultValue={
form.listen_port != null ? String(form.listen_port) : ""
}
numberText
@@ -10,6 +10,9 @@ import Checkbox from "@/src/components/twui/form/Checkbox";
import { twMerge } from "tailwind-merge";
import useStatus from "@/src/components/twui/hooks/useStatus";
import LoadingOverlay from "@/src/components/twui/elements/LoadingOverlay";
import LoadingRectangleBlock from "@/src/components/twui/layout/LoadingRectangleBlock";
import clientFetchIP from "../../(functions)/fetch-ip";
import isLocalIPAddress from "../../../../../../utils/is-local-ip-address";
type Props = ReturnType<typeof useFormInit<BUN_SQLITE_WGUI_HOSTS>>;
@@ -19,64 +22,55 @@ export default function AddHostFormPublicIP({
app_context,
existing_full,
}: Props) {
const [useLocalIP, setUseLocalIP] = useState(false);
const is_existing_local_ip = isLocalIPAddress(
existing_full?.public_ip_address,
)
? true
: false;
const [useLocalIP, setUseLocalIP] = useState(is_existing_local_ip);
const { loading, setLoading } = useStatus({
initialLoading: existing_full?.id ? false : true,
initialLoading: true,
});
function fetchIP(iface: string, local: boolean) {
if (!iface) return;
const endpoint = local
? `/api/admin/interface-local-ip?interface=${iface}`
: `/api/admin/public-ip?interface=${iface}`;
setLoading(true);
fetchApi<ApiReqParams, APIResponseObject>(endpoint, {
method: "GET",
})
.then((res) => {
if (res.success && res.stringRes) {
setForm((prev) => ({
...prev,
public_ip_address: res.stringRes!,
}));
}
})
.finally(() => {
setTimeout(() => {
setLoading(false);
}, 1000);
});
}
useEffect(() => {
if (!form.interface) return;
fetchIP(form.interface, useLocalIP);
if (!form.interface) {
setLoading(false);
return;
}
clientFetchIP({
iface: form.interface,
local: useLocalIP,
setForm,
setLoading,
});
}, [form.interface, useLocalIP]);
if (existing_full?.public_ip_address) {
return (
<Input
value={existing_full.public_ip_address || "N/A"}
title="IP Address"
readOnly
showLabel
/>
);
}
// if (existing_full?.public_ip_address) {
// return (
// <Input
// defaultValue={existing_full.public_ip_address || "N/A"}
// title="IP Address"
// readOnly
// showLabel
// />
// );
// }
return (
<Stack className={twMerge("w-full gap-2 relative")}>
{loading ? <LoadingOverlay /> : null}
{loading ? (
<LoadingRectangleBlock className="h-[70px]" />
) : (
<>
<Input
name="public_ip_address"
label="IP Address"
showLabel
placeholder="e.g. 203.0.113.10 or 192.168.1.10"
value={form.public_ip_address || ""}
defaultValue={form.public_ip_address || ""}
changeHandler={(v) => {
setForm((prev) => ({
...prev,
@@ -89,12 +83,17 @@ export default function AddHostFormPublicIP({
setUseLocalIP(checked);
}}
label={
<span className="text-base opacity-80">Use Local IP?</span>
<span className="text-base opacity-80">
Use Local IP?
</span>
}
defaultChecked={
useLocalIP || Boolean(app_context.pageProps?.is_local_ip)
useLocalIP ||
isLocalIPAddress(form.public_ip_address)
}
/>
</>
)}
</Stack>
);
}
@@ -19,7 +19,7 @@ export default function AddHostFormWgIpAddress({
return (
<Input
placeholder="WG IP address"
value={props.existing_full.wg_ip_address}
defaultValue={props.existing_full.wg_ip_address}
readOnly
showLabel
/>
@@ -87,7 +87,7 @@ export default function ChangePasswordSection() {
onChange={(e) => {
setNewPassword(e.target.value);
}}
value={new_password}
defaultValue={new_password}
/>
<Input
type="password"
@@ -97,7 +97,7 @@ export default function ChangePasswordSection() {
onChange={(e) => {
setConfirmPassword(e.target.value);
}}
value={confirm_password}
defaultValue={confirm_password}
/>
{status?.error && status.msg ? (
@@ -78,7 +78,7 @@ export default function SetupUpdateWgUiAction({ setup }: Props) {
<Input<"repo_url">
label="Repository URL"
placeholder={SiteData["RepoURL"]}
value={repoUrl}
defaultValue={repoUrl}
onChange={(e) => {
setRepoUrl(e.target.value);
}}
@@ -88,7 +88,7 @@ export default function SetupUpdateWgUiAction({ setup }: Props) {
<Input<"branch">
label="Branch"
placeholder="main"
value={branch}
defaultValue={branch}
onChange={(e) => {
setBranch(e.target.value);
}}
-1
View File
@@ -1,7 +1,6 @@
import type { BUN_SQLITE_WGUI_HOSTS } from "@/db/types/db";
import checkUserAccess from "@/src/functions/backend/auth/check-user-access";
import userAuth from "@/src/functions/backend/auth/user-auth";
import createWireguardHost from "@/src/functions/backend/setup/create-wireguard-host";
import setupWireguardHost from "@/src/functions/backend/setup/setup-wireguard-host";
import type { ApiReqParams, TableType } from "@/src/types";
import BunSQLite from "@moduletrace/bun-sqlite";
+3
View File
@@ -0,0 +1,3 @@
export default function isLocalIPAddress(ip: string | undefined) {
return Boolean(ip?.match(/^(192|10)\./));
}