Basisinstallation¶
Jeder, der diese Informationssammlung nutzt, sollte in der Lage sein, seinen Linux Server grundlegend einzurichten und abzusichern. Daher verzichte ich hier auf Standardanleitungen und stelle lediglich die spezifischen Konzepte vor.
Admin Gruppe¶
Ich gehe grundsätzlich davon aus, dass ich auf keinem System der alleinige
Administrator bin, weshalb auf allen Systemen eine Admin-Gruppe existiert,
die Rechte auf das Verzeichnis /home/admin
hat.
groupadd -g 1100 admin
mkdir -m 775 /home/admin
chown root:admin /home/admin
Die personalisierten Accounts der Systemadministratoren erhalten neben der sudo
Gruppenmitgliedschaft auch die Gruppe admin
:
adduser nicof2000
usermod -aG sudo,admin nicof2000
Docker¶
Die Installation von Docker ist in der offiziellen Dokumentation bereits sehr gut beschrieben. Zusätzlich richten wir einen Alias ein, um uns die wiederholte Eingabe von sudo docker compose zu ersparen.
curl -fsSL https://get.docker.com | sudo bash
echo 'alias dc="sudo docker compose "' >> ~/.bashrc
Proxy und Reverse Proxy¶
In den folgenden Kapiteln werden die sechs möglichen Kombinationen vorgestellt.
Welche der Konfigurationen man verwendet, ist jedem selbst überlassen.
Meine Geschichte¶
Vielleicht hilft euch meine Geschichte, welche beschreibt, warum ich diese verschiedenen Verfahren einsetze. Früher hatte ich einen kleinen Cloudserver, welcher sowohl über eine IPv4 Adresse als auch ein /64er IPv6 Netz verfügte. Auf diesem Server lief letzten Endes eine Vorgängerversion des hier beschriebenen Konzepts.
Im weiteren Verlauf, administrierte ich einen dedizierten Server, der ebenfalls über eine IPv4 Adresse und ein /64er IPv6 Netz verfügte. Da auf diesem jedoch mehrere virtuelle Maschinen betrieben werden sollten, musste ich mir eine Möglichkeit überlegen, wie ich das HTTP Routing für Clients, die über IPv4 kamen gestaltete.
Zunächst verwendete ich dafür einen zentralisierten Reverse Proxy, welcher alle HTTP Requests annahm und dann zu den jeweils verantwortlichen virtuellen Maschinen weiterleitete. Dort wurde ein weiterer Reverse Proxy betrieben, welcher sich um das HTTP Routing zu den einzelnen Docker Containern kümmerte.
Dies hatte den großen Nachteil, dass zwangsläufig ein weiterer Reverse Proxy im Einsatz war, um die richtige virtuelle Maschine zu adressieren. Für das Aufsetzen eines neuen Dienstes war plötzlich ein weiterer Schritt auf einer anderen Maschine notwendig.
Zu einem späteren Zeitpunkt erhielten weitere Administratoren für eigene virtuelle Maschinen Zugriff auf diesen dedizierten Server. Da ich diesen den Zugriff auf den Reverse Proxy, welcher das Routing zu den virtuellen Maschinen verwehren wollte, verwendete ich zunächst nur auf IPv6 exposierte Web-Server in Verbindung mit Cloudflare Proxy, um die IPv4 Erreichbarkeit zu sichern und zusätzlich weitere Schutzmaßnahmen (z. B. Denial of Service Schutz) für diesen dedizierten Server in Anspruch zu nehmen.
Spätestens seit Zensus 2022, bei dem das Statistische Bundesamt durch die Verwendung des Cloudflare Proxies in Verruf geriet, ist klar, dass auch die Verwendung des Cloudflare Proxys aus Privatsphäre-Gründen bedenklich ist (die übermittelten Daten stehen Cloudflare unverschlüsselt zur Verfügung, da der Cloudflare Proxy die TLS Verbindung terminiert).
Vor allem durch unsicherheiten hinsichtlich der Abmahnwelle wegen Google Fonts im selben Jahr, konfigurierte ich mir einen eigenen (transparenten) Proxy, um zumindest für die IPv4 Erreichbarkeit eine Alternative zu Cloudflare in der Hinterhand haben zu können.
Die Idee hinter diesem Proxy ist extrem einfach: Im DNS stehen für IPv6 (DNS AAAA-Record) die Adressen des eigentlichen Webservers, sodass die Nutzer sich direkt mit diesem Verbinden können. Falls die Nutzer über keine IPv6 Konfiguration verfügen, nutzen Sie den im IPv4 (DNS A-Record) hinterlegten IPv4-to-IPv6 Proxy, der die Anfragen dann über IPv6 weiterleitet, OHNE die TLS Verbindung zu terminieren. Dies hat den Vorteil das keine TLS Zertifikate benötigt werden.
Reverse Proxy¶
Sowohl nginx als auch Traefik, sind beide stark verbreitete Proxies. Sie werden von großen Unternehmen wie Google, Cloudflare, Dropbox und Mozilla verwendet. Ich habe mich nach reichlicher Überlegung dazu entschieden beide Varianten vorzustellen, da sowohl Traefik, als auch nginx ihre Vorteile haben.
Hinsichtlich Traefik betrachten wir lediglich den dynamischen Modus, bei dem das HTTP Routing über die Docker Labels konfiguriert wird.
Die Ersteinrichtung von Traefik empfinde ich, vor allem auf den ACME Client bezogen, als schwieriger als die von nginx. Mit nginx wird acme.sh (ein separates Skript) zum Ausstellen der TLS Zertifkate verwendet, während dies bei Traefik integriert ist.
Im weiteren Verlauf des Betriebs eines Systems mit Reverse Proxy bedeutet nginx einen höheren Konfigurationsaufwand als Traefik, da die nginx Virtual Host Konfiguration anders als bei Traefik nicht innerhalb der Containerdefinition erfolgt und die Zertifikate ggf. manuell über acme.sh ausstellen werden müssen.
Traefik bringt des Weiteren ein Dashboard mit, welches einen komfortablen Überblick über die existierenden Services und Router gibt. Dieses Dashboard sollte natürlich, sofern extern erreichbar, entsprechend geschützt sein, um das ungewollte Leaken von Informationen zu vermeiden.
Einer der wichtigsten Aspekte für die Wahl des Reverse Proxies ist aber möglicherweise, dass Traefik Zugriff auf den Docker Socket des Hosts benötigt, um die Container Labels auslesen zu können, und die HTTP Routen dynamisch zu generieren. Im Falle einer Sicherheitslücke, bei der, der Traefik Container übernommen werden kann, bedeutet dies, dass der gesamte Server komprimiert ist, da beispielsweise ein neuer Container erstellt werden kann, bei dem das Host-Dateisystem komplett eingehängt ist.
Da nginx nicht als Docker Container bereitgestellt wird, sondern direkt auf dem Host installiert wird, gilt hier eine andere Verzeichnisstruktur.
Die "Virtual-Host" Konfigurationsdateien liegen im Verzeichnis /etc/nginx/sites-available/
unter der Domain, die Sie erreichbar machen.
TLS Zertifikate beziehe ich mithilfe des Shellskriptes acme.sh
,
welches ich unter dem root-Nutzer laufen lasse. Die resultierenden privaten Schlüssel
und Zertifkate werden im Verzeichnis /root/.acme.sh/
gespeichert und direkt von
dort in der nginx Virtual-Host Konfiguration eingebunden.
Da Traefik als Docker Container bereitgestellt wird, gilt die oben genannte Verzeichnisstruktur:
- Containerdefinition:
/home/admin/traefik/docker-compose.yml
- Env-Vars (hier DNS API Token):
/home/admin/traefik/.traefik.env
- Daten (z.B. TLS Zertifikate):
/srv/traefik
Traefik verwendet als ACME Client Lego. Die Konfiguration dieses
kann der Traefik Dokumentation entnommen werden.
Die angeforderten Zertifikate und Privaten Schlüssel werden im /srv/traefik
Volume des Traefik
Containers gespeichert.
In komplexeren Server-Infrastrukturen kann es sinnvoll sein, jedem Virtual Host eine
eigene dedizierte IPv6 Adresse zuzuweisen. Dies hat den großen Vorteil, das man z. B.
die Firewall Logs auf Layer 3 auswerten kann, statt den TLS SNI Header zu betrachten, um den beteiligten
Webserver in Erfahrung zu bringen.
Da ich in diesen Netzwerken bisher immer auf nginx gesetzt habe,
habe ich nie geprüft, ob Traefik dieses Feature (jedem HTTP Router
eine eigene IPv6 Adresse zuzuweisen) ebenfalls unterstützt.
Prinzipiell ist die genutzte ACME Challenge irrelevant, da ich
auch interne Dienste betreibe, die nicht aus dem Internet erreichbar sind, verwende ich prinzipiell die ACME-DNS-01
Challenge. Sowohl Traefik / Lego als auch
acme.sh
unterstützten eine Vielzahl an DNS API's