164 lines
10 KiB
Markdown
164 lines
10 KiB
Markdown
# Debian 13: Systemresolver von systemd-resolved auf lokalen BIND9 umstellen
|
||
|
||
**Stand:** 27. Oktober 2026
|
||
**Beispielsystem:** `lists.mx` (produktiver Mail-/Listenserver, Debian 13)
|
||
**Skript:** `switch-resolver-to-bind9.sh`
|
||
|
||
## 1. Ziel und Hintergrund
|
||
|
||
Auf dem Host läuft bereits ein rekursiver BIND9 auf `127.0.0.1:53` und `[::1]:53`, einschließlich eigener DNSSEC-Validierung (`dnssec-validation auto;`). Bislang nutzten Programme `/etc/resolv.conf -> /run/systemd/resolve/stub-resolv.conf` und damit `127.0.0.53` (`systemd-resolved`), der wiederum an BIND9 weiterleitete.
|
||
|
||
Beobachtetes Problem: Die IPv6-PTR-Abfrage für `2607:f8b0:4864:20::72e` ergab über `127.0.0.53` `SERVFAIL` mit `DNSSEC validation failed: failed-auxiliary`, über `127.0.0.1` jedoch korrekt `mail-qk1-x72e.google.com.`. Mit `DNSSEC=no` in `systemd-resolved` funktionierte die PTR-Auflösung, aber Anfragen für die absichtlich DNSSEC-fehlerhafte Zone `www.dnssec-failed.org` liefen über `127.0.0.53` weiterhin in einen Timeout. Ein Loopback-Mitschnitt zeigte vielfach wiederholte Abfragen trotz `SERVFAIL`-Antworten von BIND9. Der DNS-Proxy auf `127.0.0.54` übergab dagegen `SERVFAIL` korrekt.
|
||
|
||
**Ziel:** BIND9 direkt über die glibc-/NSS-DNS-Auflösung nutzen; `systemd-resolved` nach erfolgreichem Test stoppen und deaktivieren. **Keine Änderung** an Maildiensten, BIND-Konfiguration, Interfaces, Firewall oder Routing.
|
||
|
||
## 2. Zielkonfiguration
|
||
|
||
`/etc/nsswitch.conf`:
|
||
|
||
```text
|
||
hosts: files myhostname dns
|
||
```
|
||
|
||
`/etc/resolv.conf` (reguläre Datei statt Symlink):
|
||
|
||
```text
|
||
# Local BIND9 recursive resolver; DNSSEC validated by BIND9.
|
||
nameserver 127.0.0.1
|
||
options edns0 trust-ad
|
||
search warenform.de
|
||
```
|
||
|
||
`search warenform.de` ist **systemspezifisch**. Das Skript übernimmt eine bereits vorhandene `search`-Zeile aus der bestehenden Konfiguration; es erfindet keine Suchdomäne. Bei `lists.mx` ist sie bereits gesetzt. `trust-ad` bedeutet **nicht**, dass glibc selbst DNSSEC prüft. Das validierende Glied ist BIND9. Programme mit eigenen Resolver-Bibliotheken können eine abweichende DNS-Konfiguration haben; dies ggf. anwendungsspezifisch prüfen.
|
||
|
||
Die lokale DNS-Auflösung setzt die Verfügbarkeit von BIND9 voraus. Mit nur `127.0.0.1` gibt es bewusst **keinen externen Fallback**, der lokale DNSSEC-Validierung umgehen könnte.
|
||
|
||
## 3. Voraussetzungen
|
||
|
||
- Debian 13, Root-Shell; BIND9 ist installiert, gestartet und lauscht auf IPv4-Loopback `127.0.0.1:53`.
|
||
- `dig`, `getent`, `systemctl`, die üblichen Coreutils sowie Bash sind verfügbar.
|
||
- BIND9 kann rekursiv auflösen und validiert DNSSEC unabhängig von `systemd-resolved`.
|
||
- Änderungen werden in einem Wartungsfenster bzw. mit vorhandener administrativer Konsole vorgenommen. Keine Netzwerkdienste oder Interfaces neu starten.
|
||
- Vorhandene dynamische DNS-Konfiguration (DHCP, VPN, Split-DNS, interne Domains) prüfen; das Skript bildet **keine** `systemd-resolved`-Link-Konfiguration nach.
|
||
- Eventuelle lokale Abhängigkeiten von `systemd-resolved`, `resolvectl`, LLMNR/mDNS und DNS-Stub-Adressen `127.0.0.53`/`127.0.0.54` vor dem Abschalten ausschließen.
|
||
|
||
**Achtung:** Auf `lists.mx` wurde `networking.service` zuvor als `failed` gemeldet. Das ist ein **separates** Thema und wird von diesem Skript ausdrücklich nicht behandelt. Insbesondere kein `systemctl restart networking` ausführen.
|
||
|
||
## 4. DNSSEC-Vorabprüfung
|
||
|
||
```bash
|
||
dig @127.0.0.1 cloudflare.com A +dnssec +adflag
|
||
dig @127.0.0.1 www.dnssec-failed.org A +time=5 +tries=1
|
||
dig @127.0.0.1 -x 2607:f8b0:4864:20::72e
|
||
```
|
||
|
||
Erwartung: `cloudflare.com` → `NOERROR` und Flag `ad`, `www.dnssec-failed.org` → `SERVFAIL` (nicht Timeout), PTR → `mail-qk1-x72e.google.com.` (Stand des beobachteten Beispiels; DNS-Daten können sich ändern). Das Skript führt einen Positiv- und Negativ-DNSSEC-Test zusätzlich selbst aus. Die Testdomain ist absichtlich fehlerhaft signiert.
|
||
|
||
## 5. Skriptinstallation und Verwendung
|
||
|
||
Datei an einen geeigneten Ort kopieren, beispielsweise:
|
||
|
||
```bash
|
||
install -o root -g root -m 0755 switch-resolver-to-bind9.sh \
|
||
/usr/local/sbin/switch-resolver-to-bind9.sh
|
||
|
||
bash -n /usr/local/sbin/switch-resolver-to-bind9.sh
|
||
|
||
# Nur lesen und prüfen (Standard):
|
||
/usr/local/sbin/switch-resolver-to-bind9.sh --check
|
||
|
||
# Umstellung mit interaktiver Bestätigung (exakt 'yes'):
|
||
/usr/local/sbin/switch-resolver-to-bind9.sh --apply
|
||
|
||
# Rückbau des durch dieses Skript vorgenommenen Zustands:
|
||
/usr/local/sbin/switch-resolver-to-bind9.sh --rollback
|
||
```
|
||
|
||
Statusausgaben verwenden die bekannten Muster `[ Info ]`, `[ ok ]`, `[ failed ]`, `[ skipped ]`. Keine automatische Paketinstallation und kein Reboot. Die Änderung erfolgt **nicht** schon beim Aufruf ohne Parameter.
|
||
|
||
### Was `--apply` tut
|
||
|
||
1. Prüft Root-Rechte, benötigte Kommandos und BIND9; DNSSEC-Positiv- und Negativtest.
|
||
2. Zeigt den geplanten Eingriff und verlangt `Einverstanden [yes/no, default: no]?`.
|
||
3. Legt eine Sicherung von **Datei bzw. Symlink** `/etc/resolv.conf`, `/etc/nsswitch.conf` und dem bisherigen `systemd-resolved`-Dienststatus unter `/var/backups/oopen-bind9-direct-resolver/run-.../` an (Verzeichnis nur für Root).
|
||
4. Ändert, soweit erforderlich, die `hosts:`-NSS-Zeile und erstellt `/etc/resolv.conf` mit `nameserver 127.0.0.1`. Eine vorhandene `search`-Zeile wird übernommen.
|
||
5. Prüft normale Vorwärts- und Reverse-Auflösung.
|
||
6. Stoppt und deaktiviert `systemd-resolved` und prüft BIND9/DNSSEC erneut.
|
||
7. Bei einem Fehler versucht das Skript automatisch einen Rückbau der gesicherten Dateien und des gespeicherten Dienstzustands. Ein automatischer Rückbau ist eine Schutzmaßnahme, **keine Garantie** bei Stromausfall oder hartem Prozessabbruch.
|
||
|
||
Bereits vollständig umgestellte Systeme werden ohne Änderungen mit `[ skipped ]` erkannt. Existiert noch ein offener, vom Skript angelegter Rückbauzustand, bricht ein weiterer `--apply`-Lauf ab. So wird verhindert, dass die ursprüngliche Sicherung unbemerkt überschrieben wird.
|
||
|
||
### Besonderheit bei `lists.mx` (bereits manuell umgestellt)
|
||
|
||
Auf `lists.mx` wurden `/etc/nsswitch.conf` und `/etc/resolv.conf` am 27.10.2026 bereits manuell auf direkten BIND9 umgestellt. Das Skript erkennt dies und kann bei `--apply` den Dienst `systemd-resolved` noch stoppen und deaktivieren, sofern dies noch nicht erfolgt ist. **Der Skript-Rollback stellt dann den Zustand unmittelbar vor diesem Skriptlauf wieder her, nicht automatisch den historischen systemd-resolved-Zustand vom Morgen.**
|
||
|
||
Die zuvor manuell erstellte Sicherung liegt unter:
|
||
|
||
```text
|
||
/root/dns-resolver-backup-20261027-120829
|
||
```
|
||
|
||
Dort ist `resolv.conf` ein relativer Symlink. Er muss bei manueller Wiederherstellung an seinem **ursprünglichen Ort** `/etc/resolv.conf` wieder angelegt werden. Der historische Zustand lässt sich mit gesichertem `nsswitch.conf` und dem ursprünglichen Symlink wiederherstellen; dafür `systemd-resolved` zuerst wieder aktivieren.
|
||
|
||
## 6. Abschließende Prüfungen
|
||
|
||
```bash
|
||
cat /etc/resolv.conf
|
||
grep '^hosts:' /etc/nsswitch.conf
|
||
systemctl is-active bind9
|
||
systemctl is-active systemd-resolved
|
||
systemctl is-enabled systemd-resolved
|
||
getent ahostsv4 oopen.de
|
||
getent hosts 2607:f8b0:4864:20::72e
|
||
dig cloudflare.com A +dnssec +adflag
|
||
dig www.dnssec-failed.org A +time=5 +tries=1
|
||
```
|
||
|
||
Erwartung: BIND9 `active`, `systemd-resolved` `inactive` und `disabled`, erfolgreiche normale Auflösung, DNSSEC-Positivtest `ad`, Negativtest `SERVFAIL`. Bei `dig` muss `SERVER: 127.0.0.1#53` erscheinen. Zusätzlich Mail-Logs und anwendungsspezifische Namensauflösung kontrollieren. Änderungen bestehen über einen Neustart fort, **sofern** kein anderer Netzwerkdienst `/etc/resolv.conf` ersetzt und BIND9 beim Boot zuverlässig startet; einen Neustart des Produktivservers führt das Skript nicht aus.
|
||
|
||
## 7. Rollback
|
||
|
||
Falls `--apply` dieses Skripts zuvor erfolgreich gelaufen ist:
|
||
|
||
```bash
|
||
/usr/local/sbin/switch-resolver-to-bind9.sh --rollback
|
||
```
|
||
|
||
Das stellt die bei **diesem Skriptlauf** gesicherten Dateien und den Dienststatus nach Bestätigung wieder her. Die Sicherungsdateien bleiben archiviert. Falls die Dateien **vor dem ersten Skriptlauf** schon direkt BIND9 benutzten, bringt dieser Rollback folgerichtig nicht den ursprünglichen systemd-Stub zurück.
|
||
|
||
**Manueller Rückbau auf `lists.mx` in den früheren Zustand** (nur bei gezieltem Bedarf und mit konsistenter DNS-Prüfung):
|
||
|
||
```bash
|
||
# Ursprünglichen NSS-Zustand wiederherstellen:
|
||
cp -a /root/dns-resolver-backup-20261027-120829/nsswitch.conf /etc/nsswitch.conf
|
||
|
||
# Dienst starten, Stub-Datei prüfen:
|
||
systemctl enable --now systemd-resolved
|
||
test -f /run/systemd/resolve/stub-resolv.conf
|
||
|
||
# Ziel-Symlink atomar am ursprünglichen Ort wiederherstellen:
|
||
ln -s /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf.rollback-link
|
||
mv -Tf /etc/resolv.conf.rollback-link /etc/resolv.conf
|
||
|
||
# Ergebnis prüfen:
|
||
getent ahostsv4 oopen.de
|
||
dig -x 2607:f8b0:4864:20::72e
|
||
```
|
||
|
||
Die frühere Einstellung `DNSSEC=no` in `/etc/systemd/resolved.conf.d/90-local-bind9.conf` bleibt bei diesem manuellen Rückbau erhalten, solange sie nicht separat geändert wird. DNSSEC bleibt dann bei BIND9 aktiv.
|
||
|
||
## 8. Grenzen und Sicherheit
|
||
|
||
- Das Skript setzt einen bereits gesunden lokalen BIND9 voraus und ist **kein** BIND9-Installationsskript.
|
||
- Kein automatisches Umschalten auf öffentliche Resolver; bei BIND-Ausfall würde lokale DNS-Auflösung ausfallen.
|
||
- Ein vereinfachter `hosts:`-Eintrag `files myhostname dns` ist auf diesem Server geprüft. Systeme mit weiteren NSS-Modulen wie `mymachines`, `mdns` oder LDAP benötigen eine angepasste Variante.
|
||
- `systemd-resolved` kann von speziellen Diensten per D-Bus oder `resolvectl` verwendet werden. Das muss vor dem Deaktivieren separat berücksichtigt werden.
|
||
- `systemd-resolved` wird nur gestoppt/deaktiviert, **nicht deinstalliert oder maskiert**.
|
||
- Bei fehlgeschlagenem Rollback nicht mehrfach blind ausführen: Ausgabe und gesichertes Backup-Verzeichnis überprüfen.
|
||
|
||
## 9. Quellen
|
||
|
||
- [systemd-resolved – Modes für /etc/resolv.conf](https://www.freedesktop.org/software/systemd/man/latest/systemd-resolved.service.html)
|
||
- [nss-resolve – NSS-Reihenfolge und systemd-resolved](https://www.freedesktop.org/software/systemd/man/latest/nss-resolve.html)
|
||
- [Debian: resolvconf-Kompatibilitätsmodus von resolvectl](https://manpages.debian.org/trixie/systemd-resolved/resolvconf.1.en.html)
|