Erste Hilfe, sollte man sich ausgesperrt haben
Ein guter Rat. Diese Seite ausdrucken oder auf den Lokalen Rechner kopieren. Damit man das lesen kann, wenn der Server down ist.
https://docs.hetzner.com/de/robot/dedicated-server/troubleshooting/hetzner-rescue-system
Mit rescue Image booten und mit
# Nicht blind kopieren,
# Kann auch anders sein, je nach setup des Servers
mount /dev/mapper/vg0-root /mnt
chroot-prepare /mnt
chroot /mnt
in die root / Partition chrooten
Wenn ufw als firewall installiert ist:
Hier zur Sicherheit Port 22 erlauben.
in
- /etc/rc.local
/usr/sbin/ufw allow 22
exit 0
Retrospektive: WikiJS, Firewall, DB- und Mail-Probleme
In dieser Retrospektive wird der Verlauf der Ereignisse, die Lösungsansätze und die schlussendliche Lösung für die Herausforderungen zusammengefasst, die bei der Konfiguration des WikiJS-Systems, der Firewall-Regeln und der E-Mail-Zustellung aufgetreten sind.
1. Ausgangssituation und Problemstellung
- Das WikiJS-System lief als Docker-Container.
- PostgreSQL lief als native Installation auf dem Server.
- Die Webseite, die WikiJS nutzt, hatte anfänglich keine Probleme beim Lesen der Datenbank, aber das Schreiben schlug fehl.
- Eine wachsende Mailqueue in Postfix deutete darauf hin, dass E-Mails zwar angenommen, aber nicht weitergeleitet wurden.
- Es gab diverse Hinweise auf Firewall- und iptables-Konfigurationen, die sich auf die Erreichbarkeit der Datenbankports (5432 für PostgreSQL, 3306/3307 für MariaDB) auswirkten.
- Zusätzlich kam es zu Verbindungsproblemen zwischen Postfix und Dovecot über LMTP, was zu Timeouts beim Empfang der Initial-Greeting führte.
2. Erste Untersuchungen und Lösungsansätze
-
Firewall- und iptables-Überprüfungen:
- Es wurde festgestellt, dass die UFW-Regeln und iptables-Regeln nicht wie erwartet funktionierten.
nmap-Scans zeigten, dass Port 5432 von außen als offen oder gefiltert angezeigt wurde, obwohl entsprechende DROP-Regeln vorhanden waren.- Testeingaben mit
telnetbestätigten, dass Verbindungen zu Port 5432 weiterhin möglich waren.
-
Docker und interne Netzwerke:
- WikiJS lief als Container und stellte die Verbindung zur DB über die öffentliche IP her.
- Es wurde festgestellt, dass Verbindungen aus dem Docker-Netz (172.17.0.0/16, 172.22.0.0/16) explizit erlaubt werden mussten.
-
UFW und iptables:
- Mehrere Skripte wurden entwickelt, um Regeln in der INPUT- und DOCKER-USER-Kette zu setzen.
- Der erste Ansatz beinhaltete das Einfügen von Allow-Regeln für:
- 127.0.0.1 (Loopback)
- Öffentliche IP (142.132.249.241)
- Docker-Subnetze (172.17.0.0/16, 172.22.0.0/16)
- Danach wurde eine generelle DROP-Regel für Port 5432 hinzugefügt.
- Es zeigte sich, dass die Reihenfolge der Regeln entscheidend war.
-
Problem bei Postfix/Dovecot:
- Eine wachsende Mailqueue führte zu der Fehlermeldung:
(delivery temporarily suspended: conversation with isp.rootgemeinschaft.de[private/dovecot-lmtp] timed out while receiving the initial server greeting) - Dies deutete darauf hin, dass die LMTP-Kommunikation zwischen Postfix und Dovecot aufgrund von Timeouts fehlschlug.
- Eine wachsende Mailqueue führte zu der Fehlermeldung:
Der Port 3306 war mit ufw noch nicht geöffnet
ufw 3306 ist die Lösung
und weil wir gerade dabei sind...
Für eMail müssen diese Ports frei sein:
Port 110 POP3 (Post Office Protocol) Dovecot
Port 143 IMAP (Interim Mail Access Protocol) Dovecot
Port 25 SMTP (Simple Mail Transfer Protocol) Postfix
Port 465 SMTPS (SMTP über SSL) Postfix
Port 587 SMTP (Submission TLS-Verschlüsselung) Postfix ▶ 📌
Port 993 IMAPS (IMAP über SSL) Dovecot ▶ 📌
Port 995 POP3S (POP3 über SSL) Postfix ▶ 📌
- DNS, TLS und Authentifizierung:
- Es wurden auch mögliche Ursachen wie DNS-Probleme, TLS-Konfigurationsfehler und Authentifizierungsprobleme in MySQL (bzw. MariaDB) diskutiert.
- Bei den MySQL-Berechtigungen wurde festgestellt, dass der Benutzer
c3_ballon_paxsowohl für'172.24.0.1'als auch für'%'korrekt konfiguriert war. - Es zeigte sich, dass Verbindungen aus dem Container (als 172.24.0.1 erkannt) Zugriff verweigert wurden, wenn die Zugriffsrechte nicht korrekt gesetzt waren.
3. Detaillierte Lösungsansätze im Bereich Firewall und iptables
-
Ursprünglicher Ansatz mit iptables:
- Regeln in der INPUT-Kette wurden mit
iptables -I INPUTeingefügt:- Allow-Regeln für 127.0.0.1, 142.132.249.241, 172.17.0.0/16, 172.22.0.0/16
- Anschließend eine DROP-Regel mit
iptables -A INPUT -p tcp --dport 5432 -j DROP
- Ergebnis:
nmapzeigte Port 5432 weiterhin als offen.- Telnet-Tests bestätigten, dass der Port nicht blockiert war.
- Regeln in der INPUT-Kette wurden mit
-
Erweiterter Ansatz mit Berücksichtigung der DOCKER-USER-Kette:
- Es wurde erkannt, dass Docker eigene Regeln in der DOCKER-USER-Kette erstellt.
- Das Skript wurde erweitert, um auch in der DOCKER-USER-Kette:
- Bestehende Regeln für Port 5432 zu löschen.
- Allow-Regeln für die definierten Quell-IP-Bereiche einzufügen.
- Eine abschließende DROP-Regel für alle übrigen Verbindungen zu setzen.
- Beispiel-Skript:
#!/bin/bash set -e echo "Flush der DOCKER-USER-Kette für Port 5432..." iptables -F DOCKER-USER echo "Erlaube in DOCKER-USER-Verbindungen von erlaubten Quellen zu Port 5432..." iptables -I DOCKER-USER 1 -p tcp -s 127.0.0.1 --dport 5432 -j ACCEPT iptables -I DOCKER-USER 1 -p tcp -s 142.132.249.241 --dport 5432 -j ACCEPT iptables -I DOCKER-USER 1 -p tcp -s 172.17.0.0/16 --dport 5432 -j ACCEPT iptables -I DOCKER-USER 1 -p tcp -s 172.22.0.0/16 --dport 5432 -j ACCEPT echo "Setze allgemeine DROP-Regel in DOCKER-USER für Port 5432 (alle anderen Verbindungen) ..." iptables -A DOCKER-USER -p tcp --dport 5432 -j DROP - Ergebnis:
- Trotz dieser Maßnahmen zeigte
iptables -L DOCKER-USERdie Allow-Regeln gefolgt von einer DROP-Regel. - Externe Scans (nmap, telnet) zeigten jedoch weiterhin den Port 5432 als offen.
- Trotz dieser Maßnahmen zeigte
-
Problemdiagnose und Erkenntnis:
- Es wurde erkannt, dass die Allow-Regel für die öffentliche IP (142.132.249.241) möglicherweise externen Traffic erlaubt, da diese IP auch von externen Quellen als Quell-IP erscheinen kann.
- Letztlich stellte sich heraus, dass das Problem gelöst werden konnte, indem man den Quellport nicht angab, sondern nur den Zielport filterte.
- Die endgültige Lösung bestand darin, die Regel ohne Quellangabe zu setzen, sodass alle Verbindungen zu Port 5432 blockiert werden, außer denjenigen, die ausdrücklich intern erlaubt sind.
4. Andere Lösungsansätze und Provider-Firewall
-
Hetzner-Firewall:
- Es wurde vorgeschlagen, die Hetzner-Provider-Firewall zu nutzen.
- Idee: Auf Netzwerkebene (bei Hetzner) die unerwünschten DB-Ports (5432, 3306) zu blockieren, sodass der Server von außen geschützt ist.
- Vorteil: Weniger interne Regeln, geringeres Risiko für Fehler.
- Herausforderung: Die Hetzner-Firewall filtert nur den externen Traffic; interner Traffic (z. B. aus dem Docker-Netz) bleibt unberührt.
- In der Tat konnte die Hetzner-Firewall für 5432 so konfiguriert werden, dass der Port als "discard" markiert wird, was letztlich dazu führte, dass nmap und telnet den Port nicht mehr als offen zeigten.
-
Fazit zu Firewall-Ansätzen:
- Das Zusammenspiel zwischen Docker, UFW/iptables und der Provider-Firewall ist komplex.
- Die finale Erkenntnis war, dass weniger Regeln und der Einsatz einer Provider-Firewall oft zu weniger Problemen führen.
- Bei Hetzner konnte man den DB-Port extern sperren und somit den Zugriff wirksam blockieren, während interne Verbindungen (z. B. WikiJS) weiterhin funktionierten.
5. Weitere Probleme und deren Lösung
-
Mailqueue-Problematik:
- Die Mailqueue wuchs an, weil Postfix E-Mails annahm, diese aber nicht an die Remote-Server weiterleiten konnte.
- Fehlermeldung:
delivery temporarily suspended: conversation with isp.rootgemeinschaft.de[private/dovecot-lmtp] timed out while receiving the initial server greeting - Ursachen:
- LMTP-Kommunikation zwischen Postfix und Dovecot funktionierte nicht richtig.
- Timeout-Probleme, eventuell verursacht durch Firewall- oder Ressourceneinstellungen.
- Lösungsansätze:
- Überprüfung der Dovecot LMTP-Konfiguration.
- Anpassung von Timeout-Werten in Postfix (z. B.
lmtp_connection_timeout). - Sicherstellen, dass der LMTP-Socket (private/dovecot-lmtp) korrekt angelegt und erreichbar ist.
- Letztendlich konnte das Problem behoben werden, sodass die Mailqueue sich leerte.
-
PHP-Version und Fehlermeldungen:
- Ein weiteres Problem war, dass die Anwendung keine Fehlermeldungen mehr anzeigte.
- Ursache: Die PHP-Version war nicht korrekt konfiguriert.
- Lösung:
- Umstellung auf die alte PHP7.4 für die Webanwendung, was dazu führte, dass Fehlermeldungen wieder korrekt angezeigt wurden.
- Erkenntnis: Manchmal muss man einen Schritt zurückgehen und andere Komponenten (wie PHP-Versionen) prüfen.
6. Schlüsselerkenntnisse und Lessons Learned
-
Regelreihenfolge ist entscheidend:
- Firewall-Regeln werden von oben nach unten abgearbeitet. Eine falsch platzierte Allow-Regel kann DROP-Regeln unwirksam machen.
-
Docker und externe Firewalls:
- Docker erzeugt eigene iptables-Regeln, die das Verhalten beeinflussen können.
- Die DOCKER-USER-Kette ist oft der richtige Ort, um externe Verbindungen zu blockieren.
-
Provider-Firewalls nutzen:
- Die Hetzner-Firewall bietet eine effektive Möglichkeit, unerwünschten Traffic auf Netzwerkebene zu blockieren, wodurch die interne Konfiguration vereinfacht wird.
-
Interne vs. externe Verbindungen:
- Unterschiedliche Quell-IP-Adressen können zu unerwarteten Ergebnissen führen (z. B. wenn externe Anfragen als von der eigenen öffentlichen IP erscheinen).
-
Kleinste Details können entscheidend sein:
- Die Angabe des Quellports in iptables-Regeln kann den Unterschied machen.
- Letztlich hat das Entfernen der Quellport-Angabe dazu geführt, dass der Port 5432 korrekt blockiert wird.
-
Iterativer Ansatz:
- Mehrere Lösungsansätze wurden ausprobiert (manuelle iptables-Skripte, UFW, Provider-Firewall).
- Manchmal muss man alte Regeln löschen und neu anordnen, um das gewünschte Verhalten zu erreichen.
-
Fehlersuche auf mehreren Ebenen:
- Probleme traten nicht nur bei der Firewall auf, sondern auch bei der Anwendung (PHP-Version) und der LMTP-Kommunikation zwischen Postfix und Dovecot.
- Eine umfassende Überprüfung aller Komponenten ist notwendig.
7. Die schlussendliche Lösung
-
Für die DB-Zugriffe:
- Firewall-Regeln wurden so konfiguriert, dass nur interne Zugriffe (127.0.0.1 und Docker-Subnetze) auf Port 5432 erlaubt sind.
- Die Hetzner-Firewall wurde genutzt, um externe Zugriffe auf die DB-Ports effektiv zu blockieren.
- Die entscheidende Erkenntnis war, dass die Angabe des Quellports in iptables-Regeln nicht nötig ist – nur der Zielport muss gefiltert werden.
-
Für den E-Mail-Versand:
- Postfix und Dovecot wurden so konfiguriert, dass die LMTP-Kommunikation funktioniert und Timeouts vermieden werden.
- Anpassungen an Timeout-Einstellungen und die Überprüfung des LMTP-Sockets sorgten dafür, dass die Mailqueue sich leerte.
-
Für die PHP-Anwendung:
- Durch die Rückkehr zur alten PHP7.4 wurde sichergestellt, dass Fehlermeldungen korrekt angezeigt werden, was die Diagnose von Problemen erleichterte.
-
Zusammenfassung der Endlösung:
- Externe DB-Ports (5432) wurden auf Netzwerkebene (via Hetzner-Firewall) blockiert.
- Interne Zugriffe auf die DB (über 127.0.0.1 und Docker) wurden explizit erlaubt.
- Die E-Mail-Dienste wurden so konfiguriert, dass sie zuverlässig arbeiten und die Mailqueue sich nicht weiter aufbaut.
- Fehler in der Anwendung (fehlende Fehlermeldungen) wurden durch die richtige PHP-Version behoben.
- Insgesamt wurde ein stabiler Zustand erreicht, der den Sicherheitsanforderungen (z. B. BSI-Empfehlungen) entspricht.
8. Schlusswort
-
Flexibilität und Geduld:
Es wurde viel experimentiert, getestet und schrittweise optimiert. Manchmal muss man mehrere Lösungsansätze durchspielen, bevor das richtige Ergebnis erreicht wird. -
Systemübergreifende Betrachtung:
Probleme können an vielen Stellen auftreten – nicht nur in der Firewall, sondern auch in der Anwendung, im Netzwerk, in den Container-Regeln und in den Provider-Einstellungen. Ein ganzheitlicher Ansatz ist hier entscheidend. -
Weniger ist mehr:
Der schlussendliche Erfolg beruhte auch darauf, auf komplexe, fehleranfällige interne Regeln zu verzichten und stattdessen die Provider-Firewall (bei Hetzner) zu nutzen. -
Rückblick:
„Man darf den Quellport nicht angeben“ wurde zur entscheidenden Erkenntnis, die letztlich half, Port 5432 korrekt zu blockieren. -
Ausblick:
Auch wenn aktuell alles funktioniert, bleibt es wichtig, die Systeme regelmäßig zu überwachen und bei zukünftigen Änderungen erneut eine gründliche Analyse durchzuführen.
9. Danksagung und Erkenntnisse
- Danke an alle, die an den Lösungsansätzen beteiligt waren – manchmal hilft es, mehrere Perspektiven zu betrachten.
- Die wichtigste Erkenntnis: Schritt für Schritt und iterativ vorgehen.
- „Wir werden dem Schwein schon kriegen, auch wenn ihm noch so quiekt!“ – Ein Spruch, der treffend beschreibt, dass man manchmal hartnäckig bleiben muss, bis alles passt.
Ende der Retrospektive