Fundierte Artikel über Technologien, die das Kommende formen.

Die DNS-Konfiguration bricht immer noch Produktivsysteme

DNS wirkt simpel, bis es bricht: OS-Updates, resolv.conf, mDNS und die .internal-TLD verursachen Ausfälle, die Entwickler nicht kommen sehen.

Briefe, die in einem Sortierraum in falsche Rohrpost-Röhren geleitet werden

Apples neuestes macOS-Update hat die individuellen DNS-Einstellungen tausender Entwickler kaputt gemacht. Konkret fängt es jetzt Anfragen für die TLD .internal ab – die viele Unternehmen für Ressourcen in ihrem privaten Netzwerk nutzen – und leitet sie an mDNS (Multicast DNS) statt an den konfigurierten DNS-Resolver weiter. Dienste, die jahrelang problemlos funktioniert hatten, waren plötzlich nicht mehr erreichbar. Die Lösung war alles andere als offensichtlich. Die Fehlermeldungen halfen kaum weiter. Und wie so oft bei DNS-Problemen sahen die Symptome nach allem außer DNS aus.

Dies ist eine Geschichte über DNS-Konfiguration – ein Thema, mit dem jeder Entwickler zu tun hat, das nur wenige wirklich verstehen und das jeder unterschätzt, bis es um 2 Uhr nachts etwas in der Produktion lahmlegt.

Der .internal-TLD-Vorfall

Viele Organisationen nutzen .internal als private TLD für interne Dienste: api.internal, db.staging.internal, grafana.internal. Das schien eine sichere Wahl zu sein – es ist keine öffentliche TLD, es signalisiert eindeutig „das ist intern“, und so wird sie seit Jahrzehnten verwendet.

Dann entschied Apples neues OS, dass .internal über mDNS behandelt werden soll – dasselbe Protokoll, das myprinter.local in deinem Heimnetz auflöst. Wenn dein Mac api.internal auflösen will, fragt er nicht mehr den konfigurierten DNS-Server, sondern sendet eine mDNS-Anfrage ins lokale Netzwerk. Dein DNS-Server bekommt die Anfrage nie zu Gesicht. Die Antwort bleibt entweder aus (Timeout) oder fällt falsch aus, falls irgendein Gerät im lokalen Netz auf diesen Namen antwortet.

Die Symptome: curl api.internal hängt fünf Sekunden und scheitert dann. SSH-Verbindungen zu internen Hosts laufen in einen Timeout. VPN-Nutzer erreichen keine internen Ressourcen. Docker-Container können Servicenamen nicht auflösen. Und weil sich der Fehler als allgemeiner Verbindungs-Timeout äußert, suchen die meisten Entwickler den Fehler im VPN, in der Firewall oder in der Anwendung – überall, nur nicht bei DNS.

Wie DNS-Auflösung auf modernen Systemen tatsächlich funktioniert

Das Denkmodell „DNS ist simpel“ – dein Rechner fragt einen DNS-Server nach einer IP, der Server antwortet – stimmt seit Jahren nicht mehr. Moderne Systeme haben eine Auflösungskette mit mehreren Stufen, und jede davon kann Anfragen abfangen, verändern oder umleiten.

DNS resolution pipeline on a typical macOS/Linux system:
Application calls getaddrinfo("api.internal")
↓
1. /etc/hosts — checked first. Static overrides.
↓
2. NSSwitch / resolver configuration
- Linux: /etc/nsswitch.conf controls lookup order
- macOS: /etc/resolver/* for per-domain DNS servers
↓
3. System resolver (systemd-resolved, mDNSResponder)
- May intercept .local, .internal, or other special TLDs
- May apply DNSSEC validation
- May cache responses
↓
4. DNS server (from DHCP, VPN, or manual config)
- Queries sent to configured upstream resolver
- May go through a corporate DNS proxy
↓
5. Recursive resolver (8.8.8.8, 1.1.1.1, corporate)
- Walks the DNS hierarchy: root → TLD → authoritative
↓
Response flows back up the chain

Auf jeder Stufe kann etwas schiefgehen. Der System-Resolver könnte eine Anfrage abfangen, bevor sie deinen konfigurierten DNS-Server erreicht. Das VPN könnte DNS-Einstellungen überschreiben. DHCP könnte DNS-Server vorgeben, die deine manuelle Konfiguration verdrängen. Und Caching auf jeder Ebene bedeutet, dass eine Korrektur unter Umständen nicht sofort wirkt.

Die Lüge mit /etc/resolv.conf

Unter Linux war /etc/resolv.conf historisch die einzige Quelle der Wahrheit für die DNS-Konfiguration. Trägst du dort deinen Nameserver ein, nutzt das System ihn. Einfach.

Moderne Linux-Distributionen haben das deutlich komplizierter gemacht. Wenn systemd-resolved läuft (was bei Ubuntu, Fedora und den meisten systemd-basierten Distributionen standardmäßig der Fall ist), ist /etc/resolv.conf ein Symlink auf einen Stub-Resolver unter 127.0.0.53. Die eigentliche DNS-Konfiguration liegt im Zustand von systemd-resolved und wird über resolvectl verwaltet. Wenn du /etc/resolv.conf direkt bearbeitest, wird die Änderung beim nächsten Netzwerkwechsel überschrieben oder der Stub-Resolver geht kaputt.

# What you THINK your DNS config is:
$ cat /etc/resolv.conf
nameserver 127.0.0.53  # This is systemd-resolved's stub
# What your DNS config ACTUALLY is:
$ resolvectl status
Global:
DNS Servers: 8.8.8.8 8.8.4.4
DNS Domain: ~.
Link 2 (eth0):
DNS Servers: 10.0.0.1  # From DHCP — this takes precedence
DNS Domain: corp.internal
Link 5 (wg0):  # WireGuard VPN
DNS Servers: 10.100.0.1
DNS Domain: ~internal  # VPN claims the .internal domain
# Three different DNS servers, each handling different domains.
# /etc/resolv.conf shows none of this.

Docker fügt eine weitere Ebene hinzu. Docker-Container bekommen ihre eigene /etc/resolv.conf, die meist beim Start aus der Host-Konfiguration kopiert wird. Ändert sich das DNS des Hosts (VPN verbindet sich, Netzwerk wechselt), behalten laufende Container die alte Konfiguration, bis sie neu gestartet werden. Das ist eine typische Ursache für Bugs nach dem Muster „funktioniert nach einem Neustart, fällt nach einer Weile aus“.

Split DNS und VPN-Konflikte

Split DNS – unterschiedliche DNS-Server für unterschiedliche Domains – ist in Unternehmensumgebungen Standard. Dein VPN leitet Anfragen für *.corp.internal an den Unternehmens-DNS-Server weiter, öffentliche Anfragen gehen weiterhin an deinen normalen Resolver. Das funktioniert gut, wenn es richtig konfiguriert ist, und führt zu verwirrenden Fehlern, wenn nicht.

Häufige Fehlerquellen:

  • Das VPN setzt DNS-Server als globale Standardwerte. Manche VPN-Clients machen den DNS-Server des VPNs zum Standard-Resolver für alle Anfragen, nicht nur für interne. Damit laufen sämtliche DNS-Anfragen – auch das private Surfen – über den Unternehmens-DNS-Server. Das ist langsam (weil der Unternehmens-DNS in einem anderen Rechenzentrum steht) und ein Datenschutzproblem.
  • Konflikte bei der Reihenfolge der DNS-Server. Sind mehrere DNS-Server konfiguriert, probiert das System sie nacheinander durch. Ist der erste Server langsam oder nicht erreichbar (das VPN ist getrennt, die DNS-Konfiguration bleibt aber bestehen), wartet jede DNS-Anfrage auf einen Timeout, bevor der zweite Server probiert wird. Das bringt jeder Verbindung 5 Sekunden Verzögerung.
  • Suchdomains werden still angehängt. Eine Suchdomain corp.internal bewirkt, dass eine Anfrage für api auch api.corp.internal probiert. Das ist praktisch (du tippst ssh api statt ssh api.corp.internal), bis es nicht mehr praktisch ist – wenn ein kurzer Hostname mit dem Namen eines internen Dienstes kollidiert, wird auf die falsche IP aufgelöst.
  • mDNS fängt interne Domains ab. Wie der .internal-Vorfall zeigt, kann der System-Resolver Anfragen für bestimmte TLDs abfangen, bevor sie einen konfigurierten DNS-Server erreichen. Besonders heimtückisch ist das, weil die Umleitung still passiert – ohne Fehlermeldung, nur mit einem Timeout oder einer falschen Antwort.

DNS debuggen: Das Werkzeugset

Wenn DNS ausfällt, brauchst du Werkzeuge, die dir genau zeigen, was auf jeder Stufe der Auflösungskette passiert.

# 1. Check what your system actually resolves:
$ dig api.internal
# Shows: query sent to which server, response received
# The 'SERVER' line tells you which DNS server answered
# 2. Query a specific DNS server directly:
$ dig @10.100.0.1 api.internal
# Bypasses the system resolver — goes directly to the specified server
# If this works but 'dig api.internal' doesn't, the problem is
# in the system resolver, not the DNS server
# 3. Check systemd-resolved state (Linux):
$ resolvectl query api.internal
# Shows which interface/server handled the query
# 4. Check macOS DNS routing:
$ scutil --dns
# Shows per-domain DNS configuration on macOS
# Look for your .internal domain — is it being routed correctly?
# 5. Monitor DNS queries in real time:
$ sudo tcpdump -i any port 53
# See actual DNS packets. If no packets go out for your query,
# the system resolver is intercepting it locally.
# 6. Flush DNS cache (when fixing config):
$ sudo dscacheutil -flushcache && sudo killall -HUP mDNSResponder  # macOS
$ resolvectl flush-caches  # Linux with systemd-resolved

Der wichtigste Diagnoseschritt: Frag deinen DNS-Server direkt mit dig @server hostname ab. Funktioniert das, die normale Auflösung aber nicht, liegt das Problem zwischen deiner Anwendung und dem DNS-Server – also beim Abfangen durch den System-Resolver, beim Caching oder beim Routing. Schlagen auch die direkten Abfragen fehl, liegt das Problem beim DNS-Server selbst oder bei der Netzwerkverbindung zu ihm.

Die Wahl deiner privaten TLD

Der .internal-Vorfall wirft die praktische Frage auf: Welche TLD sollte man für interne Dienste verwenden? Eine universell sichere Antwort gibt es nicht, aber manche Optionen sind besser als andere.

  • .internal – RFC 6762 reserviert diese Endung für die interne Nutzung, aber Apples mDNS-Behandlung macht sie unter macOS problematisch. Unter Linux funktioniert sie vermutlich problemlos.
  • .local – Reserviert für mDNS (RFC 6762). Wer sie für per DNS aufgelöste Dienste nutzt, bekommt Konflikte mit Bonjour/Avahi. Nicht verwenden.
  • .corp, .home, .mail – Nicht reserviert. Die ICANN könnte sie jederzeit als öffentliche TLDs vergeben, was deine interne Auflösung zerstören würde. Nicht verwenden.
  • Subdomain einer Domain, die dir gehört. internal.deinefirma.de – das ist die sicherste Option. Du kontrollierst die übergeordnete Domain, also gibt es kein Kollisionsrisiko. Der Nachteil: Es ist länger zu tippen.
  • .test, .example, .invalid, .localhost – Durch RFC 6761 reserviert und garantiert nie als öffentliche TLD vergeben. .test ist die sauberste Option für interne Dienste, die nicht produktiv sind.

Die unspektakuläre, aber richtige Antwort: Nutze eine Subdomain einer Domain, die dir gehört. api.internal.deinefirma.de ist eindeutig, kollidiert mit nichts und funktioniert auf jedem Betriebssystem und jedem DNS-Resolver einwandfrei. Es ist länger, aber DNS-Probleme um 2 Uhr nachts sind schlimmer als ein paar zusätzliche Buchstaben beim Tippen.

Lektionen für Produktionssysteme

Jeder DNS-Ausfall lehrt dieselben Lektionen, und wir lernen sie immer wieder neu.

  1. Überwache die DNS-Auflösung, nicht nur die DNS-Server. Dass dein DNS-Server gesund ist, heißt noch lange nicht, dass die Auflösung funktioniert. Überwache den gesamten Pfad: Kann deine Anwendung die Hostnamen, die sie braucht, tatsächlich auflösen? Ein synthetischer Check, der kritische Hostnamen alle 30 Sekunden auflöst, erkennt Probleme schneller als reine Serverüberwachung.
  2. Setze kurze TTLs für internes DNS. Wenn du einen internen DNS-Eintrag ändern musst, sorgen lange TTLs für veraltete Daten im Cache. 60-Sekunden-TTLs für interne Dienste ermöglichen schnelles Failover bei minimaler Last auf den Resolvern.
  3. Teste OS-Updates gegen dein DNS-Setup. Der .internal-Bruch betraf nur macOS-Nutzer. Teste deine Entwicklungsumgebung nach größeren OS-Updates – Änderungen an der DNS-Auflösung stehen selten in den Release Notes.
  4. Dokumentiere deine DNS-Architektur. Welche DNS-Server sind für welche Domains zuständig? Wo liegen die Split-Punkte? Was passiert, wenn das VPN getrennt wird? Diese Dokumentation brauchst du als Erstes bei einem Ausfall – und sie ist das, was am Ende niemand schreibt.
  5. Plane einen Fallback ein. Kann deine Anwendung bei einem Ausfall der DNS-Auflösung für einen internen Dienst auf eine fest kodierte IP zurückfallen? Elegant ist das nicht, aber eine funktionierende feste IP ist besser als ein DNS-Name, der nicht aufgelöst wird.

DNS ist einer dieser grundlegenden Dienste, die unsichtbar sind, solange sie funktionieren, und katastrophal, wenn nicht. Der .internal-Bruch erinnert daran, dass DNS-Konfiguration fragiler ist, als sie aussieht – ein einziges OS-Update kann das Auflösungsverhalten für Millionen Nutzer verändern. Baue deine Systeme in dem Bewusstsein, dass DNS irgendwann ausfallen wird, dann überrascht dich der Ausfall weit weniger.