IPv4, IPv6, SSL und Docker – sehr viel verrückter wird es nicht!
Momentan sieht’s so aus: Die Ports 80 (http) und 443 (https) werden über den sogenannten „Userland Proxy“ von Docker auf allen Netzwerk-Interfaces des Servers veröffentlicht. Die SSL-Terminierung übernimmt Nginx. Für IPv4-Clients ist alles super, für IPv6-Clients wird der jeweilige Container intern aber per IPv4 kontaktiert. Das ist im Log des Reverse Proxy zu sehen:
Ruft man eine der IP-Adressen des Servers direkt im Browser auf, sieht man Dinge, die man nicht sehen will: Beim Zugriff mit HTTP ist das eine hässliche Fehlerseite, mit HTTPS ist es ein Zertifikatsfehler.
Für HTTP lässt sich das relativ einfach beheben, indem im Reverse Proxy ein – nach außen nicht sichtbarer – Default-Host mit dem gemäß RFC2606 ungültigen Namen „invalid.invalid“ konfiguriert wird, der einfach nur einen Redirect liefert. Damit leiten http://176.9.147.173 und http://[2a01:4f8:160:30a8::2] schon mal richtig weiter.
Für HTTPS funktioniert das prinzipiell auch, allerdings macht mir dort SSL einen Strich durch die Rechnung: Da die IP-Adressen des Servers laut RIPE Hetzner gehören, wird mir keine vertrauenswürdige CA ein Zertifikat dafür ausstellen. Es muss also eine Alternative her, die ohne „richtiges“ Zertifikat auskommt. Um die Warnung im Browser kommt man dann aber leider nicht herum.
Als halbwegs brauchbare Lösung erscheint mir ein selbstsigniertes Zertifikat mit Text im „Common Name“. Das ist im eben angelegten Default-Host am Reverse Proxy auch schnell konfiguriert. Beim Zugriff auf https://176.9.147.173 und https://[2a01:4f8:160:30a8::2] bekommt man dann zwar den unvermeidlichen Zertifikatsfehler zu sehen, aber zumindest hat der eine hübsche Meldung:
Momentan läuft auf dem Server noch nichts wirklich sinnvolles. Damit das nicht so bleibt, installiere ich Docker Community Edition. Der Plan ist, den Großteil der Server-Software in Form von Docker-Containern laufen zu lassen.
Als nächstes starte ich jeweils einen Docker-Container auf Basis der Images jwilder/nginx-proxy und jrcs/letsencrypt-nginx-proxy-companion. Unverschlüsselte HTTP-Verbindungen liefern ausschließlich Weiterleitungen auf die entsprechenden HTTPS-Äquivalente, die durch das Zusammenspiel der beiden Docker-Container mit Zertifikaten von Let’s Encrypt abgesichert sind.
Um sämtliche Kombinationen aus „www.“, „.de“ und „.com“ letztlich auf die Master-URL umzulenken, sind noch ein paar Weiterleitungen notwendig. Dafür benutze ich das Docker-Image schmunk42/nginx-redirect. Über den vorher aufgesetzten Mechanismus bekommen auch die daraus erstellten Redirect-Container vollwertige SSL-Zertifikate.
Beim Test der der Redirect-Container fiel mir allerdings noch auf, dass sie sich nicht sauber stoppen lassen. Die Lösung dafür spiele ich mit einem Pull-Request an den Autor zurück.