From 86a1f947d16a4f6723f97caaeb5b2da633f056d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=CE=93=CE=B9=CF=8E=CF=81=CE=B3=CE=BF=CF=82=20=CE=A4=CF=81?= =?UTF-8?q?=CE=B9=CE=B3=CF=89=CE=BD=CE=AC=CE=BA=CE=B7=CF=82?= Date: Thu, 5 Feb 2026 12:03:38 +0200 Subject: [PATCH] Added ability to manage wildcard dns entries --- dns/forms.py | 11 +++++++---- dns/functions.py | 7 ++++++- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/dns/forms.py b/dns/forms.py index 3422c37..37a4309 100644 --- a/dns/forms.py +++ b/dns/forms.py @@ -63,6 +63,7 @@ class StaticHostForm(forms.ModelForm): self.helper = FormHelper() self.helper.form_method = 'post' self.fields['hostname'].label = _('Hostname') + self.fields['hostname'].help_text = _('Hostname or wildcard domain (e.g. *.example.com)') self.fields['ip_address'].label = _('IP Address') back_label = _('Back') delete_label = _('Delete') @@ -90,10 +91,12 @@ class StaticHostForm(forms.ModelForm): cleaned_data = super().clean() hostname = cleaned_data.get('hostname') if hostname: - regex = r'^[a-zA-Z][a-zA-Z0-9-\.]*[a-zA-Z0-9]$' - if not re.match(regex, hostname): - raise ValidationError('Invalid hostname') - return + # Allow plain hostname (e.g. example.com) or wildcard (e.g. *.example.com) + plain_regex = r'^[a-zA-Z0-9]([a-zA-Z0-9-\.]*[a-zA-Z0-9])?$' + wildcard_regex = r'^\*\.([a-zA-Z0-9]([a-zA-Z0-9-\.]*[a-zA-Z0-9])?)$' + if not (re.match(plain_regex, hostname) or re.match(wildcard_regex, hostname)): + raise ValidationError(_('Invalid hostname. Use a hostname (e.g. example.com) or wildcard (e.g. *.example.com).')) + return cleaned_data class DNSFilterListForm(forms.ModelForm): diff --git a/dns/functions.py b/dns/functions.py index 542c391..1f8281e 100644 --- a/dns/functions.py +++ b/dns/functions.py @@ -124,7 +124,12 @@ bind-interfaces if static_hosts: dnsmasq_config += '\n' for static_host in static_hosts: - dnsmasq_config += f'address=/{static_host.hostname}/{static_host.ip_address}\n' + # dnsmasq uses /.example.com/ for wildcards (matches *.example.com and example.com) + if static_host.hostname.startswith('*.'): + dnsmasq_domain = '.' + static_host.hostname[2:] + else: + dnsmasq_domain = static_host.hostname + dnsmasq_config += f'address=/{dnsmasq_domain}/{static_host.ip_address}\n' if dns_lists: dnsmasq_config += '\n'