fix: nur noch über IPv4 prüfen, hetzner hat kein funktionierendes IPv6

hetzner hat eine globale IPv6-Adresse und eine Default-Route, aber keine
Konnektivität — auch google.com und cloudflare.com laufen über IPv6 in den
Timeout. Bei jeder Domain mit AAAA-Record wartete Python erst ~20s, bevor es
auf IPv4 zurückfiel: vanityontour.de und wiki wurden mit über 20000ms statt
~180ms gemessen, und der Lauf überschritt das 5-Minuten-Cron-Intervall.

Bisher war das verdeckt, weil ein /etc/hosts-Block auf hetzner die betroffenen
Domains auf IPv4 pinnte. Der Block stammte aus der DNS-Migration im April, war
überholt und enthielt für wiki.vanityontour.de eine tote IP (2.57.91.91) —
daher der TLS-Fehler und das dauerhafte "down" des Wikis. Mit dem Entfernen des
Blocks kam die latente IPv6-Störung zum Vorschein.

Der Checker filtert getaddrinfo jetzt auf AF_INET. Das ist kein Workaround um
die Störung herum, sondern beschreibt den Messpunkt korrekt: mehr als IPv4
kann hetzner derzeit nicht erreichen. Die IPv6-Störung selbst bleibt offen.
This commit is contained in:
Oliver 2026-08-03 07:02:31 +02:00
parent db2c6c70a0
commit 61c486167c
No known key found for this signature in database

View file

@ -12,6 +12,22 @@ import urllib.request
import urllib.error
from datetime import datetime, timezone
# hetzner, von dem aus geprüft wird, hat zwar eine globale IPv6-Adresse und eine
# Default-Route, aber keine funktionierende IPv6-Konnektivität — jede Verbindung
# zu einem AAAA-Record läuft erst in einen ~20s-Timeout, bevor Python auf IPv4
# zurückfällt. Das verfälscht die gemessenen Antwortzeiten massiv (20s statt
# 150ms) und zog den Lauf über das Cron-Intervall hinaus. Bis IPv6 auf hetzner
# repariert ist, wird hier ausschließlich über IPv4 geprüft — das entspricht
# ohnehin dem, was dieser Messpunkt tatsächlich erreichen kann.
_getaddrinfo_orig = socket.getaddrinfo
def _getaddrinfo_ipv4_only(*args, **kwargs):
return [ai for ai in _getaddrinfo_orig(*args, **kwargs) if ai[0] == socket.AF_INET]
socket.getaddrinfo = _getaddrinfo_ipv4_only
OUTPUT_FILE = "public/status.json"
# Seit der VPN-Absicherung (Phase 2) antworten die Admin-Oberflächen auf ihren