Die Liste der offenen Ports ist die Liste der Wege zu Ihrem Server. Alles Übrige — Firewalls, WAFs, Angriffserkennung — baut darauf auf. Deshalb steht „was lauscht hier“ in jedem Audit an erster Stelle, und deshalb liefert genau diese Prüfung am häufigsten ein unangenehmes Ergebnis: Die Hälfte des Gefundenen wurde nicht von Ihnen geöffnet, sondern vom Installationsprogramm irgendeines Pakets.

Die Ausgabe lesen

sudo ss -tulpn

Die Schalter: t für TCP, u für UDP, l nur lauschende, p der Prozess, n Zahlen bleiben Zahlen. Ohne sudo bleibt die Prozessspalte leer, und die Übung verliert ihren Sinn.

Entscheidend ist die Spalte Local Address:Port, und der Unterschied dort ist grundsätzlich:

  • 127.0.0.1:3306 — der Dienst ist nur von der Maschine selbst erreichbar. Das ist gut;
  • 0.0.0.0:3306 — von jeder IPv4-Adresse, also aus dem Internet. Das ist zu prüfen;
  • [::]:3306 — dasselbe für IPv6. Eine eigene Zeile, die regelmäßig übersehen wird;
  • 203.0.113.25:443 — auf einer bestimmten Adresse, meist beabsichtigt.

Zu jeder Zeile mit 0.0.0.0 oder [::] stellen Sie dann eine Frage: Soll ein Fremder das erreichen können? Für 80 und 443 lautet die Antwort ja. Für fast alles andere nein.

Die üblichen Funde

Redis, Port 6379. Die gefährlichste Zeile überhaupt. Standardmäßig verlangt Redis kein Passwort, und seine Befehle erlauben es, eine Datei auf die Platte zu schreiben — also einen fremden Schlüssel in authorized_keys. Zwischen dem Erscheinen von Redis auf einer öffentlichen Adresse und seiner Nutzung vergehen Stunden, manchmal weniger. Prüfen Sie bind 127.0.0.1 und protected-mode yes in der Konfiguration.

Memcached, 11211/UDP. Selbst wenn darin nichts Wertvolles liegt, wird Ihr Server zum Verstärker fremder Angriffe — und die Beschwerde kommt vom Hoster.

MySQL und PostgreSQL, 3306 und 5432. Ein Passwort gibt es, aber dagegen wird ununterbrochen geraten, und Datenbankversionen werden seltener aktualisiert als einem lieb ist. Nach außen müssen sie fast nie: Die Anwendung läuft auf derselben Maschine, und für Ihre Arbeit genügt ein SSH-Tunnel.

Elasticsearch 9200, MongoDB 27017. Historisch ohne Authentifizierung ab Werk. Öffentliche Instanzen davon sind eine stete Quelle von Nachrichten über Datenlecks.

Docker-API, 2375. Ein offener Docker-Steuerport ist Root auf dem Host ganz ohne Passwort. Er erscheint meist nach Experimenten mit dem Fernzugriff auf Docker.

Verwaltungspanels und phpMyAdmin auf ihren Ports: 8080, 8083, 10000. Nicht, dass man sie nie öffnen dürfte — aber genau sie ziehen den Großteil der Versuche auf sich.

Beim Dienst beheben, nicht bei der Firewall

Der Drang, jeden Fund mit einer UFW-Regel zu schließen, ist verständlich, aber das ist die zweite Linie, nicht die erste. Eine Regel lässt sich versehentlich löschen, eine Firewall zum Debuggen vorübergehend abschalten, und Docker veröffentlicht Ports gänzlich an UFW vorbei. Eine Bindungseinstellung in der Konfiguration des Dienstes überlebt all das:

  • MySQL/MariaDB — bind-address = 127.0.0.1;
  • PostgreSQL — listen_addresses = 'localhost';
  • Redis — bind 127.0.0.1 ::1;
  • Docker Compose — Veröffentlichung als "127.0.0.1:5432:5432".

Die Firewall kommt als Absicherung obendrauf, nicht an dessen Stelle.

Den Prozess finden, wenn unklar

ss nennt Name und PID. Danach:

sudo systemctl status <pid>
sudo lsof -i :8080

Der erste Befehl nennt die systemd-Unit, zu der der Prozess gehört — meist genug, um zu verstehen, was es ist und ob es gebraucht wird. Ein unbekannter Prozess, der auf einem hohen Port lauscht und außerhalb der Systemverzeichnisse gestartet wurde — etwa aus /tmp oder /dev/shm —, ist keine Konfigurationsfrage mehr, sondern Anlass für eine eigene Untersuchung.

Die Prüfung von außen ist Pflicht

ss beantwortet „was lauscht“, nicht „was ist erreichbar“. Dazwischen stehen Firewall, NAT und die Regeln des Hosters. Die einzige ehrliche Antwort liefert ein Scan von einer anderen Maschine:

nmap -Pn -p- 203.0.113.25
nmap -Pn -p- -6 2001:db8::1

Lassen Sie den zweiten Befehl nicht aus: Fast jeder VPS hat eine IPv6-Adresse, ihre Regeln werden getrennt geschrieben, und der Dienst lauscht auf beiden Protokollversionen zugleich.

Das ist keine einmalige Prüfung

Die Liste der offenen Ports ändert sich von selbst. Sie haben ein Paket installiert, es brachte einen Dienst mit und öffnete einen Port. Sie haben ein Panel aktualisiert, es stellte eine Voreinstellung wieder her. Sie haben einen Container gestartet, er veröffentlichte einen Port an der Firewall vorbei. Eine einmalige Prüfung steht für den heutigen Tag und für nichts sonst.

Der Wert liegt nicht in der Liste selbst, sondern in ihren Veränderungen: Ein neuer Port, der gestern nicht da war, ist ein kurzes und sehr aussagekräftiges Signal. Genau so lohnt es sich, das zu beobachten — als Schnappschuss mit Verlauf und nicht als aus dem Gedächtnis rekonstruierte ss-Ausgabe. Die Demo-Seite unten zeigt genau das.