SSD Nodes Learn 🎉 VPS ab $5.50/Monat
Anleitungen Matt ConnorVon Matt Connor

SSH-Port mit SELinux und firewalld ändern

So ändern Sie den SSH-Port unter Rocky Linux und AlmaLinux sicher: firewalld, SELinux-Portlabel und sshd_config in der richtigen Reihenfolge, ohne die Sitzung zu verlieren.

Warum die Änderung des SSH-Ports hier drei Schritte erfordert

Um den SSH-Port unter Rocky Linux, AlmaLinux, CentOS Stream oder Fedora zu ändern, reicht eine einzelne Anpassung nicht aus. Drei getrennte Systeme entscheiden jeweils, ob eine Verbindung über den neuen Port funktioniert. firewalld entscheidet, ob das Paket den Rechner erreicht. SELinux entscheidet, ob sshd überhaupt an diese Portnummer gebunden werden darf. sshd_config legt fest, welchen Port der Daemon anfordert. Wird der SELinux-Schritt ausgelassen, verweigert der Daemon den Start. Wird der firewalld-Schritt ausgelassen, startet der Dienst und lauscht, ist aber nicht erreichbar.

Unter Ubuntu besteht dieselbe Aufgabe aus einer Änderung und einem Neustart, weil Ubuntu statt SELinux AppArmor verwendet und kein Profil mitliefert, das die Ports beschränkt, an die sshd gebunden werden darf. Wenn ufw dort aktiv ist, fügen Sie eine Regel hinzu. Das ist der gesamte Unterschied. In der RHEL-Familie laufen firewalld und SELinux bei einer frischen Installation standardmäßig, wobei SELinux den Modus enforcing verwendet. Beide berücksichtigen Portnummern.

Führen Sie die Arbeiten in dieser Reihenfolge durch. Ihre aktuelle Sitzung bleibt dabei über alle Schritte hinweg bestehen:

  1. Öffnen Sie den neuen Port in firewalld, und lassen Sie Port 22 vorerst geöffnet.
  2. Fügen Sie mit semanage das SELinux-Label für den neuen Port hinzu.
  3. Setzen Sie den Port in der sshd-Konfiguration.
  4. Starten Sie sshd neu. Melden Sie sich anschließend von einem zweiten Terminal über den neuen Port an, bevor Sie das erste Terminal schließen.
Ermitteln Sie vor Beginn die Webkonsole Ihres Providers (VNC oder seriell) und prüfen Sie, ob Sie sich darüber anmelden können. Diese Konsole ermöglicht Ihnen den Zugriff, falls die Änderung fehlschlägt. Eine Portänderung gehört zu den häufigsten Gründen dafür, dass sich ein Mieter aus einem Server aussperrt, den er gerade bezahlt hat.

Semanage installieren

semanage ist das Werkzeug zum Bearbeiten der SELinux-Richtlinieneinstellungen. Eine minimale Installation von Rocky Linux oder AlmaLinux enthält es nicht. Es befindet sich in policycoreutils-python-utils.

sudo dnf install -y policycoreutils-python-utils

Wenn Sie den Befehl vor der Installation dieses Pakets ausführen, wird sudo: semanage: command not found ausgegeben. An dieser Stelle gehen viele Leser davon aus, dass SELinux nicht installiert ist, und überspringen den Schritt. SELinux ist installiert. Es fehlt nur das Verwaltungswerkzeug. Wenn die Syntax von dnf für Sie neu ist, ordnet die Befehlsäquivalente für dnf und apt sie den Befehlen zu, die Sie bereits kennen.

Einen Port auswählen und prüfen, ob er bereits verwendet wird

Jeder freie TCP-Port zwischen 1024 und 65535 ist geeignet. Prüfen Sie vor der Auswahl zwei Dinge:

sudo ss -tlnp | grep -w 2222
sudo semanage port -l | grep -w 2222

Der erste Befehl zeigt, ob bereits ein Prozess auf dieser Nummer lauscht. Der zweite zeigt, ob die SELinux-Richtlinie den Port bereits einem anderen Servicetyp zuweist. Bei einem freien Port geben beide Befehle keine Ausgabe zurück. Wenn die Richtlinie den Port bereits beansprucht, schlägt semanage port -a in Schritt 2 mit ValueError: Port tcp/2222 already defined fehl. Wählen Sie dann eine andere Nummer.

In dieser Anleitung wird durchgehend 2222 als Beispiel verwendet. Nach 22 ist dies außerdem der erste Port, den ein Scanner prüft. Wählen Sie auf einem echten Server daher einen weniger offensichtlichen Port.

Schritt 1: Den Port in firewalld öffnen

sudo firewall-cmd --permanent --add-port=2222/tcp
sudo firewall-cmd --reload
sudo firewall-cmd --list-ports

--permanent schreibt die Regel in die Zonendatei auf der Festplatte und ändert die laufende Firewall nicht. --reload lädt die Konfiguration von der Festplatte in die laufende Firewall. Wenn Sie das Neuladen überspringen, ist die Regel zwar vorhanden, hat aber keine Wirkung, bis firewalld neu gestartet wird. Das ist eine der häufigsten Ursachen dafür, dass dieses gesamte Verfahren scheinbar grundlos fehlschlägt.

Lassen Sie den ssh-Diensteintrag vorerst unverändert. Dieser Eintrag hält Port 22 offen und dient als Rückfallebene während des Tests.

Prüfen Sie außerdem die Steuerungsoberfläche Ihres Providers. Viele Hoster betreiben vor der VPS eine Netzwerk-Firewall außerhalb des Betriebssystems. Daher kann ein in firewalld geöffneter Port weiterhin vorgelagert verworfen werden. Der Grundlagenleitfaden zu firewalld für eine VPS erläutert Zonen sowie die Trennung zwischen Laufzeit- und permanenter Konfiguration, falls dieses Modell für Sie neu ist.

Schritt 2: Port für SELinux kennzeichnen

sudo semanage port -a -t ssh_port_t -p tcp 2222
sudo semanage port -l | grep ssh_port_t

-a fügt eine neue Portzuweisung hinzu. -t ssh_port_t ist der Typ, den SSH-Ports verwenden. Der zweite Befehl listet alle Ports auf, die ssh_port_t jetzt abdeckt. So können Sie prüfen, ob Ihre Portnummer übernommen wurde, bevor Sie den Daemon ändern.

Warum SELinux den Port überhaupt blockiert

SELinux (security-enhanced Linux) weist jedem Objekt auf dem System ein Label zu. TCP-Portnummern sind dabei Objekte wie alle anderen. Der SSH-Daemon läuft in einer eingeschränkten Domain namens sshd_t. Die Policy erlaubt sshd_t, TCP-Ports mit dem Label ssh_port_t zu binden. Standardmäßig trägt nur Port 22 dieses Label. Fordert der Daemon Port 2222 an, prüft der Kernel das Label, findet den generischen Typ, den die Policy dieser Portnummer zugewiesen hat, und verweigert die Berechtigung name_bind für den Socket.

Deshalb sieht dieser Fehler nicht wie ein Firewall-Problem aus. Der Kernel verweigert die Anfrage, bevor überhaupt ein Listening-Socket existiert. sshd meldet den Fehler und wird beendet. Bei einem Firewall-Problem ist es umgekehrt: Der Daemon läuft und ist fehlerfrei, aber die Pakete werden auf dem Weg zum Server verworfen.

getenforce zeigt, in welchem Modus sich das System befindet. Im Modus Permissive wird eine Verweigerung protokolliert, aber nicht durchgesetzt. Dadurch scheint die Portänderung zunächst zu funktionieren. Sie schlägt jedoch fehl, sobald jemand setenforce 1 ausführt oder der Server im Enforcing-Modus neu gestartet wird. Beschriften Sie den Port daher unabhängig vom Modus. Der SELinux-Grundlagenleitfaden für Server erläutert Modi, Kontexte und Booleans ausführlich.

Schritt 3: Port in der sshd-Konfiguration festlegen

Unter Rocky Linux 9 und 10, AlmaLinux 9 und 10 sowie aktuellen Fedora-Versionen beginnt /etc/ssh/sshd_config mit einer Include-Zeile. Die saubere Stelle für Ihre Änderung ist daher eine Drop-in-Datei. Paketaktualisierungen überschreiben Ihre Änderung dann nicht.

grep -n '^Include' /etc/ssh/sshd_config
echo 'Port 2222' | sudo tee /etc/ssh/sshd_config.d/10-port.conf
sudo sshd -t

Wenn grep keine Include-Zeile findet, wie es bei Rocky Linux 8 und anderen älteren Images der Fall ist, tragen Sie Port 2222 stattdessen direkt in /etc/ssh/sshd_config ein. sshd -t prüft die gesamte Konfiguration einschließlich der Drop-ins und meldet Syntaxfehler. Beheben Sie alle gemeldeten Fehler, bevor Sie den Dienst neu starten. Eine Konfiguration, die nicht geparst werden kann, verhindert, dass der Daemon wieder startet.

Port kann mehr als einmal vorkommen. sshd lauscht dann auf jedem angegebenen Port. Lassen Sie Port 22 am ersten Tag zusätzlich zu Port 2222 aktiviert. Das ist eine einfache Sicherheitsmaßnahme, solange Sie daran denken, den zusätzlichen Eintrag wieder zu entfernen.

Wird Ihr sshd von einer Socket-Unit gestartet?

Einige Images starten SSH über die Socket-Aktivierung von systemd statt als dauerhaft laufenden Dienst. Wenn dies so eingerichtet ist, verwaltet systemd den Listening-Socket und übergibt Verbindungen an sshd. Die Zeile Port in sshd_config wird dann vollständig ignoriert. Prüfen Sie dies, bevor Sie etwas neu starten:

systemctl is-enabled sshd.socket

Eine Antwort enabled bedeutet, dass der Port in der Socket-Unit und nicht in sshd_config festgelegt ist:

sudo systemctl edit sshd.socket
[Socket]
ListenStream=
ListenStream=2222

Das leere ListenStream= ist erforderlich. Werte werden über Drop-in-Dateien hinweg kumuliert. Ohne eine leere Zuweisung, die die Liste zuerst leert, lauscht der Socket weiterhin sowohl auf 22 als auch auf 2222. Wenden Sie die Änderung mit sudo systemctl daemon-reload an und führen Sie anschließend sudo systemctl restart sshd.socket aus. Wenn die Unit auf Ihrem Server deaktiviert ist oder nicht vorhanden ist, trifft dieser Abschnitt auf Sie nicht zu.

Schritt 4: Neustart durchführen und anschließend von einem zweiten Terminal testen

sudo systemctl restart sshd
systemctl status sshd
sudo ss -tlnp | grep sshd

Lassen Sie dieses Terminal geöffnet. Melden Sie sich dort nicht ab. Öffnen Sie auf Ihrem eigenen Rechner ein zweites Terminal und stellen Sie über den neuen Port eine Verbindung her:

ssh -p 2222 youruser@203.0.113.10

Schließen Sie die erste Sitzung erst, nachdem die zweite Anmeldung funktioniert hat. Falls die Anmeldung nicht funktioniert, haben Sie weiterhin eine Shell, von der aus Sie alle Änderungen rückgängig machen können. Diese Vorgehensweise entscheidet darüber, ob die Änderung in fünf Minuten erledigt ist oder Sie einen Nachmittag in der Provider-Konsole verbringen.

Firewall-Drop oder SELinux-Verweigerung? So unterscheiden Sie die Ursachen

Von Ihrem Laptop aus sehen die beiden Fehler nahezu identisch aus. Auf dem Server unterscheiden sie sich deutlich.

  • Wenn systemctl status sshd anzeigt, dass die Unit fehlgeschlagen ist, hat der Daemon seinen Socket nie erhalten. Ursache ist ein Konfigurationsfehler oder eine SELinux-Verweigerung.
  • Wenn die Unit aktiv ist und ss -tlnp anzeigt, dass sshd am neuen Port gebunden ist, funktioniert der Daemon. Das Problem liegt im Netzwerkpfad: bei firewalld, bei der separaten Firewall des Providers oder bei der verwendeten Adresse beziehungsweise dem verwendeten Port.

Lesen Sie bei SELinux den Audit-Eintrag, statt die Ursache zu vermuten:

sudo ausearch -m AVC -ts recent
sudo journalctl -u sshd -n 50 --no-pager

Eine name_bind-Verweigerung für die Klasse tcp_socket nennt den Prozess in comm="sshd", die Portnummer in src= und das tatsächlich am Port vorhandene Label in tcontext=. Das letzte Feld liefert die Antwort. Jeder Wert außer ssh_port_t bedeutet, dass Schritt 2 auf den verwendeten Port nicht angewendet wurde. Meistens ist die Portnummer falsch geschrieben oder das falsche Protokoll wurde verwendet. Installieren Sie setroubleshoot-server, wenn sealert den Eintrag lieber in einen Satz umwandeln soll.

Die Meldung, die sshd selbst schreibt, wenn der Kernel das Binden verweigert, sieht so aus:

error: Bind to port 2222 on 0.0.0.0 failed: Permission denied.

Permission denied an einem Port über 1024, an den ohne root-Berechtigungen gebunden werden kann, ist das SELinux-Symptom. Address already in use in derselben Zeile weist auf einen anderen Fehler hin: Ein anderer Prozess verwendet den Port bereits. Auf der Clientseite unterscheidet der Unterschied zwischen abgelehnter Verbindung und abgelaufenem Verbindungsversuch die beiden Netzwerkfälle. Eine Ablehnung bedeutet, dass Ihr Paket den Host erreicht hat und dort nichts lauschte. Ein Timeout bedeutet, dass überhaupt keine Antwort eingegangen ist.

Port 22 schließen und Ihre Clients aktualisieren

Sobald mehrere Anmeldungen am neuen Port funktioniert haben, entfernen Sie Port 22:

sudo firewall-cmd --permanent --remove-service=ssh
sudo firewall-cmd --reload
sudo firewall-cmd --list-all

Lassen Sie das SELinux-Label für Port 22 unverändert. Es stammt aus der Basispolicy und gewährt nichts, sobald die Firewall keine Pakete mehr durchlässt.

Passen Sie anschließend die Clients an, da nun jedes Tool, das den Standardport vorausgesetzt hat, entsprechend konfiguriert werden muss. Tragen Sie die Einstellung einmal auf Ihrem eigenen Rechner in ~/.ssh/config ein, anstatt dauerhaft -p einzugeben:

Host myvps
  HostName 203.0.113.10
  Port 2222
  User youruser

scp, sftp, rsync und Ansible lesen diese Datei. Sicherungsaufträge, Monitoring-Prüfungen und cron-Skripte, die Port 22 fest eintragen, tun das nicht. Suchen Sie daher nach diesen Stellen, solange die Änderung noch präsent ist.

Was das Ändern des Ports bewirkt und was nicht

Es reduziert das Logaufkommen. Automatisierte Scanner greifen ständig auf Port 22 zu. Wenn Sie den Dienst auf einen anderen Port verschieben, verschwinden die meisten dieser Zeilen aus dem Journal. Dadurch sind echte Ereignisse leichter zu erkennen. Das ist keine Sicherheitsmaßnahme. Jeder Scanner, der den gesamten Portbereich durchsucht, findet Ihren Daemon und liest dessen Versionsbanner trotzdem aus. Betrachten Sie die Portänderung als Aufräumarbeit. Die eigentliche Absicherung erfolgt durch schlüsselbasierte Authentifizierung bei deaktivierten Kennwortanmeldungen. Der Leitfaden zur SSH-Absicherung eines VPS beschreibt dieses Vorgehen Schritt für Schritt.

Alles oben Beschriebene funktioniert bei beiden großen RHEL-Rebuilds identisch, da sie aus denselben Quellen erstellt werden. Wenn Sie noch zwischen ihnen wählen, lesen Sie den Vergleich Rocky Linux und AlmaLinux im Vergleich. Prüfen Sie vor der Verwendung eines älteren Leitfadens mit cat /etc/os-release, welche Version Sie tatsächlich erhalten haben. Für Rocky Linux 8 erstellte Leitfäden erzielen weiterhin gute Suchrankings. Ihre Schritte semanage und firewall-cmd sind nach wie vor korrekt. Rocky 8 enthält jedoch keine sshd_config.d-Include-Zeile und keine Socket-Unit, die berücksichtigt werden müsste. Daher passt der sshd-Teil dieser Leitfäden nicht zu einem aktuellen System.

fail2ban muss über den neuen Port informiert werden

fail2ban ist nicht in den Basis-Repositories enthalten. Es stammt aus EPEL (Extra Packages for Enterprise Linux):

sudo dnf install -y epel-release
sudo dnf install -y fail2ban fail2ban-firewalld

Das Unterpaket fail2ban-firewalld sorgt dafür, dass fail2ban seine Sperren über firewalld setzt. Das ist auf einem System erforderlich, auf dem firewalld das Regelwerk verwaltet.

Das mitgelieferte sshd-Jail setzt port = ssh. Dieser Name wird über /etc/services in Port 22 aufgelöst. Nach Ihrer Änderung überwacht das Jail einen Port, auf dem keine Angriffe stattfinden. Daher werden keine Angreifer gesperrt, während sich fehlgeschlagene Anmeldeversuche auf Port 2222 ansammeln. Setzen Sie den Port in /etc/fail2ban/jail.local direkt als Zahl:

[sshd]
enabled = true
port = 2222
backend = systemd
maxretry = 5
bantime = 3600

backend = systemd liest die Fehlversuche aus dem Journal und nicht aus /var/log/secure. Das ist bei einer Minimalinstallation die sicherere Wahl, wenn rsyslog möglicherweise nicht vorhanden ist. Starten Sie den Dienst mit sudo systemctl enable --now fail2ban und prüfen Sie das Jail mit sudo fail2ban-client status sshd. Die Syntax des Jails entspricht der in der fail2ban-Konfiguration für SSH unter Ubuntu 24.04. Nur die Paketquelle und die Sperraktion unterscheiden sich.

Patching ist wichtiger als der Port

Ein Server mit einem verlegten SSH-Port und seit vier Monaten nicht installierten Sicherheitsupdates ist schlechter geschützt als ein Server auf Port 22, der sich jede Nacht automatisch aktualisiert. Aktivieren Sie unbeaufsichtigte Updates in derselben Sitzung, solange Sie bereits als root angemeldet sind: automatische dnf-Updates auf Rocky Linux und AlmaLinux beschreibt den Timer sowie die Wahl zwischen dem Herunterladen und dem Installieren der Updates.

FAQ

Warum startet sshd nach der Portänderung unter Rocky Linux nicht?

Fast immer fehlt das SELinux-Portlabel. sshd läuft eingeschränkt in der sshd_t-Domain, und die Policy erlaubt das Binden nur an Ports mit dem Label ssh_port_t. Standardmäßig ist das nur Port 22. Der Kernel verweigert das Binden. Deshalb beendet sich der Daemon, statt auf dem Port zu lauschen. journalctl -u sshd enthält eine Zeile in der Form error: Bind to port 2222 on 0.0.0.0 failed: Permission denied.. Führen Sie sudo semanage port -a -t ssh_port_t -p tcp 2222 mit Ihrer eigenen Portnummer aus und starten Sie den Dienst anschließend neu. Wenn semanage nicht gefunden wird, installieren Sie zuerst policycoreutils-python-utils.

Benötige ich semanage weiterhin, wenn SELinux im permissive-Modus läuft?

Ja. Im permissive-Modus wird die Verweigerung protokolliert, und das Binden wird trotzdem erlaubt. Dadurch sieht es so aus, als hätte die Änderung funktioniert. Das Label fehlt weiterhin. Sobald jemand setenforce 1 ausführt oder der Rechner mit SELINUX=enforcing in /etc/selinux/config startet, kann sshd auf diesem Port nicht mehr gestartet werden. Das Hinzufügen des Labels erfordert einen Befehl und verhindert einen Fehler, der sonst Wochen später ohne erkennbare Ursache auftreten würde.

Der Port ist gelabelt und sshd läuft. Warum läuft meine Verbindung trotzdem in einen Timeout?

Ein laufender Daemon bedeutet, dass SELinux den Zugriff zulässt. Das Paket wird also auf dem Weg zum Server verworfen. Prüfen Sie sudo firewall-cmd --list-ports für Ihren Port. Stellen Sie außerdem sicher, dass Sie firewall-cmd --reload nach der --permanent-Regel ausgeführt haben. Eine dauerhafte Regel allein wird niemals auf die laufende Firewall angewendet. Prüfen Sie anschließend im Control Panel Ihres Hosts, ob sich vor dem VPS eine separate Netzwerk-Firewall befindet. Dort werden Verbindungen ebenfalls häufig blockiert. Innerhalb des Betriebssystems ist davon nichts zu sehen.

Welchen Port sollte ich anstelle von 22 verwenden?

Jeden freien TCP-Port von 1024 bis 65535. Verwenden Sie auf einem realen Server nicht 2222 oder 22222, da Scanner diese Ports unmittelbar nach 22 testen. Prüfen Sie mit sudo ss -tlnp, ob die Nummer frei ist. Prüfen Sie mit sudo semanage port -l, ob die SELinux-Policy den Port nicht bereits beansprucht. Vermeiden Sie außerdem Ports, die einem Dienst zugewiesen sind, den Sie später möglicherweise installieren. Eine hohe, schwer merkbare Nummer ist unproblematisch. Sie tragen sie einmal in ~/.ssh/config ein und müssen sie danach nicht mehr eingeben.