Fedora 33 is planning to enable systemd-resolved by default. The change is described in detail in https://fedoraproject.org/wiki/Changes/systemd-resolved
FreeIPA needs to be ready for systemd-resolved operation by Fedora 33. FreeIPA does modification of resolv.conf when installed with DNS and it also expects to fix resolv.conf on the test systems in own integration tests. Since resolv.conf would become a symlink some of the expectations might not be true anymore.
We need to find out what actual tasks need to be done to preserve current FreeIPA behavior with regards to DNS and DNSSEC operations.
Metadata Update from @abbra: - Issue set to the milestone: FreeIPA 4.8.7
It might be sufficient to drop in a config file and reload systemd-resolved
# /etc/systemd/resolved.conf.d/ipa.conf [Resolve] DNS=127.0.0.1 Domains=~.
It might also be advisable to configure dnssec trust anchors and add our DNSSEC KSK.
Metadata Update from @cheimes: - Issue set to the milestone: None (was: FreeIPA 4.8.7)
Metadata Update from @cheimes: - Issue priority set to: important - Issue set to the milestone: FreeIPA 4.8.7
Rawhide doesn't use systemd resolved yet. We have to wait until the new feature is implemented.
See #8375 for a related issue
Metadata Update from @abbra: - Custom field rhbz adjusted to https://bugzilla.redhat.com/show_bug.cgi?id=1880628
Fedora 33 now uses systemd resolved and we've got bug https://bugzilla.redhat.com/show_bug.cgi?id=1880628 as accepted exception to fix the behavior.
Metadata Update from @abbra: - Issue set to the milestone: FreeIPA 4.8
--auto-forwarders is not compatible with systemd-resolved yet. Internally the flag uses dnspython to get a list of name servers with dns.resolver.get_default_resolver().nameservers / get_ipa_resolver() since #8383. On Fedora 33 this returns the stub resolver ['127.0.0.53']. FreeIPA either needs to parse the output of resolvectl dns (ugly) or use D-Bus to query the DNS resolver information for global scope and all link scopes.
--auto-forwarders
dns.resolver.get_default_resolver().nameservers
get_ipa_resolver()
resolvectl dns
/etc/resolv.conf
import os from ipaplatform.paths import paths def detect_resolve1_resolv_conf(): """Detect if /etc/resolv.conf is managed by systemd-resolved See man(5) NetworkManager.conf """ systemd_resolv_conf = { "/run/systemd/resolve/stub-resolv.conf", "/run/systemd/resolve/resolv.conf", "/lib/systemd/resolv.conf", "/usr/lib/systemd/resolv.conf", } try: dest = os.readlink(paths.RESOLV_CONF) except OSError: # not a link return False # convert path relative to /etc/resolv.conf to abs path dest = os.path.normpath( os.path.join(os.path.dirname(paths.RESOLV_CONF), dest) ) return dest in systemd_resolv_conf
import socket import dbus DBUS_RESOLVE1_NAME = "org.freedesktop.resolve1" DBUS_RESOLVE1_PATH = "/org/freedesktop/resolve1" DBUS_RESOLVE1_MANAGER_IF = 'org.freedesktop.resolve1.Manager' DBUS_PROPERTY_IF = 'org.freedesktop.DBus.Properties' # netlink interface index for resolve1 global settings and loopback IFINDEX_GLOBAL = 0 IFINDEX_LOOPBACK = 1 def get_resolve1_nameservers(): """Get list of DNS forwarders from systemd-resolved :return: list of tuples (ifindex, ipaddress) """ bus = dbus.SystemBus() try: resolve1 = bus.get_object(DBUS_RESOLVE1_NAME, DBUS_RESOLVE1_PATH) prop_if = dbus.Interface(resolve1, DBUS_PROPERTY_IF) dns_prop = prop_if.Get(DBUS_RESOLVE1_MANAGER_IF, "DNSEx") finally: bus.close() results = [] for ifindex, af, dns_arr, port, sniname in dns_prop: if af not in {socket.AF_INET, socket.AF_INET6}: # neither IPv4 nor IPv6 continue if port not in {0, 53} or sniname: # non-default port, non-standard port, or SNI name configuration # for DNS over TLS, e.g. 1.2.3.4:9953#example.com continue # netlink interface index, see socket.if_nameindex() ifindex = int(ifindex) dnsip = socket.inet_ntop(af, bytes(dns_arr)) results.append((ifindex, dnsip)) return results
```
Using socket.if_indextoname() you can get back the interface name:
socket.if_indextoname()
.... results.append((ifindex, socket.if_indextoname(ifindex), dnsip))
Metadata Update from @cheimes: - Custom field on_review adjusted to https://github.com/freeipa/freeipa/pull/5125 - Issue assigned to cheimes - Issue priority set to: critical (was: important)
master:
ipa-4-8:
Metadata Update from @abbra: - Custom field changelog adjusted to FreeIPA DNS servers now detect systemd-resolved and configure it to pass through itself.
Upgrade does not yet work well, I filed a separate issue https://pagure.io/freeipa/issue/8518 for this problem
Metadata Update from @cheimes: - Issue close_status updated to: fixed - Issue status updated to: Closed (was: Open)
I found a potential issue with my code. If the server has multiple NICs with multiple IP addresses than the new code might add "127.0.0.1" and "::1" to /etc/resolv.conf multiple times.
The get_server_ip_address(host, True, False, []) should be equivalent to resolve_ip_addresses_nss(host).
get_server_ip_address(host, True, False, [])
resolve_ip_addresses_nss(host)
$ git diff diff --git a/ipaserver/install/bindinstance.py b/ipaserver/install/bindinstance.py index aae2fe603..3b446ce76 100644 --- a/ipaserver/install/bindinstance.py +++ b/ipaserver/install/bindinstance.py @@ -1121,18 +1121,18 @@ class BindInstance(service.Service): def setup_resolv_conf(self): searchdomains = [self.domain] - nameservers = [] + nameservers = set() resolve1_enabled = dnsforwarders.detect_resolve1_resolv_conf() for ip_address in self.ip_addresses: if ip_address.version == 4: - nameservers.append("127.0.0.1") + nameservers.add("127.0.0.1") elif ip_address.version == 6: - nameservers.append("::1") + nameservers.add("::1") try: tasks.configure_dns_resolver( - nameservers, searchdomains, + sorted(nameservers), searchdomains, resolve1_enabled=resolve1_enabled, fstore=self.fstore ) except IOError as e: diff --git a/ipaserver/install/server/upgrade.py b/ipaserver/install/server/upgrade.py index d1d8b3a64..ef58fd24c 100644 --- a/ipaserver/install/server/upgrade.py +++ b/ipaserver/install/server/upgrade.py @@ -1437,8 +1437,9 @@ def upgrade_bind(fstore): # resolve1's stub resolver config file. has_resolved_ipa_conf = os.path.isfile(paths.SYSTEMD_RESOLVED_IPA_CONF) if not has_resolved_ipa_conf and detect_resolve1_resolv_conf(): - ip_addresses = installutils.get_server_ip_address( - api.env.host, True, False, []) + ip_addresses = installutils.resolve_ip_addresses_nss( + api.env.host + ) bind.ip_addresses = ip_addresses bind.setup_resolv_conf() logger.info("Updated systemd-resolved configuration")
Metadata Update from @cheimes: - Issue status updated to: Open (was: Closed)
Login to comment on this ticket.