SSH-Port mit SELinux und firewalld ändern
Ändern Sie den SSH-Port unter Rocky Linux oder AlmaLinux sicher: firewalld-Regel, SELinux-Portlabel und sshd_config in der richtigen Reihenfolge.
Warum das Ändern 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 separate Systeme entscheiden jeweils darüber, ob eine Verbindung am 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 Anpassung 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 dort ufw läuft, 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 beziehungsweise im Enforcing-Modus, und beide berücksichtigen Portnummern.
Führen Sie die Arbeiten in dieser Reihenfolge durch. Ihre aktuelle Sitzung bleibt dabei in jedem Schritt bestehen:
- Öffnen Sie den neuen Port in firewalld. Lassen Sie Port 22 zunächst geöffnet.
- Fügen Sie mit
semanagedas SELinux-Label für den neuen Port hinzu. - Setzen Sie den Port in der sshd-Konfiguration.
- Starten Sie
sshdneu. Melden Sie sich anschließend von einem zweiten Terminal über den neuen Port an, bevor Sie das erste Terminal schließen.
Suchen Sie vor dem Start 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 erneuten Zugriff, falls die Änderung fehlschlägt. Eine Portänderung ist einer der häufigsten Gründe dafür, dass sich ein Benutzer aus einem Server aussperrt, den er gerade bezahlt hat.
Zuerst 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-utilsWenn Sie den Befehl vor der Installation dieses Pakets ausführen, erhalten Sie sudo: semanage: command not found. An dieser Stelle gehen viele Leser davon aus, dass SELinux nicht installiert ist, und überspringen den Schritt. SELinux ist installiert. Es fehlt lediglich das Verwaltungswerkzeug. Wenn Ihnen die dnf-Syntax noch nicht vertraut ist, ordnet der Vergleich der dnf- und apt-Befehle sie den Ihnen bereits bekannten Befehlen zu.
Einen Port auswählen und prüfen, ob er bereits verwendet wird
Jeder freie TCP-Port von 1024 bis 65535 ist geeignet. Prüfen Sie vor der Festlegung zwei Punkte:
sudo ss -tlnp | grep -w 2222
sudo semanage port -l | grep -w 2222Der erste Befehl zeigt, ob bereits ein Prozess auf dieser Portnummer lauscht. Der zweite zeigt, ob die SELinux-Richtlinie den Port bereits einem anderen Servicetyp zuweist. Ein freier Port liefert bei beiden Befehlen keine Ausgabe. 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 in diesem Fall eine andere Portnummer.
In dieser Anleitung wird durchgehend 2222 als Beispiel verwendet. Nach 22 ist dies außerdem der erste Port, den ein Scanner ausprobiert. Verwenden Sie auf einem realen Server daher eine weniger offensichtliche Portnummer.
Schritt 1: 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 dem Datenträger und ändert die laufende Firewall nicht. --reload lädt die Konfiguration vom Datenträger 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 Dienst-Eintrag ssh vorerst unverändert. Dieser Eintrag hält Port 22 offen und dient beim Testen als Fallback.
Prüfen Sie auch das Control Panel 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 firewalld-Grundlagenleitfaden für eine VPS behandelt Zonen sowie die Trennung zwischen Laufzeit- und dauerhafter Konfiguration, falls dieses Modell für Sie neu ist.
Schritt 2: Den 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 Portzuordnung hinzu. -t ssh_port_t ist der Typ, den SSH-Ports verwenden. Der zweite Befehl listet alle Ports auf, die ssh_port_t jetzt umfasst. 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 im 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 zu binden, die mit ssh_port_t gelabelt sind. Standardmäßig trägt nur Port 22 dieses Label. Fordern Sie den Daemon auf, Port 2222 zu binden, prüft der Kernel das Label, ermittelt 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 beendet sich. Bei einem Firewall-Problem ist es umgekehrt: Der Daemon läuft fehlerfrei, und die Pakete werden auf dem Weg zum Server verworfen.
getenforce zeigt, in welchem Modus sich das System befindet. In Permissive wird eine Verweigerung protokolliert, aber nicht durchgesetzt. Dadurch scheint die Portänderung zu funktionieren. Sie schlägt jedoch fehl, sobald jemand setenforce 1 ausführt oder das System im Enforcing-Modus neu startet. Labeln Sie den Port unabhängig davon. Der SELinux-Grundlagenleitfaden für Server behandelt Modi, Kontexte und Booleans ausführlich. Ports sind nicht die einzigen Objekte, bei denen dieses Problem auftritt. Dieselbe Policy verhindert, dass ein Container ein eingebundenes Host-Verzeichnis liest, bis der Pfad neu gelabelt wurde. Deshalb enthält die Docker-Installation unter Rocky Linux oder AlmaLinux einen SELinux-Schritt, der in Ubuntu-Anleitungen nicht erwähnt wird.
Schritt 3: Den 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. Daher ist eine Drop-in-Datei der passende Ort für die Änderung. Bei Paketaktualisierungen kommt es dann nicht zu Konflikten mit Ihrer Anpassung.
grep -n '^Include' /etc/ssh/sshd_config
echo 'Port 2222' | sudo tee /etc/ssh/sshd_config.d/10-port.conf
sudo sshd -tWenn grep keine Zeile mit Include findet, was unter Rocky Linux 8 und anderen älteren Images der Fall ist, tragen Sie Port 2222 stattdessen direkt in /etc/ssh/sshd_config ein. sshd -t analysiert die gesamte Konfiguration einschließlich der Drop-ins und meldet Syntaxfehler. Beheben Sie alle gemeldeten Fehler vor dem Neustart. Eine Konfiguration, die nicht analysiert werden kann, führt dazu, dass der Daemon nicht wieder startet.
Port kann mehr als einmal vorkommen. sshd lauscht dann an jedem aufgeführten Port. Lassen Sie Port 22 am ersten Tag zusätzlich zu Port 2222 aktiviert, um eine einfache Rückfallebene zu haben. Denken Sie daran, 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 und nicht als dauerhaft laufenden Dienst. Wenn dies so eingerichtet ist, verwaltet systemd den Listening-Socket und übergibt die Verbindungen an sshd. Daher wird die Zeile Port in sshd_config vollständig ignoriert. Prüfen Sie dies, bevor Sie etwas neu starten:
systemctl is-enabled sshd.socketEine 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=2222Das alleinstehende ListenStream= ist erforderlich. Werte werden über Drop-ins hinweg akkumuliert. Ohne eine leere Zuweisung zum vorherigen Leeren der Liste 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 sshdLassen 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.10Schließen Sie die erste Sitzung erst, nachdem die zweite Anmeldung funktioniert hat. Falls die Anmeldung fehlschlägt, verfügen Sie weiterhin über eine Shell, von der aus Sie alle Änderungen rückgängig machen können. Diese Vorgehensweise entscheidet darüber, ob eine Änderung fünf Minuten oder einen ganzen Nachmittag in der Provider-Konsole dauert.
Firewall-Drop oder SELinux-Verweigerung? So unterscheiden Sie die Fälle
Vom Laptop aus sehen die beiden Fehler nahezu identisch aus. Auf dem Server sehen sie völlig unterschiedlich aus.
- Wenn
systemctl status sshdanzeigt, 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 -tlnpanzeigt, dass sshd am neuen Port gebunden ist, funktioniert der Daemon. Das Problem liegt im Netzwerkpfad: bei firewalld, der separaten Firewall des Providers oder bei der von Ihnen verwendeten Adresse und dem verwendeten Port.
Lesen Sie bei SELinux den Audit-Datensatz, statt die Ursache zu erraten:
sudo ausearch -m AVC -ts recent
sudo journalctl -u sshd -n 50 --no-pagerEine name_bind-Verweigerung für die Klasse tcp_socket nennt den Prozess in comm="sshd", die Portnummer in src= und das Label, das der Port tatsächlich trägt, in tcontext=. Das letzte Feld enthält die Antwort. Jeder Wert außer ssh_port_t bedeutet, dass Schritt 2 nicht auf den verwendeten Port angewendet wurde. Meistens liegt ein Tippfehler in der Portnummer oder das falsche Protokoll vor. Installieren Sie setroubleshoot-server, wenn sealert den Datensatz lieber in einen vollständigen Satz umwandeln soll.
Die Meldung, die sshd selbst ausgibt, 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 oberhalb von 1024, an den kein root-Recht zum Binden erforderlich ist, ist das SELinux-Signaturmerkmal. Address already in use in derselben Zeile bezeichnet einen anderen Fehler: Ein anderer Prozess belegt den Port. Von der Clientseite aus unterscheidet der Unterschied zwischen „Verbindung abgelehnt“ und „Zeitüberschreitung der Verbindung“ die beiden Netzwerkfälle: Eine Ablehnung bedeutet, dass Ihr Paket den Host erreicht hat und dort nichts lauschte. Eine Zeitüberschreitung bedeutet, dass überhaupt keine Antwort einging.
Port 22 schließen und Clients aktualisieren
Nachdem mehrere Anmeldungen am neuen Port erfolgreich waren, entfernen Sie Port 22:
sudo firewall-cmd --permanent --remove-service=ssh
sudo firewall-cmd --reload
sudo firewall-cmd --list-allLassen Sie das SELinux-Label für Port 22 unverändert. Es stammt aus der Basispolicy und gewährt nichts mehr, sobald die Firewall keine Pakete mehr an diesen Port durchlässt.
Passen Sie anschließend die Clients an, da jedes Tool, das den Standardport voraussetzt, nun entsprechend konfiguriert werden muss. Tragen Sie die Einstellung einmal auf Ihrem eigenen Rechner in ~/.ssh/config ein, statt dauerhaft -p einzugeben:
Host myvps
HostName 203.0.113.10
Port 2222
User youruserscp, sftp, rsync und Ansible lesen diese Datei. Sicherungsaufträge, Überwachungsprüfungen und cron-Skripte mit fest eingetragenem Port 22 berücksichtigen sie jedoch nicht. Suchen Sie diese Stellen daher, solange die Änderung noch präsent ist.
Was die Portänderung bewirkt und was nicht
Sie reduziert das Lograuschen. 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 lassen sich tatsächliche Ereignisse leichter erkennen. Die Änderung 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 über die Authentifizierung ausschließlich mit Schlüsseln und deaktivierte Passwortanmeldungen. Der Leitfaden zur SSH-Härtung eines VPS beschreibt dieses Vorgehen Schritt für Schritt.
Alles oben Beschriebene funktioniert bei den beiden großen RHEL-Rebuilds identisch, da sie aus denselben Quellen erstellt werden. Wenn Sie noch zwischen ihnen wählen, lesen Sie Rocky Linux und AlmaLinux im Vergleich. Es gibt überhaupt zwei nahezu identische Rebuilds zur Auswahl, weil CentOS 2020 aufgehört hat, ein solcher zu sein. Die vollständige Entwicklung wird in der Geschichte von Red Hat über CentOS zu Rocky und AlmaLinux beschrieben. Prüfen Sie mit cat /etc/os-release, welche Version Ihnen tatsächlich bereitgestellt wurde, bevor Sie einem älteren Leitfaden folgen. Für Rocky Linux 8 geschriebene Anleitungen erzielen weiterhin gute Suchergebnisse. Ihre Schritte semanage und firewall-cmd sind weiterhin korrekt. Rocky 8 enthält jedoch keine sshd_config.d-Include-Zeile und keine Socket-Unit. Der Abschnitt zum sshd dieser Anleitungen passt daher 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-firewalldDas Unterpaket fail2ban-firewalld veranlasst fail2ban, seine Bans über firewalld zu setzen. Das ist auf einem System erforderlich, auf dem firewalld das Regelwerk verwaltet.
Das standardmäßige sshd-Jail setzt port = ssh. Dieser Name wird über /etc/services in Port 22 aufgelöst. Nach Ihrer Änderung überwacht das Jail einen Port, den niemand angreift. Daher werden keine IP-Adressen gebannt, während sich fehlgeschlagene Anmeldungen auf Port 2222 ansammeln. Setzen Sie den Port als Nummer in /etc/fail2ban/jail.local:
[sshd]
enabled = true
port = 2222
backend = systemd
maxretry = 5
bantime = 3600backend = systemd liest die fehlgeschlagenen Anmeldungen aus dem Journal statt aus /var/log/secure. Das ist bei einer minimalen Installation 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 derjenigen in der fail2ban-Konfiguration für SSH unter Ubuntu 24.04. Nur die Paketquelle und die Ban-Aktion unterscheiden sich.
Patchen ist wichtiger als der Port
Ein Server mit verlegtem SSH-Port und seit vier Monaten nicht installierten Sicherheitsupdates ist schlechter geschützt als ein Server auf Port 22, der sich jede Nacht selbst 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 und die Wahl zwischen dem Herunterladen und dem Installieren der Updates. Ein installiertes Update startet Daemons, die noch den alten Code ausführen, nicht neu. Daher lohnt sich die Minute, um zu prüfen, welche Dienste noch einen Neustart oder Reboot benötigen, sobald openssh-server oder eine Bibliothek, gegen die es gelinkt ist, mit dem Update installiert wurde.
FAQ
Warum startet sshd nach einer Portänderung unter Rocky Linux nicht?
Fast immer fehlt die SELinux-Portbeschriftung. sshd läuft eingeschränkt in der sshd_t-Domain, und die Policy erlaubt das Binden nur an Ports mit der Beschriftung ssh_port_t, die standardmäßig ausschließlich Port 22 zugewiesen ist. Der Kernel verweigert das Binden. Der Daemon beendet sich daher, statt auf dem Port zu lauschen, und journalctl -u sshd enthält eine Zeile 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 trotzdem zugelassen. Dadurch sieht es so aus, als hätte die Änderung funktioniert. Die Beschriftung fehlt weiterhin. Sobald jemand setenforce 1 ausführt oder der Server mit SELINUX=enforcing in /etc/selinux/config startet, kann sshd auf diesem Port nicht mehr starten. Das Hinzufügen der Beschriftung erfordert einen einzigen Befehl und verhindert einen Fehler, der sonst Wochen später ohne offensichtliche Ursache auftreten würde.
Der Port ist beschriftet 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 auf Ihren Port und stellen Sie sicher, dass Sie firewall-cmd --reload nach der --permanent-Regel ausgeführt haben. Eine dauerhafte Regel allein wird in der laufenden Firewall nie aktiv. 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 dann nichts zu sehen.
Welchen Port sollte ich anstelle von 22 verwenden?
Jeden freien TCP-Port von 1024 bis 65535. Vermeiden Sie auf einem produktiven Server 2222 und 22222, da Scanner diese Ports unmittelbar nach 22 ausprobieren. Prüfen Sie mit sudo ss -tlnp, ob die Nummer frei ist. Prüfen Sie mit sudo semanage port -l, ob die SELinux-Policy sie nicht bereits beansprucht. Verwenden Sie außerdem keinen Port, der einem Dienst zugewiesen ist, den Sie später installieren könnten. Eine hohe, schwer merkbare Nummer ist unproblematisch, weil Sie sie einmal in ~/.ssh/config eintragen und danach nie wieder eingeben müssen.