systemd: disable NSCD when DNSSEC validation is disabled in timesyncd
When a system has a wrong date and time timesyncd is unable to synchronize it because DNSSEC doesn't work. In order to break this chicken and egg problem systemd-timesync disables DNSSEC validation by setting SYSTEMD_NSS_RESOLVE_VALIDATE=0 in the unit file. However, it doesn't work in NixOS because it uses NSCD. This patch disables NSCD in systemd-timesyncd when SYSTEMD_NSS_RESOLVE_VALIDATE is set to 0 so that it uses NSS libraries directly. In order for it to be able to find the libnss_resolve.so.2 library this patch adds the systemd directory in the nix store to the LD_LIBRARY_PATH.
This commit is contained in:
parent
688991ba84
commit
6008246790
5 changed files with 116 additions and 0 deletions
|
@ -46,6 +46,13 @@ with lib;
|
||||||
wantedBy = [ "sysinit.target" ];
|
wantedBy = [ "sysinit.target" ];
|
||||||
aliases = [ "dbus-org.freedesktop.timesync1.service" ];
|
aliases = [ "dbus-org.freedesktop.timesync1.service" ];
|
||||||
restartTriggers = [ config.environment.etc."systemd/timesyncd.conf".source ];
|
restartTriggers = [ config.environment.etc."systemd/timesyncd.conf".source ];
|
||||||
|
# systemd-timesyncd disables DNSSEC validation in the nss-resolve module by setting SYSTEMD_NSS_RESOLVE_VALIDATE to 0 in the unit file.
|
||||||
|
# This is required in order to solve the chicken-and-egg problem when DNSSEC validation needs the correct time to work, but to set the
|
||||||
|
# correct time, we need to connect to an NTP server, which usually requires resolving its hostname.
|
||||||
|
# In order for nss-resolve to be able to read this environment variable we patch systemd-timesyncd to disable NSCD and use NSS modules directly.
|
||||||
|
# This means that systemd-timesyncd needs to have NSS modules path in LD_LIBRARY_PATH. When systemd-resolved is disabled we still need to set
|
||||||
|
# NSS module path so that systemd-timesyncd keeps using other NSS modules that are configured in the system.
|
||||||
|
environment.LD_LIBRARY_PATH = config.system.nssModules.path;
|
||||||
|
|
||||||
preStart = (
|
preStart = (
|
||||||
# Ensure that we have some stored time to prevent
|
# Ensure that we have some stored time to prevent
|
||||||
|
|
|
@ -847,6 +847,7 @@ in {
|
||||||
systemd-shutdown = handleTest ./systemd-shutdown.nix {};
|
systemd-shutdown = handleTest ./systemd-shutdown.nix {};
|
||||||
systemd-sysupdate = runTest ./systemd-sysupdate.nix;
|
systemd-sysupdate = runTest ./systemd-sysupdate.nix;
|
||||||
systemd-timesyncd = handleTest ./systemd-timesyncd.nix {};
|
systemd-timesyncd = handleTest ./systemd-timesyncd.nix {};
|
||||||
|
systemd-timesyncd-nscd-dnssec = handleTest ./systemd-timesyncd-nscd-dnssec.nix {};
|
||||||
systemd-user-tmpfiles-rules = handleTest ./systemd-user-tmpfiles-rules.nix {};
|
systemd-user-tmpfiles-rules = handleTest ./systemd-user-tmpfiles-rules.nix {};
|
||||||
systemd-misc = handleTest ./systemd-misc.nix {};
|
systemd-misc = handleTest ./systemd-misc.nix {};
|
||||||
systemd-userdbd = handleTest ./systemd-userdbd.nix {};
|
systemd-userdbd = handleTest ./systemd-userdbd.nix {};
|
||||||
|
|
61
nixos/tests/systemd-timesyncd-nscd-dnssec.nix
Normal file
61
nixos/tests/systemd-timesyncd-nscd-dnssec.nix
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
# This test verifies that systemd-timesyncd can resolve the NTP server hostname when DNSSEC validation
|
||||||
|
# fails even though it is enforced in the systemd-resolved settings. It is required in order to solve
|
||||||
|
# the chicken-and-egg problem when DNSSEC validation needs the correct time to work, but to set the
|
||||||
|
# correct time, we need to connect to an NTP server, which usually requires resolving its hostname.
|
||||||
|
#
|
||||||
|
# This test does the following:
|
||||||
|
# - Sets up a DNS server (tinydns) listening on the eth1 ip addess, serving .ntp and fake.ntp records.
|
||||||
|
# - Configures that DNS server as a resolver and enables DNSSEC in systemd-resolved settings.
|
||||||
|
# - Configures systemd-timesyncd to use fake.ntp hostname as an NTP server.
|
||||||
|
# - Performs a regular DNS lookup, to ensure it fails due to broken DNSSEC.
|
||||||
|
# - Waits until systemd-timesyncd resolves fake.ntp by checking its debug output.
|
||||||
|
# Here, we don't expect systemd-timesyncd to connect and synchronize time because there is no NTP
|
||||||
|
# server running. For this test to succeed, we only need to ensure that systemd-timesyncd
|
||||||
|
# resolves the IP address of the fake.ntp host.
|
||||||
|
|
||||||
|
import ./make-test-python.nix ({ pkgs, ... }:
|
||||||
|
|
||||||
|
let
|
||||||
|
ntpHostname = "fake.ntp";
|
||||||
|
ntpIP = "192.0.2.1";
|
||||||
|
in
|
||||||
|
{
|
||||||
|
name = "systemd-timesyncd";
|
||||||
|
nodes.machine = { pkgs, lib, config, ... }:
|
||||||
|
let
|
||||||
|
eth1IP = (lib.head config.networking.interfaces.eth1.ipv4.addresses).address;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
# Setup a local DNS server for the NTP domain on the eth1 IP address
|
||||||
|
services.tinydns = {
|
||||||
|
enable = true;
|
||||||
|
ip = eth1IP;
|
||||||
|
data = ''
|
||||||
|
.ntp:${eth1IP}
|
||||||
|
+.${ntpHostname}:${ntpIP}
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
# Enable systemd-resolved with DNSSEC and use the local DNS as a name server
|
||||||
|
services.resolved.enable = true;
|
||||||
|
services.resolved.dnssec = "true";
|
||||||
|
networking.nameservers = [ eth1IP ];
|
||||||
|
|
||||||
|
# Configure systemd-timesyncd to use our NTP hostname
|
||||||
|
services.timesyncd.enable = lib.mkForce true;
|
||||||
|
services.timesyncd.servers = [ ntpHostname ];
|
||||||
|
services.timesyncd.extraConfig = ''
|
||||||
|
FallbackNTP=${ntpHostname}
|
||||||
|
'';
|
||||||
|
|
||||||
|
# The debug output is necessary to determine whether systemd-timesyncd successfully resolves our NTP hostname or not
|
||||||
|
systemd.services.systemd-timesyncd.environment.SYSTEMD_LOG_LEVEL = "debug";
|
||||||
|
};
|
||||||
|
|
||||||
|
testScript = ''
|
||||||
|
machine.wait_for_unit("tinydns.service")
|
||||||
|
machine.wait_for_unit("systemd-timesyncd.service")
|
||||||
|
machine.fail("resolvectl query ${ntpHostname}")
|
||||||
|
machine.wait_until_succeeds("journalctl -u systemd-timesyncd.service --grep='Resolved address ${ntpIP}:123 for ${ntpHostname}'")
|
||||||
|
'';
|
||||||
|
})
|
|
@ -0,0 +1,46 @@
|
||||||
|
From 7a27556920fe1feefd17096841c8f3ca1294a1b3 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Yuri Nesterov <yuriy.nesterov@unikie.com>
|
||||||
|
Date: Wed, 21 Jun 2023 17:17:38 +0300
|
||||||
|
Subject: [PATCH] timesyncd: disable NSCD when DNSSEC validation is disabled
|
||||||
|
|
||||||
|
Systemd-timesyncd sets SYSTEMD_NSS_RESOLVE_VALIDATE=0 in the unit file
|
||||||
|
to disable DNSSEC validation but it doesn't work when NSCD is used in
|
||||||
|
the system. This patch disabes NSCD in systemd-timesyncd when
|
||||||
|
SYSTEMD_NSS_RESOLVE_VALIDATE is set to 0 so that it uses NSS libraries
|
||||||
|
directly.
|
||||||
|
---
|
||||||
|
src/timesync/timesyncd.c | 11 +++++++++++
|
||||||
|
1 file changed, 11 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/src/timesync/timesyncd.c b/src/timesync/timesyncd.c
|
||||||
|
index 1d8ebecc91..2b0ae361ff 100644
|
||||||
|
--- a/src/timesync/timesyncd.c
|
||||||
|
+++ b/src/timesync/timesyncd.c
|
||||||
|
@@ -21,6 +21,11 @@
|
||||||
|
#include "timesyncd-conf.h"
|
||||||
|
#include "timesyncd-manager.h"
|
||||||
|
#include "user-util.h"
|
||||||
|
+#include "env-util.h"
|
||||||
|
+
|
||||||
|
+struct traced_file;
|
||||||
|
+extern void __nss_disable_nscd(void (*)(size_t, struct traced_file *));
|
||||||
|
+static void register_traced_file(size_t dbidx, struct traced_file *finfo) {}
|
||||||
|
|
||||||
|
static int advance_tstamp(int fd, const struct stat *st) {
|
||||||
|
assert_se(fd >= 0);
|
||||||
|
@@ -198,6 +203,12 @@ static int run(int argc, char *argv[]) {
|
||||||
|
if (r < 0)
|
||||||
|
return log_error_errno(r, "Failed to parse fallback server strings: %m");
|
||||||
|
|
||||||
|
+ r = getenv_bool_secure("SYSTEMD_NSS_RESOLVE_VALIDATE");
|
||||||
|
+ if (r == 0) {
|
||||||
|
+ log_info("Disabling NSCD because DNSSEC validation is turned off");
|
||||||
|
+ __nss_disable_nscd(register_traced_file);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
log_debug("systemd-timesyncd running as pid " PID_FMT, getpid_cached());
|
||||||
|
|
||||||
|
notify_message = notify_start("READY=1\n"
|
||||||
|
--
|
||||||
|
2.34.1
|
||||||
|
|
|
@ -206,6 +206,7 @@ stdenv.mkDerivation (finalAttrs: {
|
||||||
./0017-core-don-t-taint-on-unmerged-usr.patch
|
./0017-core-don-t-taint-on-unmerged-usr.patch
|
||||||
./0018-tpm2_context_init-fix-driver-name-checking.patch
|
./0018-tpm2_context_init-fix-driver-name-checking.patch
|
||||||
./0019-systemctl-edit-suggest-systemdctl-edit-runtime-on-sy.patch
|
./0019-systemctl-edit-suggest-systemdctl-edit-runtime-on-sy.patch
|
||||||
|
./0020-timesyncd-disable-NSCD-when-DNSSEC-validation-is-dis.patch
|
||||||
] ++ lib.optional stdenv.hostPlatform.isMusl (
|
] ++ lib.optional stdenv.hostPlatform.isMusl (
|
||||||
let
|
let
|
||||||
oe-core = fetchzip {
|
oe-core = fetchzip {
|
||||||
|
|
Loading…
Reference in a new issue