From bc9e83e41f9d42e1f8717b13f5b632fa34429cf1 Mon Sep 17 00:00:00 2001 From: Sunil Mohan Adapa Date: Fri, 6 Sep 2024 18:26:29 -0700 Subject: [PATCH] bind: Fix port number clash with 'shared' network connections Closes: #707 Helps: #1570 - Network Manager's 'shared' connections use port 53 on those interfaces. Bind by default also listens on them if possible. In some corner cases, this could lead to a clash. This patch fixes to cases by making sure bind does not listen on IP address likely used by Network Manager's 'shared' connections. If user custom configures address, they will need to update the bind configuration accordingly. - App version increment is not necessary because in this release cycle we have already incremented it once. Tests: - Install without patch. Increment the app version number (and the version number in the privileged script). Notice that bind app setup is run again. 'listen-on' line is inserted into the configuration file as expected. - Increment the version numbers again and a second 'listen-on' line is not inserted. - Without patch, on a machine with two network interfaces, start a 'shared' network connection. Start bind. Notice the error that bind could not listen on the shared network IP address. - Without patch, on a machine with two network interface, start bind while 'shared' network connection is configured with just the IP address. Start bind and it will listening on the IP address with shared network IP address. Configure a shared connection and it fails to start. - Apply the patch. Start 'shared' network connection. Start bind and notice that bind does not attempt to listen on that shared network IP address and does not print error message as well. - Apply the patch. Start bind while 'shared' network connection is configured with just the IP address. Bind does not attempt to listen on that shared network IP address. Start the shared network connection. It start without issues. Signed-off-by: Sunil Mohan Adapa Reviewed-by: James Valleroy --- plinth/modules/bind/privileged.py | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/plinth/modules/bind/privileged.py b/plinth/modules/bind/privileged.py index 9276b9443..3c94f4e96 100644 --- a/plinth/modules/bind/privileged.py +++ b/plinth/modules/bind/privileged.py @@ -1,6 +1,7 @@ # SPDX-License-Identifier: AGPL-3.0-or-later """Configuration helper for BIND server.""" +import pathlib import re from collections import defaultdict from pathlib import Path @@ -18,6 +19,7 @@ acl goodclients { localnets; }; options { +listen-on { !10.42.0.1; !10.42.1.1; !10.42.2.1; !10.42.3.1; !10.42.4.1; !10.42.5.1; !10.42.6.1; !10.42.7.1; any; }; directory "/var/cache/bind"; recursion yes; @@ -31,8 +33,10 @@ forward first; auth-nxdomain no; # conform to RFC1035 listen-on-v6 { any; }; }; -''' +''' # noqa: E501 DEFAULT_FORWARDER = '127.0.0.53' # systemd-resolved +LISTEN_ON = 'listen-on { !10.42.0.1; !10.42.1.1; !10.42.2.1; !10.42.3.1; '\ + '!10.42.4.1; !10.42.5.1; !10.42.6.1; !10.42.7.1; any; };' @privileged @@ -45,6 +49,9 @@ def setup(old_version: int): if not get_config()['forwarders']: _set_forwarders(DEFAULT_FORWARDER) + if not _has_listen_on(): + _insert_listen_on() + if old_version < 3: _remove_dnssec() @@ -106,6 +113,26 @@ def _remove_dnssec(): file_handle.write(line + '\n') +def _has_listen_on(): + """Return whether listen-on config option is present.""" + lines = pathlib.Path(CONFIG_FILE).read_text().splitlines() + regex = r'^\s*listen-on\s+{' + return any((re.match(regex, line) for line in lines)) + + +def _insert_listen_on(): + """Insert the listen-on option.""" + config_file = pathlib.Path(CONFIG_FILE) + lines = config_file.read_text().splitlines(keepends=True) + write_lines = [] + for line in lines: + write_lines += line + if re.match(r'^\s*options\s+{', line): + write_lines += LISTEN_ON + '\n' + + config_file.write_text(''.join(write_lines)) + + def get_served_domains(): """Return list of domains service handles.