diff --git a/plinth/modules/names/forms.py b/plinth/modules/names/forms.py new file mode 100644 index 000000000..186b611f9 --- /dev/null +++ b/plinth/modules/names/forms.py @@ -0,0 +1,39 @@ +# SPDX-License-Identifier: AGPL-3.0-or-later +"""Forms for the names app.""" + +from django import forms +from django.utils.translation import gettext_lazy as _ + +from plinth.utils import format_lazy + + +class NamesConfigurationForm(forms.Form): + """Form to configure names app.""" + + dns_over_tls = forms.ChoiceField( + label=_('Use DNS-over-TLS for resolving domains (global preference)'), + widget=forms.RadioSelect, choices=[ + ('yes', + format_lazy( + 'Yes. Encrypt connections to the DNS server.
This improves privacy as domain name ' + 'queries will not be made as plain text over the network. It ' + 'also improves security as responses from the server cannot ' + 'be manipulated. If the configured DNS servers do not ' + 'support DNS-over-TLS, all name resolutions will fail. If ' + 'your DNS provider (likely your ISP) does not support ' + 'DNS-over-TLS or blocks some domains, you can configure ' + 'well-known public DNS servers in individual network ' + 'connection settings.
', allow_markup=True)), + ('opportunistic', + format_lazy( + 'Opportunistic.Encrypt connections to ' + 'the DNS server if the server supports DNS-over-TLS. ' + 'Otherwise, use unencrypted connections. There is no ' + 'protection against response manipulation.
', + allow_markup=True)), + ('no', + format_lazy( + 'No.Do not encrypt domain name ' + 'resolutions.
', allow_markup=True)), + ], initial='no') diff --git a/plinth/modules/names/privileged.py b/plinth/modules/names/privileged.py index 37ec1deb1..8b1c464fd 100644 --- a/plinth/modules/names/privileged.py +++ b/plinth/modules/names/privileged.py @@ -3,26 +3,37 @@ import pathlib +import augeas + from plinth import action_utils from plinth.actions import privileged fallback_conf = pathlib.Path( '/etc/systemd/resolved.conf.d/freedombox-fallback.conf') +override_conf = pathlib.Path('/etc/systemd/resolved.conf.d/freedombox.conf') source_fallback_conf = pathlib.Path( '/usr/share/freedombox' '/etc/systemd/resolved.conf.d/freedombox-fallback.conf') @privileged -def set_resolved_configuration(dns_fallback: bool | None = None): +def set_resolved_configuration(dns_fallback: bool | None = None, + dns_over_tls: str | None = None): """Set systemd-resolved configuration options.""" if dns_fallback is not None: _set_enable_dns_fallback(dns_fallback) + if dns_over_tls is not None: + _set_resolved_configuration(dns_over_tls) + + action_utils.service_reload('systemd-resolved') + def get_resolved_configuration() -> dict[str, bool]: """Return systemd-resolved configuration.""" - return {'dns_fallback': fallback_conf.exists()} + configuration = _get_resolved_configuration() + configuration['dns_fallback'] = fallback_conf.exists() + return configuration def _set_enable_dns_fallback(dns_fallback: bool): @@ -34,4 +45,28 @@ def _set_enable_dns_fallback(dns_fallback: bool): else: fallback_conf.unlink(missing_ok=True) - action_utils.service_reload('systemd-resolved') + +def _load_augeas(): + """Initialize Augeas.""" + aug = augeas.Augeas(flags=augeas.Augeas.NO_LOAD + + augeas.Augeas.NO_MODL_AUTOLOAD) + aug.transform('Systemd', str(override_conf)) + aug.set('/augeas/context', '/files' + str(override_conf)) + aug.load() + return aug + + +def _get_resolved_configuration(): + """Return overridden configuration for systemd-resolved.""" + aug = _load_augeas() + return {'dns_over_tls': aug.get('Resolve/DNSOverTLS/value') or 'no'} + + +def _set_resolved_configuration(dns_over_tls: str | None = None): + """Write configuration into a systemd-resolved override file.""" + aug = _load_augeas() + + if dns_over_tls is not None: + aug.set('Resolve/DNSOverTLS/value', dns_over_tls) + + aug.save() diff --git a/plinth/modules/names/templates/names.html b/plinth/modules/names/templates/names.html index 2c6f1b409..2ba35f9a4 100644 --- a/plinth/modules/names/templates/names.html +++ b/plinth/modules/names/templates/names.html @@ -6,7 +6,10 @@ {% load bootstrap %} {% load i18n %} -{% block configuration %} +{% block status %} + {{ block.super }} + +