From 908039464a80e7b60e1f5f3ea331e133bd734fef Mon Sep 17 00:00:00 2001 From: Roberto Matias Date: Wed, 26 Mar 2025 15:45:19 +0100 Subject: [PATCH] feat: add local DNS override toggle component and action Implements a user interface toggle component to control the override_local_dns setting in Headscale. This allows administrators to force clients to use the configured DNS servers instead of their local DNS configuration. - Added ToggleOverrideLocalDns component - Added corresponding action handler in dns-actions.ts - Added section to the DNS overview panel - Updated interface to reflect config changes immediately Fixes #125 --- .../components/toggle-override-local-dns.tsx | 36 +++++++++++++++++++ app/routes/dns/dns-actions.ts | 18 ++++++++++ app/routes/dns/overview.tsx | 13 +++++++ test/config.yaml | 2 ++ 4 files changed, 69 insertions(+) create mode 100644 app/routes/dns/components/toggle-override-local-dns.tsx diff --git a/app/routes/dns/components/toggle-override-local-dns.tsx b/app/routes/dns/components/toggle-override-local-dns.tsx new file mode 100644 index 0000000..f8a38fb --- /dev/null +++ b/app/routes/dns/components/toggle-override-local-dns.tsx @@ -0,0 +1,36 @@ +import Dialog from '~/components/Dialog'; + +interface Props { + isEnabled: boolean; + isDisabled: boolean; +} + +export default function Modal({ isEnabled, isDisabled }: Props) { + return ( + + + {isEnabled ? 'Disable' : 'Enable'} Local DNS Override + + + + {isEnabled ? 'Disable' : 'Enable'} Local DNS Override + + + {isEnabled + ? 'Devices will no longer have their local DNS settings overridden by Headscale.' + : 'Headscale will override local DNS settings on connected devices, forcing them to use the server\'s DNS configuration.' + } + + + + + + ); +} \ No newline at end of file diff --git a/app/routes/dns/dns-actions.ts b/app/routes/dns/dns-actions.ts index a0e658f..512c383 100644 --- a/app/routes/dns/dns-actions.ts +++ b/app/routes/dns/dns-actions.ts @@ -33,6 +33,8 @@ export async function dnsAction({ return removeRecord(formData, context); case 'add_record': return addRecord(formData, context); + case 'toggle_override_local_dns': + return toggleOverrideLocalDns(formData, context); default: return data({ success: false }, 400); } @@ -221,3 +223,19 @@ async function addRecord(formData: FormData, context: LoadContext) { await hp_getIntegration()?.onConfigChange(); } + +async function toggleOverrideLocalDns(formData: FormData, context: LoadContext) { + const newState = formData.get('new_state')?.toString(); + if (!newState) { + return data({ success: false }, 400); + } + + await context.hs.patch([ + { + path: 'dns.override_local_dns', + value: newState === 'enabled', + }, + ]); + + await hp_getIntegration()?.onConfigChange(); +} \ No newline at end of file diff --git a/app/routes/dns/overview.tsx b/app/routes/dns/overview.tsx index ef382bb..58a76b0 100644 --- a/app/routes/dns/overview.tsx +++ b/app/routes/dns/overview.tsx @@ -9,6 +9,7 @@ import ManageRecords from './components/manage-records'; import RenameTailnet from './components/rename-tailnet'; import ToggleMagic from './components/toggle-magic'; import { dnsAction } from './dns-actions'; +import ToggleOverrideLocalDns from './components/toggle-override-local-dns'; // We do not want to expose every config value export async function loader({ context }: LoaderFunctionArgs) { @@ -25,6 +26,7 @@ export async function loader({ context }: LoaderFunctionArgs) { splitDns: config.dns.nameservers.split, searchDomains: config.dns.search_domains, extraRecords: config.dns.extra_records, + overrideLocalDns: config.dns.override_local_dns, }; return { @@ -59,6 +61,17 @@ export default function Page() { +
+

Local DNS Override

+

+ When enabled, Headscale will override the local DNS configuration + of connected clients, forcing them to use the configured DNS servers. +

+ +