Jak zmienić port SSH w systemach RHEL, Rocky i AlmaLinux
Zmiana portu SSH wymaga konfiguracji firewalld, polityki SELinux oraz pliku sshd_config. Dowiedz się, jak wykonać te kroki, aby uniknąć błędu Permission denied lub blokady.
Dlaczego zmiana portu SSH wymaga tutaj trzech kroków
Aby zmienić port SSH w systemach Rocky Linux, AlmaLinux, CentOS Stream lub Fedora, jedna edycja nie wystarczy. Trzy oddzielne systemy decydują o tym, czy połączenie na nowym porcie będzie działać. firewalld decyduje, czy pakiet dotrze do maszyny. SELinux decyduje, czy sshd w ogóle może przypisać się do tego numeru portu. sshd_config określa, o który port prosi daemon. Pominięcie kroku z SELinux spowoduje, że daemon odmówi uruchomienia. Pominięcie kroku z firewalld sprawi, że usługa wystartuje i będzie nasłuchiwać, ale nikt nie uzyska do niej dostępu.
W systemie Ubuntu to samo zadanie wymaga jednej edycji i restartu, ponieważ Ubuntu używa AppArmor zamiast SELinux i nie dostarcza profilu ograniczającego porty, do których może przypisać się sshd. Jeśli ufw jest uruchomiony, wystarczy dodać jedną regułę. Na tym polega cała różnica. Rodzina systemów RHEL dostarczana jest z aktywnym firewalld oraz wymuszającym SELinux w świeżej instalacji, a oba te mechanizmy kontrolują numery portów.
Wykonaj pracę w tej kolejności, aby bieżąca sesja pozostała aktywna na każdym etapie:
- Otwórz nowy port w firewalld, pozostawiając port 22 otwarty na ten moment.
- Dodaj etykietę SELinux dla nowego portu za pomocą
semanage. - Ustaw port w konfiguracji sshd.
- Zrestartuj
sshd, a następnie zaloguj się na nowy port z drugiego terminala przed zamknięciem pierwszego.
Przed rozpoczęciem znajdź konsolę internetową swojego dostawcy (VNC lub szeregową) i sprawdź, czy możesz się przez nią zalogować. Ta konsola jest drogą powrotną w razie niepowodzenia zmian. Zmiana portu jest jedną z najczęstszych przyczyn, dla których użytkownik traci dostęp do serwera, za który właśnie zapłacił.
Najpierw zainstaluj semanage
semanage to narzędzie służące do edycji ustawień polityki SELinux, a minimalna instalacja Rocky Linux lub AlmaLinux go nie zawiera. Znajduje się ono w pakiecie policycoreutils-python-utils.
sudo dnf install -y policycoreutils-python-utilsUruchomienie polecenia przed zainstalowaniem tego pakietu zwraca sudo: semanage: command not found i jest to moment, w którym wielu czytelników decyduje, że SELinux nie jest zainstalowany i pomija ten krok. SELinux jest zainstalowany. Brakuje jedynie narzędzia do zarządzania. Jeśli składnia dnf jest nowa, odpowiedniki poleceń dnf i apt pozwolą odnieść ją do znanych już rozwiązań.
Wybór portu i weryfikacja jego dostępności
Można użyć dowolnego wolnego portu TCP z zakresu od 1024 do 65535. Przed podjęciem decyzji należy wykonać dwie kontrole:
sudo ss -tlnp | grep -w 2222
sudo semanage port -l | grep -w 2222Pierwsze polecenie sprawdza, czy proces już nasłuchuje na danym numerze. Drugie sprawdza, czy polityka SELinux przypisuje go już do innego typu usługi. Wolny port nie zwraca żadnych wyników w obu przypadkach. Jeśli polityka już go rezerwuje, polecenie semanage port -a w kroku 2 zakończy się błędem ValueError: Port tcp/2222 already defined; rozwiązaniem jest wybór innego numeru.
W całym przewodniku jako przykładu użyto portu 2222. Jest to również pierwszy port, który skanery sprawdzają po porcie 22, dlatego na serwerze produkcyjnym warto wybrać mniej oczywistą wartość.
Krok 1: otwarcie portu w firewalld
sudo firewall-cmd --permanent --add-port=2222/tcp
sudo firewall-cmd --reload
sudo firewall-cmd --list-ports--permanent zapisuje regułę do pliku strefy na dysku i nie modyfikuje działającego firewalla. --reload ładuje konfigurację z dysku do działającego firewalla. Pominięcie przeładowania sprawia, że reguła istnieje, ale nie działa aż do następnego restartu firewalld, co jest jedną z najczęstszych przyczyn pozornego niepowodzenia całej procedury.
Na razie należy pozostawić wpis usługi ssh bez zmian. Ten wpis utrzymuje otwarty port 22 i stanowi zabezpieczenie na czas testów.
Należy również sprawdzić panel sterowania dostawcy. Wielu dostawców hostingu stosuje sieciowy firewall przed VPS, poza systemem operacyjnym, więc port otwarty w firewalld może być nadal blokowany na poziomie nadrzędnym. Podstawowy przewodnik po firewalld dla VPS omawia strefy oraz podział na konfigurację uruchomieniową i trwałą, jeśli ten model jest nowy dla użytkownika.
Krok 2: etykietowanie portu dla SELinux
sudo semanage port -a -t ssh_port_t -p tcp 2222
sudo semanage port -l | grep ssh_port_t-a dodaje nowe przypisanie portu. -t ssh_port_t to typ przypisywany portom SSH. Drugie polecenie wyświetla listę wszystkich portów obsługiwanych przez ssh_port_t, co pozwala potwierdzić dodanie numeru przed wprowadzeniem zmian w demonie.
Dlaczego SELinux blokuje port
SELinux (Security-Enhanced Linux) nadaje każdemu obiektowi w systemie etykietę, a numery portów TCP są obiektami takimi jak każde inne. Demon SSH działa w izolowanej domenie o nazwie sshd_t. Polityka pozwala sshd_t na wiązanie portów TCP z etykietą ssh_port_t, a domyślnie jedynym portem z taką etykietą jest 22. Jeśli demon otrzyma polecenie powiązania z portem 2222, jądro sprawdza etykietę, odnajduje typ przypisany do tego numeru w polityce i odmawia uprawnienia name_bind dla gniazda.
Dlatego ten błąd nie wygląda jak problem z firewallem. Jądro odmawia dostępu, zanim gniazdo nasłuchujące w ogóle powstanie, więc sshd zgłasza błąd i kończy działanie. Problem z firewallem to sytuacja odwrotna: demon działa poprawnie, a pakiety są odrzucane w trakcie próby dotarcia do niego.
getenforce informuje o trybie pracy systemu. W trybie Permissive odmowy są rejestrowane, ale nie są egzekwowane, więc zmiana portu wydaje się działać, dopóki ktoś nie uruchomi setenforce 1 lub system nie zrestartuje się w trybie wymuszania (enforcing). W obu przypadkach należy nadać portowi odpowiednią etykietę. Podstawy SELinux dla serwera szczegółowo omawiają tryby, konteksty i wartości logiczne (booleans). Porty nie są jedynymi obiektami, które powodują ten problem; ta sama polityka blokuje kontenerowi odczyt zamontowanego katalogu hosta, dopóki ścieżka nie otrzyma odpowiedniej etykiety. Dlatego instalacja Docker na systemach Rocky Linux lub AlmaLinux zawiera krok dotyczący SELinux, o którym nie wspominają poradniki dla Ubuntu.
Krok 3: ustawienie portu w konfiguracji sshd
W systemach Rocky Linux 9 i 10, AlmaLinux 9 i 10 oraz bieżących wersjach Fedora, plik /etc/ssh/sshd_config rozpoczyna się od dyrektywy include, dlatego najwłaściwszym miejscem na wprowadzenie zmian jest osobny plik konfiguracyjny (drop-in). Dzięki temu aktualizacje pakietów nie nadpiszą wprowadzonych zmian.
grep -n '^Include' /etc/ssh/sshd_config
echo 'Port 2222' | sudo tee /etc/ssh/sshd_config.d/10-port.conf
sudo sshd -tJeśli grep nie zawiera linii Include, co ma miejsce w Rocky Linux 8 oraz innych starszych obrazach, należy umieścić Port 2222 bezpośrednio w /etc/ssh/sshd_config. Narzędzie sshd -t analizuje całą konfigurację, w tym pliki typu drop-in, i zgłasza błędy składniowe. Wszelkie wykryte błędy należy usunąć przed restartem, ponieważ niepoprawna konfiguracja uniemożliwi ponowne uruchomienie demona.
Dyrektywa Port może wystąpić więcej niż raz, a sshd nasłuchuje na każdym wymienionym porcie. Pozostawienie Port 22 obok Port 2222 przez pierwszy dzień stanowi tanie zabezpieczenie, pod warunkiem pamiętania o późniejszym usunięciu starego portu.
Czy sshd jest uruchamiany przez jednostkę typu socket?
Niektóre obrazy uruchamiają SSH poprzez mechanizm socket activation w systemd, zamiast jako usługę działającą w tle. W takiej konfiguracji systemd zarządza gniazdem nasłuchującym i przekazuje połączenia do sshd, dlatego dyrektywa Port w pliku sshd_config jest całkowicie ignorowana. Przed wykonaniem jakiegokolwiek restartu należy sprawdzić konfigurację:
systemctl is-enabled sshd.socketOdpowiedź enabled oznacza, że port jest zdefiniowany w jednostce typu socket, a nie w sshd_config:
sudo systemctl edit sshd.socket[Socket]
ListenStream=
ListenStream=2222Wymagane jest użycie pustego przypisania ListenStream=. Wartości w plikach typu drop-in sumują się, więc bez wyczyszczenia listy gniazdo będzie nasłuchiwać zarówno na porcie 22, jak i 2222. Zastosuj zmianę za pomocą sudo systemctl daemon-reload, a następnie sudo systemctl restart sshd.socket. Jeśli jednostka jest wyłączona lub nie występuje na serwerze, ta sekcja nie ma zastosowania.
Krok 4: restart, a następnie test z drugiego terminala
sudo systemctl restart sshd
systemctl status sshd
sudo ss -tlnp | grep sshdPozostaw ten terminal otwarty. Nie wylogowuj się z niego. Otwórz drugi terminal na własnej maszynie i połącz się przez nowy port:
ssh -p 2222 youruser@203.0.113.10Zamknij pierwszą sesję dopiero po udanym zalogowaniu w drugiej. Jeśli połączenie nie zadziała, nadal masz dostęp do powłoki, z której możesz cofnąć wszystkie zmiany. Ten nawyk stanowi różnicę między pięciominutową zmianą a popołudniem spędzonym w konsoli dostawcy.
Odrzucenie przez firewall czy blokada SELinux? Jak je rozróżnić
Z perspektywy laptopa obie awarie wyglądają niemal identycznie. Na serwerze różnią się całkowicie.
- Jeśli
systemctl status sshdwskazuje, że jednostka nie uruchomiła się, demon nie otrzymał swojego gniazda. Jest to błąd konfiguracji lub blokada SELinux. - Jeśli jednostka jest aktywna, a
ss -tlnppokazuje, że sshd jest powiązany z nowym portem, demon działa poprawnie, a problem leży na ścieżce sieciowej: firewalld, zewnętrzny firewall dostawcy lub adres i port, z którym nawiązywane jest połączenie.
W przypadku SELinux należy odczytać wpis w dzienniku audit zamiast zgadywać:
sudo ausearch -m AVC -ts recent
sudo journalctl -u sshd -n 50 --no-pagerBlokada name_bind w klasie tcp_socket wskazuje proces w comm="sshd", numer portu w src= oraz etykietę, którą port faktycznie posiada w tcontext=. To ostatnie pole zawiera rozwiązanie. Wartość inna niż ssh_port_t oznacza, że krok 2 nie został zastosowany do używanego portu, co zazwyczaj wynika z literówki w numerze lub błędnego protokołu. Należy zainstalować setroubleshoot-server, jeśli preferowane jest użycie sealert do przekształcenia wpisu w czytelne zdanie.
Komunikat zapisywany przez sam proces sshd, gdy jądro odmawia powiązania z portem, wygląda następująco:
error: Bind to port 2222 on 0.0.0.0 failed: Permission denied.Permission denied na porcie powyżej 1024, gdzie uprawnienia root nie są wymagane do powiązania, jest sygnaturą SELinux. Address already in use w tej samej linii oznacza inny błąd: inny proces zajmuje dany port. Od strony klienta, różnica między connection refused a connection timed out pozwala rozróżnić dwa przypadki sieciowe, ponieważ odmowa oznacza, że pakiet dotarł do hosta, ale nikt nie nasłuchiwał, natomiast przekroczenie czasu oznacza brak jakiejkolwiek odpowiedzi.
Zamknięcie portu 22 i aktualizacja klientów
Gdy kilka logowań na nowy port zakończy się powodzeniem, należy zamknąć port 22:
sudo firewall-cmd --permanent --remove-service=ssh
sudo firewall-cmd --reload
sudo firewall-cmd --list-allEtykietę SELinux dla portu 22 należy pozostawić bez zmian. Wynika ona z polityki podstawowej i nie nadaje żadnych uprawnień, gdy firewall przestaje przepuszczać pakiety.
Następnie należy zaktualizować klientów, ponieważ każde narzędzie zakładające użycie portu domyślnego wymaga teraz konfiguracji. Warto dodać ją raz do ~/.ssh/config na własnej maszynie, zamiast ciągłego wpisywania -p:
Host myvps
HostName 203.0.113.10
Port 2222
User youruserscp, sftp, rsync oraz Ansible odczytują ten plik. Zadania kopii zapasowych, testy monitoringu oraz skrypty cron, w których port 22 jest wpisany na sztywno, nie korzystają z tego pliku, dlatego należy je odnaleźć, póki zmiana jest świeża w pamięci.
Co daje, a czego nie daje zmiana portu
Zmniejsza ona szum w logach. Zautomatyzowane skanery nieustannie atakują port 22, a przeniesienie usługi na inny port usuwa większość tych wpisów z dziennika, co ułatwia dostrzeżenie rzeczywistych zdarzeń. Nie jest to mechanizm bezpieczeństwa. Każdy skaner przeszukujący pełny zakres portów i tak wykryje demona oraz odczyta jego baner wersji. Zmianę portu należy traktować jako porządkowanie systemu, a rzeczywistą ochronę oprzeć na uwierzytelnianiu wyłącznie za pomocą kluczy przy wyłączonym logowaniu hasłem, co krok po kroku opisuje przewodnik po utwardzaniu SSH dla VPS.
Powyższe informacje działają identycznie w obu głównych dystrybucjach typu RHEL rebuild, ponieważ bazują one na tych samych źródłach. Zobacz porównanie Rocky Linux i AlmaLinux, jeśli nadal dokonujesz wyboru między nimi. Istnienie dwóch niemal identycznych systemów wynika z faktu, że CentOS przestał pełnić tę rolę w 2020 roku, co szczegółowo opisano w historii przejścia od Red Hat przez CentOS do Rocky i AlmaLinux. Przed skorzystaniem ze starszych poradników sprawdź, jaką wersję systemu faktycznie posiadasz, używając cat /etc/os-release. Poradniki napisane dla Rocky Linux 8 nadal są wysoko pozycjonowane, a ich kroki dotyczące semanage oraz firewall-cmd pozostają poprawne, jednak Rocky 8 nie posiada linii include sshd_config.d ani jednostki socket, więc część dotycząca sshd w tych przewodnikach nie odpowiada współczesnym systemom.
Należy poinformować fail2ban o nowym porcie
Pakiet fail2ban nie znajduje się w podstawowych repozytoriach. Pochodzi on z EPEL (extra packages for enterprise Linux):
sudo dnf install -y epel-release
sudo dnf install -y fail2ban fail2ban-firewalldPodpakiet fail2ban-firewalld sprawia, że fail2ban zapisuje blokady za pośrednictwem firewalld, co jest pożądane w systemie, w którym firewalld zarządza zestawem reguł.
Domyślne więzienie (jail) sshd ustawia port = ssh, a ta nazwa jest rozwiązywana przez /etc/services na 22. Po wprowadzeniu zmiany więzienie monitoruje port, który nie jest atakowany, więc nie blokuje nikogo, podczas gdy nieudane próby logowania gromadzą się na porcie 2222. Należy ustawić port za pomocą numeru w /etc/fail2ban/jail.local:
[sshd]
enabled = true
port = 2222
backend = systemd
maxretry = 5
bantime = 3600backend = systemd odczytuje nieudane próby logowania z dziennika systemd zamiast z /var/log/secure, co jest bezpieczniejszym wyborem w minimalnej instalacji, gdzie rsyslog może nie być obecny. Uruchom usługę za pomocą sudo systemctl enable --now fail2ban i sprawdź stan więzienia za pomocą sudo fail2ban-client status sshd. Składnia więzienia jest taka sama, jak użyta w konfiguracji fail2ban dla SSH w systemie Ubuntu 24.04. Różnią się jedynie źródło pakietu oraz akcja blokowania.
Aktualizacje zabezpieczeń są ważniejsze niż numer portu
Serwer z przeniesionym portem SSH i czteromiesięcznymi zaległościami w aktualizacjach jest w gorszym stanie niż serwer działający na porcie 22, który aktualizuje się każdej nocy. Włącz automatyczne aktualizacje w tej samej sesji, będąc zalogowanym jako root: automatyczne aktualizacje dnf w systemach Rocky Linux i AlmaLinux opisuje konfigurację timera oraz wybór między samym pobieraniem a automatycznym instalowaniem poprawek. Zainstalowana aktualizacja nie restartuje demonów, które nadal korzystają ze starego kodu, dlatego sprawdzanie, co wymaga restartu usługi lub systemu jest czynnością wartą poświęcenia minuty, gdy w pakiecie aktualizacji znajduje się openssh-server lub biblioteka, z którą jest on powiązany.
FAQ
Dlaczego sshd nie uruchamia się po zmianie portu w systemie Rocky Linux?
Przyczyną jest niemal zawsze brak etykiety portu w SELinux. sshd działa w izolacji w domenie sshd_t, a polityka zezwala mu na powiązanie wyłącznie z portami o etykiecie ssh_port_t, co domyślnie ogranicza się tylko do portu 22. Jądro odrzuca próbę powiązania, więc demon kończy działanie zamiast nasłuchiwać, a journalctl -u sshd zawiera wpis o treści error: Bind to port 2222 on 0.0.0.0 failed: Permission denied.. Należy wykonać polecenie sudo semanage port -a -t ssh_port_t -p tcp 2222 z własnym numerem portu, a następnie zrestartować usługę. Jeśli polecenie semanage nie jest dostępne, należy najpierw zainstalować pakiet policycoreutils-python-utils.
Czy nadal muszę używać semanage, jeśli SELinux działa w trybie permissive?
Tak. W trybie permissive odmowa jest rejestrowana, ale powiązanie z portem jest mimo to dozwolone, więc zmiana wydaje się poprawna. Etykieta nadal jednak nie istnieje. W momencie, gdy ktokolwiek wykona setenforce 1 lub serwer uruchomi się z parametrem SELINUX=enforcing w pliku /etc/selinux/config, sshd przestanie się uruchamiać na tym porcie. Dodanie etykiety wymaga tylko jednego polecenia i eliminuje awarię, która w przeciwnym razie mogłaby wystąpić po kilku tygodniach bez wyraźnej przyczyny.
Port ma etykietę i sshd działa, dlaczego więc połączenie przekracza czas oczekiwania?
Działający demon oznacza, że SELinux nie blokuje operacji, więc pakiet jest odrzucany na etapie docierania do serwera. Należy sprawdzić sudo firewall-cmd --list-ports pod kątem używanego portu i upewnić się, że po dodaniu reguły --permanent wykonano polecenie firewall-cmd --reload, ponieważ trwała reguła sama w sobie nie jest automatycznie stosowana do działającego firewalla. Następnie należy sprawdzić panel sterowania hosta pod kątem zewnętrznego firewalla sieciowego przed VPS. Jest to drugie miejsce, w którym najczęściej dochodzi do blokad, a żadne narzędzie wewnątrz systemu operacyjnego tego nie wykaże.
Jakiego portu użyć zamiast 22?
Dowolnego wolnego portu TCP z zakresu od 1024 do 65535. Należy unikać portów 2222 oraz 22222 na serwerach produkcyjnych, ponieważ skanery sprawdzają je natychmiast po porcie 22. Należy potwierdzić, że numer jest wolny za pomocą sudo ss -tlnp, sprawdzić czy polityka SELinux już go nie zajęła za pomocą sudo semanage port -l oraz pominąć porty przypisane do usług, które mogą zostać zainstalowane w przyszłości. Wysoki, trudny do zapamiętania numer jest odpowiedni, ponieważ wpisuje się go w ~/.ssh/config tylko raz i nie trzeba go więcej wpisywać ręcznie.