Als ich vor kurzem auf die Idee kam, meinen V-Server (Linux bzw. Ubuntu) neu aufzusetzen, wagte ich mich an meine ersten Versuche mit Docker. Nach einiger Zeit der Beschäftigung fiel mir Portainer, eine grafische Verwaltung für Docker ins Auge. Ich installierte das Tool und musste erschreckend feststellen, wie unzählige Menschen Portainer im Internet nutzen, ohne das Tool gegen Angriffe abzusichern. Ich selbst stand nun auch vor diesem Problem, suchte und suchte jedoch ohne Erfolg, bis ich auf ein ganz interessantes Github Repository stieß.
Die Idee
Verbiete den Zugriff auf Portainer, durch das iptables Frontend Uncomplicated Firewall (kurz UFW), von außen und verbinde dich über eine interne IP-Adresse, mittels VPN, zu Portainer.
Das Problem
Portainer, oder generell alle Docker Anwendungen lassen sich nicht ohne weiteres hinter dem iptables Frontend Uncomplicated Firewall (kurz UFW) verstecken, da Docker diese Regeln ignoriert und sich selbst die benötigten Ports öffnet.
Die Lösung
Nach kurzer Suche bin ich auf das Github Repository chaifeng/ufw-docker aufmerksam geworden, welches eine einfache Lösung vorstellt, um dem Öffnen von Ports, durch Docker.
Einrichtung des chaifeng/ufw-docker
Schritt 1: Deaktivieren Sie die UFW.
sudo ufw --force disable
Schritt 2: Setzen Sie die UFW auf den Anfangsstand zurück, bitte bedenken Sie, dass dadurch alle bereits gesetzten Regeln gelöscht werden.
sudo ufw --force reset
Schritt 3: Verbieten Sie alle eingehenden Verbindungen.
sudo ufw default deny incoming
Schritt 4: Lassen Sie alle nach außen gehenden Verbindungen zu.
sudo ufw default allow outgoing
Schritt 5: Bearbeiten Sie die UFW after.rules
sudo vi /etc/ufw/after.rules
Schritt 6: Kopieren Sie den unten aufgeführten Text ans Ende der UFW after.rules und speichern Sie die Datei.
# BEGIN UFW AND DOCKER
*filter
:ufw-user-forward - [0:0]
:ufw-docker-logging-deny - [0:0]
:DOCKER-USER - [0:0]
-A DOCKER-USER -j ufw-user-forward
-A DOCKER-USER -j RETURN -s 10.0.0.0/8
-A DOCKER-USER -j RETURN -s 172.16.0.0/12
-A DOCKER-USER -j RETURN -s 192.168.0.0/16
-A DOCKER-USER -p udp -m udp --sport 53 --dport 1024:65535 -j RETURN
-A DOCKER-USER -j ufw-docker-logging-deny -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -d 192.168.0.0/16
-A DOCKER-USER -j ufw-docker-logging-deny -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -d 10.0.0.0/8
-A DOCKER-USER -j ufw-docker-logging-deny -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -d 172.16.0.0/12
-A DOCKER-USER -j ufw-docker-logging-deny -p udp -m udp --dport 0:32767 -d 192.168.0.0/16
-A DOCKER-USER -j ufw-docker-logging-deny -p udp -m udp --dport 0:32767 -d 10.0.0.0/8
-A DOCKER-USER -j ufw-docker-logging-deny -p udp -m udp --dport 0:32767 -d 172.16.0.0/12
-A DOCKER-USER -j RETURN
-A ufw-docker-logging-deny -m limit --limit 3/min --limit-burst 10 -j LOG --log-prefix "[UFW DOCKER BLOCK] "
-A ufw-docker-logging-deny -j DROP
COMMIT
# END UFW AND DOCKER
Schritt 7: Geben Sie Ihren SSH Port (normal 22) frei.
sudo ufw allow 22/tcp
Schritt 8: Aktivieren Sie UFW
sudo ufw --force enable
Schritt 9: Laden Sie UFW neu.
sudo systemctl restart ufw
Oder
sudo ufw reload
Ggf. ist auch ein Neustart des Servers nötig. Dies können Sie überprüfen, wenn Sie versuchen, auf die Oberfläche von Portainer zuzugreifen.
Grundverständnis UFW
Für Ihr Verständnis ist es wichtig zu wissen, dass Sie alle UFW Befehle, die einen Docker Container betreffen, nun nach einem anderen Schema absetzen müssen als normale UFW Befehle, wenn Sie einen Effekt erzielen möchten.
# Zugriff auf Port 80 von überall erklauben
ufw route allow proto tcp from any to any port 80
So können Sie eine Freigabe von jedem beliebigen Port erstellen. Sie können den Zugang auch weiter einschränken, indem Sie eines der Wörter „any“ durch z.B. eine IP-Adresse ersetzen, wie später zu sehen.
Einrichtung von WireGuard VPN
Schritt 1: Installieren Sie WireGuard.
sudo apt install wireguard
Schritt 2: Navigieren Sie in das Verzeichnis /etc/wireguard
cd /etc/wireguard
Schritt 3: Generieren Sie je einen Public Key und Private Key für den Zugriff via WireGuard.
sudo wg genkey | tee srv.privatekey | wg pubkey > srv.publickey
sudo wg genkey | tee clt.privatekey | wg pubkey > clt.publickey
Schritt 4: Erstellen Sie die Datei server.conf
sudo vi server.conf
Schritt 5: Füllen Sie die Datei mit folgendem Inhalt und setzen Sie die passenden, zuvor generierten Schlüssel ein.
[Interface]
# Name: server
Address = 192.168.10.10/24
PrivateKey = srv.privatekey
ListenPort = 51820
[Peer]
# Name: client
PublicKey = clt.publickey
AllowedIPs = 192.168.10.11/32
Wir weisen jetzt unserem Server die interne IP-Adresse 192.168.10.10 zu. Über diese können Sie später auch Portainer erreichen. Unser VPN Client bekommt die interne IP-Adresse 192.168.10.11 zugewiesen.
Schritt 6: Installieren Sie WireGuard auf Ihrem Client, z.B. unter Windows. Starten Sie diesen und klicken Sie auf „Einen leeren Tunnel hinzufügen“.
Schritt 7: Vergeben Sie einen beliebigen Namen für den Tunnel und füllen Sie das Textfeld mit dem unten aufgeführten Text. Ersetzen Sie jetzt die passenden, zuvor generierten Schlüssel ein. Anschließend ändern Sie die [Server-IP] auf die IP-Adresse Ihres Servers.
[Interface]
# Name: client
PrivateKey = $clt.privatekey
Address = 192.168.10.11/24
[Peer]
# Name: server
PublicKey = $srv.publickey
EndPoint = [SERVER IP]:51820
AllowedIPs = 192.168.10.10/32, 192.168.10.0/24
PersistentKeepalive = 25
Schritt 8: Löschen Sie die zuvor generierten Keys auf Ihrem Host.
sudo rm *.privatekey
sudo rm *.publickey
Schritt 9: Geben Sie den Port 51820 für WireGuard frei.
sudo ufw allow 51820
Schritt 10: Starten Sie WireGuard auf dem Host.
sudo wg-quick up server
Schritt 11: Öffnen Sie jetzt den Port 9000 auf Ihrem Host, um Zugriff von der IP-Adresse 192.168.10.11 via WireGuard zu erhalten.
ufw route allow proto tcp from 192.168.10.11 to any port 9000
Würden Sie statt dem obigen den nachfolgenden Befehl absetzen, wäre der Zugriff auch weiterhin von außen möglich gewesen. Die IP-Adresse 192.168.10.11 haben wir unserem VPN Client zugewiesen. Weshalb wir via VPN weiterhin Zugriff auf Portainer haben. Ebenso könnten Sie (falls gegeben) eine fixe IP-Adresse unseres Heimanschlusses festlegen.
ufw route allow proto tcp from any to any port 9000
Schritt 12: WireGuard Verbindung Client starten
Test
Jetzt können Sie versuchen, über die [IP-Adresse unseres Servers]:9000 auf Portainer zuzugreifen. Wenn dies nicht gelingt, haben Sie alle Schritte richtig umgesetzt. Ein Zugriff über die Adresse 192.168.10.10:9000 sollte jetzt die Oberfläche von Portainer zeigen und uns dadurch beweisen das unser VPN funktioniert. Jetzt ist das Absichern von Portainer gelungen!
Sollten Sie bei der Umsetzung Ihrer Projekte Hilfe benötigen, wenden Sie sich gern an mich.