From b33d6531ce609ae3d822397fb48d5f83f0861b1b Mon Sep 17 00:00:00 2001 From: Johnathan Corgan Date: Tue, 10 Mar 2026 19:19:24 +0000 Subject: [PATCH] Fix fips-dns.service pulling in systemd-resolved and hanging on missing fips0 The fips-dns.service unit had three issues: 1. Wants=systemd-resolved.service caused systemd to start systemd-resolved on systems that weren't using it, breaking existing DNS by rewriting /etc/resolv.conf to the stub resolver at 127.0.0.53. 2. The ExecStart busy-wait loop for fips0 had no timeout, hanging forever if fips.service failed to create the TUN device. 3. Installers unconditionally enabled fips-dns.service regardless of whether systemd-resolved was present. Fix by replacing Wants= with ConditionPathExists=/run/systemd/resolve (skips cleanly if resolved isn't running), adding Requires=fips.service (won't start without the daemon), bounding the fips0 wait loop to 30 seconds, and making the installers conditional on systemd-resolved being active. --- packaging/debian/fips-dns.service | 17 ++++++++++++++--- packaging/debian/postinst | 8 ++++++-- packaging/systemd/README.install.md | 17 ++++++++++++----- packaging/systemd/fips-dns.service | 17 ++++++++++++++--- packaging/systemd/install.sh | 10 ++++++++-- 5 files changed, 54 insertions(+), 15 deletions(-) diff --git a/packaging/debian/fips-dns.service b/packaging/debian/fips-dns.service index 459e810..b8e161b 100644 --- a/packaging/debian/fips-dns.service +++ b/packaging/debian/fips-dns.service @@ -1,11 +1,22 @@ [Unit] Description=Configure DNS routing for .fips domain -After=systemd-resolved.service -Wants=systemd-resolved.service +After=fips.service systemd-resolved.service +Requires=fips.service +ConditionPathExists=/run/systemd/resolve [Service] Type=oneshot -ExecStart=/usr/bin/bash -c 'while ! ip link show fips0 >/dev/null 2>&1; do sleep 1; done; /usr/bin/resolvectl dns fips0 127.0.0.1:5354; /usr/bin/resolvectl domain fips0 ~fips' +ExecStart=/usr/bin/bash -c '\ + for i in $(seq 1 30); do \ + ip link show fips0 >/dev/null 2>&1 && break; \ + sleep 1; \ + done; \ + if ! ip link show fips0 >/dev/null 2>&1; then \ + echo "fips0 interface not found after 30s" >&2; \ + exit 1; \ + fi; \ + /usr/bin/resolvectl dns fips0 127.0.0.1:5354; \ + /usr/bin/resolvectl domain fips0 ~fips' RemainAfterExit=yes [Install] diff --git a/packaging/debian/postinst b/packaging/debian/postinst index c7e971d..67a9001 100755 --- a/packaging/debian/postinst +++ b/packaging/debian/postinst @@ -18,12 +18,16 @@ case "$1" in if [ -d /run/systemd/system ]; then systemctl daemon-reload systemctl enable fips.service 2>/dev/null || true - systemctl enable fips-dns.service 2>/dev/null || true + if systemctl is-active --quiet systemd-resolved.service 2>/dev/null; then + systemctl enable fips-dns.service 2>/dev/null || true + fi # On upgrade, restart services that were running before if [ -n "$2" ]; then systemctl start fips.service 2>/dev/null || true - systemctl start fips-dns.service 2>/dev/null || true + if systemctl is-enabled --quiet fips-dns.service 2>/dev/null; then + systemctl start fips-dns.service 2>/dev/null || true + fi fi fi ;; diff --git a/packaging/systemd/README.install.md b/packaging/systemd/README.install.md index e8cb132..37c0a40 100644 --- a/packaging/systemd/README.install.md +++ b/packaging/systemd/README.install.md @@ -76,19 +76,26 @@ peers: connect_policy: auto_connect ``` -### 4. DNS Resolver +### 4. DNS Resolver (optional, requires systemd-resolved) FIPS includes a DNS responder for `.fips` domain names (port 5354). -To integrate with systemd-resolved: +On systems running `systemd-resolved`, the installer automatically enables +`fips-dns.service` to route `.fips` queries to the FIPS resolver. + +If `systemd-resolved` is not running at install time, DNS integration is +skipped. To enable it later (after starting `systemd-resolved`): + +```bash +sudo systemctl enable --now fips-dns.service +``` + +For manual configuration without `fips-dns.service`: ```bash sudo resolvectl dns fips0 127.0.0.1:5354 sudo resolvectl domain fips0 ~fips ``` -To make this persistent, create a systemd-networkd override or add a -drop-in for the fips0 interface. - ## Firewall Ports | Port | Protocol | Purpose | diff --git a/packaging/systemd/fips-dns.service b/packaging/systemd/fips-dns.service index 459e810..b8e161b 100644 --- a/packaging/systemd/fips-dns.service +++ b/packaging/systemd/fips-dns.service @@ -1,11 +1,22 @@ [Unit] Description=Configure DNS routing for .fips domain -After=systemd-resolved.service -Wants=systemd-resolved.service +After=fips.service systemd-resolved.service +Requires=fips.service +ConditionPathExists=/run/systemd/resolve [Service] Type=oneshot -ExecStart=/usr/bin/bash -c 'while ! ip link show fips0 >/dev/null 2>&1; do sleep 1; done; /usr/bin/resolvectl dns fips0 127.0.0.1:5354; /usr/bin/resolvectl domain fips0 ~fips' +ExecStart=/usr/bin/bash -c '\ + for i in $(seq 1 30); do \ + ip link show fips0 >/dev/null 2>&1 && break; \ + sleep 1; \ + done; \ + if ! ip link show fips0 >/dev/null 2>&1; then \ + echo "fips0 interface not found after 30s" >&2; \ + exit 1; \ + fi; \ + /usr/bin/resolvectl dns fips0 127.0.0.1:5354; \ + /usr/bin/resolvectl domain fips0 ~fips' RemainAfterExit=yes [Install] diff --git a/packaging/systemd/install.sh b/packaging/systemd/install.sh index e77891d..1e1c10c 100755 --- a/packaging/systemd/install.sh +++ b/packaging/systemd/install.sh @@ -116,8 +116,14 @@ echo "tmpfiles.d entry created for /run/fips/ ownership." # --- Enable service --- systemctl enable fips.service -systemctl enable fips-dns.service -echo "Services enabled (will start on boot)." +if systemctl is-active --quiet systemd-resolved.service 2>/dev/null; then + systemctl enable fips-dns.service + echo "Services enabled (will start on boot)." +else + echo "fips.service enabled (will start on boot)." + echo " Note: fips-dns.service not enabled (systemd-resolved is not running)." + echo " To enable .fips DNS later: sudo systemctl enable --now fips-dns.service" +fi # Restart if they were running before if $was_active; then