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 997 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 - wie in der Docker Dokumentation
bereits sehr gut beschrieben, - verwenden wie zusätzlich einen Alias der uns den
Tippaufwand für sudo docker compose
erspart:
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.
IPv4-to-IPv6 Proxy¶
Dieser einfache IPv4-to-IPv6 Proxy unterstützt in seiner ersten Version lediglich HTTP Verbindungen auf Port 80 und TLS Verbindungen auf Port 443. Eine Anpassung dieser Konfiguration um einige anderen Protokolle (SMTPs, IMAPs, POP3s) welche TLS verwenden zu unterstützten ist denkbar.
Aus Gründen der Vollständigkeit hier einmal die nginx Konfiguration für den Proxy für Alpine Linux. Die Einrichtung ist denkbar einfach: nginx installieren, die untenstehende Konfiguration kopieren und den Proxy starten:
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log notice;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
keepalive_timeout 65;
server {
listen 80 default_server;
location / {
return 301 https://$host$request_uri;
}
}
}
stream {
# https://gist.github.com/kekru/c09dbab5e78bf76402966b13fa72b9d2#non-terminating-tls-pass-through
server {
listen 443;
proxy_connect_timeout 1s;
proxy_timeout 3s;
resolver 1.1.1.1 1.0.0.1 [2606:4700:4700::1111] [2606:4700:4700::1001] ipv6=on ipv4=off;
proxy_pass $ssl_preread_server_name:443;
ssl_preread on;
}
}
Vergleich der Möglichkeiten¶
Aus meiner Sicht ergibt die Verwendung eines eigenen vorgeschaltenen Proxies nur Sinn, wenn mehr als ein Server administriert wird und die Web-Server über IPv6 Adressen exposiert bereitstellt werden.
Wird lediglich ein System betreut (wie z.B. der oben erwähnte Cloudserver), kann die zugewiesene IPv4 Adresse natürlich ebenfalls auf den Ports 80 und 443 verwendet werden und dann auf den Reverse Proxy zeigen. Dadurch entfällt die Abhängigkeit zu anderen Systemen.
Sofern der Cloudserver über keine eigene IPv4 Adresse oder keine eigenen IPv6 Adressen verfügt, sollte ein Proxy vorgeschaltet werden, um den Nutzern, die keine IPv4/IPv6 Adresse verfügen den Zugriff zu ermöglichen.
Wird Cloudflare Proxy verwendet erkauft man sich neben der Erreichbarkeit diverse Vorteile (DDoS Protection, Web Application Firewall, Page Rules).
Jedoch sollte man einige Details beachten, bevor man sich auf Cloudflare festlegt.
Der Datenverkehr der Nutzer liegt bei Cloudflare unverschlüsselt vor, da diese die
TLS Pakete terminieren. In der kostenfreien Version von Cloudflare Proxy können
des Weiteren keine gestackten Subdomains (sub.sub.domain.de
) eingerichtet werden,
da dafür kein TLS Zertifikat angefordert werden kann.
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