Czym jest SSH i jak działa połączenie zdalne?
Dowiedz się, jak działa protokół SSH, dlaczego port 22 jest standardem oraz na czym polega różnica między uwierzytelnianiem hasłem a kluczem prywatnym w systemach Linux.
Czym jest SSH?
SSH (secure shell) to protokół służący do logowania się na zdalny komputer i wykonywania na nim poleceń za pośrednictwem szyfrowanego połączenia. Wpisywane dane trafiają na zdalną maszynę, a jej odpowiedź wraca do użytkownika, przy czym nikt monitorujący sieć pomiędzy nimi nie może odczytać przesyłanych informacji. Wynajęty serwer Linux nie posiada podłączonego ekranu ani klawiatury, dlatego SSH jest podstawowym sposobem obsługi takiej maszyny.
Nazwa ta odnosi się do dwóch pojęć. SSH to protokół, opisany w RFC 4251 oraz RFC 4254. OpenSSH to program implementujący ten protokół i jest on używany przez niemal każdy serwer Linux oraz większość laptopów. Gdy ktoś mówi o połączeniu "SSH do serwera", ma na myśli program kliencki ssh na własnym urządzeniu, komunikujący się z programem serwerowym sshd po drugiej stronie.
Problem, który SSH miało rozwiązać
Zdalne logowanie jest znacznie starsze niż SSH. Telnet otwierał zwykłe połączenie TCP na porcie 23 i przesyłał każdy bajt dokładnie tak, jak został wpisany. Nic nie było szyfrowane, wliczając w to hasło użytkownika. Każdy, kto miał dostęp do ruchu sieciowego, mógł je odczytać: osoba w tej samej sieci biurowej lub operator dowolnego routera na trasie połączenia. Rodzina protokołów rlogin miała tę samą słabość i dodatkowo ufała maszynie klienckiej na podstawie jej nazwy, co oznaczało zaufanie do tego, za kogo podawała się sieć.
Tatu Ylönen napisał pierwsze SSH w 1995 roku na Helsinki University of Technology po ataku typu password sniffing w sieci uniwersyteckiej. Projekt zachowuje użyteczną część protokołu telnet, czyli strumień bajtów między terminalem a zdalną powłoką, i dodaje dwie rzeczy, na które telnet nie oferuje rozwiązania: szyfrowanie strumienia oraz dowód, że serwer po drugiej stronie jest tym, z którym zamierzano się połączyć.
Ten drugi element łatwo przeoczyć, a stanowi on połowę istoty SSH. Samo szyfrowanie nie zapewniłoby bezpieczeństwa. Maszyna znajdująca się pomiędzy klientem a serwerem mogłaby przyjąć połączenie, zaszyfrować je poprawnie, odczytać wszystko, co przesyła użytkownik, i przekazać dalej do właściwego serwera. SSH blokuje taką możliwość, nadając każdemu serwerowi stałą tożsamość, zwaną host key, i weryfikując ją przy każdym połączeniu.
Jak działa model klient-serwer
Istnieją dwa programy. Na serwerze sshd działa w trybie ciągłym i oczekuje na połączenia. Na Twoim komputerze ssh inicjuje te połączenia. Są to oddzielne programy z odrębnymi plikami konfiguracyjnymi, a ich pomylenie jest najczęstszą przyczyną braku efektów wprowadzanych zmian.
- Serwer odczytuje
/etc/ssh/sshd_config. W tym miejscu wyłącza się logowanie hasłem oraz ustawia port nasłuchiwania. - Klient odczytuje
/etc/ssh/ssh_configw celu uzyskania ustawień systemowych, a następnie~/.ssh/configdla własnych konfiguracji przypisanych do poszczególnych hostów.
W systemach Debian i Ubuntu jednostka usługi nosi nazwę ssh. W systemach RHEL, Rocky i Fedora nazywa się sshd. Nowsze wydania Ubuntu instalują ją w trybie aktywacji przez gniazdo (socket activated), dlatego systemctl status ssh może raportować inactive (dead), mimo że maszyna jest w pełni dostępna. Wynika to z faktu, że ssh.socket jest jednostką odpowiedzialną za nasłuchiwanie i uruchamia usługę na żądanie.
Klient nie musi być oprogramowaniem OpenSSH. PuTTY w systemie Windows, Termius na telefonie oraz zdalne wsparcie wbudowane w edytory tekstu korzystają z tego samego protokołu, łącząc się z tym samym sshd. Systemy Windows 10 i 11 również zawierają klienta OpenSSH, dzięki czemu polecenie ssh you@server działa w PowerShell bez konieczności instalacji dodatkowych narzędzi.
Dlaczego SSH używa portu 22?
Port to liczba informująca jądro systemu, do którego nasłuchującego programu należy przychodzące połączenie, a porty w systemie Linux działają w ten sam sposób dla każdej usługi. SSH używa portu 22, ponieważ IANA przypisała go w 1995 roku. Ylönen poprosił o wolny numer znajdujący się w pobliżu protokołów, które SSH miało zastąpić: 21 to FTP, 23 to telnet, a 22 był nieużywany.
Ponieważ 22 jest wartością domyślną, wszystko zakłada jej użycie. Zdalne repozytorium Git, skrypt kopii zapasowej oraz panel sterowania dostawcy próbują najpierw połączyć się przez port 22. Podobnie robi każdy zautomatyzowany skaner w Internecie. Nowy serwer z włączonym logowaniem hasłem zaczyna gromadzić wpisy takie jak poniższy w pliku /var/log/auth.log w ciągu kilku minut od uruchomienia:
Failed password for invalid user admin from 203.0.113.55 port 43122 ssh2Ten ruch jest stały i nie jest skierowany do Ciebie osobiście. Przeniesienie sshd na port 2222 eliminuje większość tych wpisów, ponieważ skanery przeszukują cały Internet na porcie 22, zamiast analizować Twój serwer. Nie utrudnia to włamania się na maszynę nikomu, kto faktycznie się nią zainteresuje. Zmianę portu należy traktować wyłącznie jako redukcję szumu.
Możesz sprawdzić odpowiedź serwera, zanim w ogóle się zalogujesz:
nc 203.0.113.10 22W systemie Ubuntu 24.04 polecenie to wyświetli wynik zbliżony do SSH-2.0-OpenSSH_9.6p1 Ubuntu-3ubuntu13. Baner jest przesyłany otwartym tekstem, zanim powstanie jakiekolwiek szyfrowanie, ponieważ obie strony muszą go użyć do uzgodnienia wersji protokołu. Naciśnij Ctrl+C, aby zamknąć połączenie.
Co dzieje się w sieci podczas nawiązywania połączenia
Poniższa sekwencja opisuje czynności wykonywane przez ssh you@server przed wyświetleniem znaku zachęty.
- Klient rozwiązuje nazwę hosta na adres IP, a następnie otwiera połączenie TCP na porcie 22.
- Obie strony przesyłają swój baner wersji w tekście jawnym.
- Obie strony przesyłają listy obsługiwanych algorytmów: wymiany kluczy, szyfrowania, uwierzytelniania komunikatów oraz kompresji. Nadal w tekście jawnym. Wybierana jest najsilniejsza opcja obsługiwana przez obie strony.
- Następuje wymiana kluczy. Obecny OpenSSH preferuje
curve25519-sha256. Obie strony uzyskują ten sam współdzielony sekret bez przesyłania go przez sieć, więc osoba rejestrująca całą konwersację nie jest w stanie go odtworzyć. - Serwer podpisuje wynik wymiany swoim prywatnym kluczem hosta. Klient sprawdza podpis za pomocą posiadanego publicznego klucza hosta. Ten krok uniemożliwia maszynie pośredniczącej podszycie się pod serwer.
- Rozpoczyna się szyfrowanie.
chacha20-poly1305@openssh.comjest domyślnym szyfrem w obecnym OpenSSH. - Dopiero teraz klient uwierzytelnia użytkownika za pomocą hasła lub klucza. Nazwa użytkownika i hasło przesyłane są wewnątrz zaszyfrowanego kanału.
- Klient otwiera kanał i żąda powłoki.
Kolejność w tej liście stanowi o zasadniczej różnicy względem telnet. Uwierzytelnianie następuje po zaszyfrowaniu kanału i potwierdzeniu tożsamości serwera, dzięki czemu hasło nigdy nie jest przesyłane w sieci w formie jawnej.
Osoba monitorująca sieć nadal uzyskuje pewne informacje. Widzi adres IP klienta, adres IP serwera, port 22, oba banery wersji w tekście jawnym oraz czas i przybliżony rozmiar każdego pakietu. Nie widzi jednak nazwy użytkownika, hasła, wpisywanych poleceń ani ich wyników. Wyszukiwanie nazwy hosta w kroku 1 nie jest częścią SSH i zazwyczaj nie jest prywatne, więc zapytanie DNS rozwiązujące nazwę serwera może ujawnić, z którą maszyną nawiązywane jest połączenie, mimo że sama sesja pozostaje zabezpieczona.
Klucz hosta i monit o odcisk palca przy pierwszym połączeniu
Podczas instalacji openssh-server generowane są pary kluczy hosta dla maszyny, które są zapisywane w /etc/ssh/, na przykład w ssh_host_ed25519_key oraz ssh_host_ed25519_key.pub. Część prywatna nigdy nie opuszcza serwera. Część publiczna stanowi tożsamość serwera i to właśnie z nią porównywany jest podpis w kroku 5.
Przy pierwszym połączeniu z nowym serwerem klient nie posiada punktu odniesienia, dlatego wyświetla monit:
The authenticity of host '203.0.113.10 (203.0.113.10)' can't be established.
ED25519 key fingerprint is SHA256:E9nVQ5Sm2oQ3nGm5Zf1tOaU7Xh0k2p8bWc4dLrTvYxA.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])?Odcisk palca (fingerprint) to skrót SHA256 klucza publicznego hosta, zapisany w formacie base64, dzięki czemu jest wystarczająco krótki do wzrokowej weryfikacji. Wpisanie yes powoduje zapisanie tego klucza w pliku ~/.ssh/known_hosts na lokalnej maszynie. Każde kolejne połączenie z tym samym adresem porównuje klucz oferowany przez serwer z zapisanym. Jeśli są zgodne, nie wyświetlają się żadne komunikaty i następuje przejście bezpośrednio do wiersza poleceń.
Ten model nazywany jest zaufaniem przy pierwszym użyciu (trust on first use) i należy mieć świadomość jego ograniczeń. Pierwsze połączenie jest momentem braku ochrony, ponieważ akceptowany jest klucz, który nie był wcześniej znany. Aby wyeliminować to ryzyko, należy uzyskać odcisk palca inną drogą i dokonać porównania. Większość dostawców wyświetla go w danych wyjściowych procesu uruchamiania w konsoli WWW; można go również wyświetlić bezpośrednio na serwerze:
ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pubPolecenie to wyświetla ten sam ciąg SHA256:, który pojawił się w monicie. Opcja [fingerprint] w monicie służy właśnie do tego: należy wkleić oczekiwany odcisk palca, a klient kontynuuje działanie tylko wtedy, gdy jest on zgodny z tym, co przedstawił serwer.
W systemach Debian i Ubuntu plik known_hosts jest domyślnie haszowany, więc zawiera linie rozpoczynające się od |1| zamiast czytelnych nazw hostów. Należy uruchomić ssh-keygen -F 203.0.113.10, aby odnaleźć wpis dla konkretnego hosta.
Dlaczego SSH zgłasza zmianę klucza hosta?
Prędzej czy później napotkasz ten blok tekstu:
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!Kończy się on komunikatem Host key verification failed., a klient odmawia nawiązania połączenia. Wyświetla również Password authentication is disabled to avoid man-in-the-middle attacks., ponieważ wpisywanie hasła do nieznanej maszyny jest dokładnie tym zagrożeniem, przed którym chroni ta weryfikacja.
Komunikat brzmi jak sytuacja awaryjna, jednak w większości przypadków tak nie jest. Typowe przyczyny:
- Serwer został przebudowany lub przeinstalowany, więc
sshdwygenerował nowe klucze hosta przy pierwszym uruchomieniu. Jest to zdecydowanie najczęstsza przyczyna. - Zniszczono jeden serwer VPS i utworzono kolejny, a dostawca przypisał nowej maszynie stary adres IP.
- Połączenie przechodzi przez przekierowanie lub load balancer, który obecnie kieruje ruch do innej maszyny backendowej.
- Rzeczywiście występuje próba przechwycenia połączenia.
Zanim cokolwiek usuniesz, ustal przyczynę. Jeśli maszyna została przeinstalowana dziesięć minut temu, przyczyna jest oczywista. Jeśli po Twojej stronie nic się nie zmieniło, przerwij działania i przeprowadź dochodzenie, ponieważ to ostrzeżenie oznacza, że mechanizm zabezpieczający działa poprawnie. Gdy zyskasz pewność, usuń nieaktualny wpis i połącz się ponownie:
ssh-keygen -R 203.0.113.10Kolejne połączenie ponownie wyświetli monit o odcisk palca (fingerprint), co daje możliwość porównania go z danymi z konsoli dostawcy.
Logowanie hasłem a logowanie kluczem
Uwierzytelnianie hasłem przesyła hasło wewnątrz już zaszyfrowanego kanału, a sshd weryfikuje je w bazie danych kont, zazwyczaj za pośrednictwem PAM (pluggable authentication modules). Nie wymaga to żadnych przygotowań, dlatego dostawca może przekazać nowy serwer, na którym skonfigurowano jedynie hasło dla użytkownika root.
Słabym punktem nie jest szyfrowanie. Problemem jest to, że hasło to krótki sekret, przesyłany do serwera przy każdym logowaniu, podczas gdy port 22 jest nieustannie atakowany metodą prób i błędów przez automaty, które nigdy się nie męczą.
Uwierzytelnianie kluczem publicznym działa inaczej. Para kluczy jest generowana na komputerze lokalnym. Połowa publiczna trafia do pliku ~/.ssh/authorized_keys wewnątrz konta na serwerze. Połowa prywatna pozostaje na laptopie i nigdy nie jest przesyłana. Aby się zalogować, klient podpisuje fragment danych zawierający identyfikator sesji z wymiany kluczy, a serwer weryfikuje ten podpis przy użyciu posiadanego klucza publicznego. Ponieważ podpisane dane są powiązane z tą konkretną sesją, przechwycony podpis jest bezużyteczny w innych okolicznościach.
Należy zwracać uwagę na kierunek, ponieważ jego odwrócenie jest częstym i szkodliwym błędem: klucz publiczny umieszcza się na serwerze, a klucz prywatny pozostaje u użytkownika. Klucz prywatny skopiowany na serwer przestaje być kluczem, któremu można ufać.
Logowanie kluczem ma własne tryby awarii. sshd ignoruje klucze, gdy uprawnienia do plików są zbyt luźne, co jest odnotowywane w dzienniku serwera:
Authentication refused: bad ownership or modes for directory /home/ubuntu/.sshKlient wyświetla jedynie komunikat Permission denied (publickey), który jest wspólny dla wielu różnych przyczyn, dlatego warto nauczyć się poprawnej interpretacji błędu publickey przed zablokowaniem sobie dostępu. Praktyczne aspekty tworzenia kluczy, zabezpieczania ich hasłem oraz ładowania do agenta zostały opisane w zarządzaniu kluczami SSH, natomiast wyłączenie logowania hasłem bez ryzyka utraty dostępu znajduje się w zabezpieczaniu SSH na VPS.
SFTP, scp oraz przekierowanie portów korzystają z tego samego połączenia
Oto koncepcja, która porządkuje działanie reszty świata SSH. Uwierzytelnianie otwiera szyfrowane połączenie, które może obsługiwać kilka niezależnych kanałów jednocześnie. Powłoka jest tylko jednym z wielu rodzajów kanałów.
- Zdalna powłoka.
ssh you@serverotwiera kanał sesji i żąda interaktywnej powłoki. - Pojedyncze polecenie.
ssh you@server uptimeotwiera kanał, wykonuje jedno polecenie, wypisuje wynik i kończy działanie. - SFTP. Klient prosi
sshdo uruchomienie podsystemusftp, a przesyłanie plików odbywa się wewnątrz tego samego połączenia. SFTP to protokół przesyłania plików działający w oparciu o SSH i nie ma nic wspólnego z FTP. Protokół będący FTP z dodanym szyfrowaniem nazywa się FTPS i nie jest z nim powiązany. - scp. Kopiuje pliki przy użyciu tego samego logowania. Od wersji OpenSSH 9.0, wydanej w 2022 roku,
scpdomyślnie korzysta z protokołu SFTP. - Przekierowanie portów.
ssh -L 8080:localhost:80 you@serverzamienia port 8080 na laptopie w bramę do portu 80 na serwerze, przesyłaną wewnątrz szyfrowanego połączenia.-Rprzekierowuje ruch w drugą stronę, a-D 1080zamienia sesję w proxy SOCKS. - Git. Zdalny zasób typu
git@github.com:user/repo.gitto logowanie SSH, w którym po stronie zdalnej zamiast powłoki uruchamiany jest program obsługujący polecenia. - rsync oraz Ansible to również klienci SSH. Otwierają kanał, uruchamiają proces i odczytują jego wynik.
Każdy element z tej listy korzysta z tego samego portu, tej samej weryfikacji klucza hosta oraz tych samych poświadczeń. Dlatego jednorazowa konfiguracja uwierzytelniania kluczem natychmiast przynosi korzyści: każde z tych narzędzi dziedziczy to ustawienie. Z tego samego powodu plik ~/.ssh/config, który skraca proces logowania, jest plikiem, który pozwala na skalowanie pracy podczas zarządzania wieloma serwerami Linux z poziomu jednego laptopa.
Czego SSH nie robi
- Nie zapewnia bezpieczeństwa serwera. SSH chroni jedynie drogę do drzwi. Drzwi nadal istnieją, a niepowołane osoby będą próbowały naciskać klamkę. Blokowanie powtarzających się prób logowania za pomocą fail2ban ogranicza skalę tego zjawiska, a uwierzytelnianie wyłącznie za pomocą kluczy eliminuje element, który jest przedmiotem zgadywania.
- Nie chroni przed zagrożeniami pochodzącymi z własnej stacji roboczej. Każdy, kto ma dostęp do laptopa, posiada również klucz prywatny oraz załadowany agent.
- Nie ukrywa faktu korzystania z SSH. Numer portu oraz jawny baner wersji informują o tym otwarcie.
- Nie obejmuje zdarzeń poprzedzających nawiązanie połączenia. Wyszukiwanie nazwy oraz decyzja o tym, któremu adresowi zaufać, mają miejsce wcześniej.
Dalsze kroki
Jeśli aktualnie w konsoli dostawcy otwarty jest nowy serwer, należy zachować określoną kolejność działań. Należy zalogować się, utworzyć użytkownika z uprawnieniami standardowymi, zainstalować klucz, a następnie zamknąć łatwo dostępne ścieżki dostępu. Artykuł Pierwsze dziesięć minut na nowym VPS przeprowadza przez ten proces od początku do końca, natomiast czym w rzeczywistości jest VPS wyjaśnia budowę maszyny, jeśli te pojęcia są jeszcze nowe. Następnie należy zapoznać się z artykułami o kluczach oraz o zabezpieczaniu systemu, właśnie w tej kolejności.
FAQ
Co oznacza skrót SSH?
SSH oznacza secure shell. Jest to protokół służący do logowania się na zdalny komputer i wykonywania na nim poleceń za pośrednictwem szyfrowanego połączenia, zdefiniowany w RFC 4251 do RFC 4254. OpenSSH to implementacja używana niemal powszechnie: klient ssh na komputerze lokalnym oraz serwer sshd na maszynie zdalnej. Zastąpił on protokół telnet, który przesyłał wszystkie dane, w tym hasła, przez sieć w postaci otwartego tekstu.
Dlaczego SSH używa portu 22?
IANA przypisała port 22 do SSH w 1995 roku, obok FTP na porcie 21 oraz telnet na 23, czyli protokołów, które SSH miało zastąpić. Nic nie wymusza użycia tego numeru: Port w pliku /etc/ssh/sshd_config zmienia go na serwerze, a ssh -p wybiera inny port po stronie klienta. Ponieważ 22 jest wartością domyślną, zautomatyzowane skanery nieustannie sprawdzają ten port, dlatego plik /var/log/auth.log na nowym serwerze szybko zapełnia się wpisami Failed password for invalid user. Zmiana portu redukuje ten szum, ale nie zapewnia realnej ochrony.
Co zrobić, gdy SSH ostrzega o zmianie klucza hosta?
Przed usunięciem jakichkolwiek danych należy ustalić przyczynę. Zazwyczaj powód jest niegroźny: serwer został przeinstalowany, więc sshd wygenerował nowe klucze hosta, albo nowa maszyna otrzymała stary adres IP. Jeśli wiadomo, że maszyna została przeinstalowana, należy wykonać ssh-keygen -R <host>, aby usunąć zapisany klucz, połączyć się ponownie i porównać wyświetlony odcisk klucza (fingerprint) z tym, który podaje konsola dostawcy. Jeśli po stronie użytkownika nie wprowadzano zmian, nie należy się łączyć ani wpisywać hasła. OpenSSH w takim stanie automatycznie odmawia uwierzytelniania hasłem właśnie z tego powodu.
Czy SFTP i scp różnią się od SSH?
Działają one w oparciu o SSH. Po uwierzytelnieniu połączenie SSH może obsługiwać wiele kanałów, a powłoka (shell) jest tylko jednym z nich. SFTP to protokół przesyłania plików, który wykorzystuje podsystem sftp w ramach sshd przez to samo połączenie, a scp od wersji OpenSSH 9.0 używa protokołu SFTP jako mechanizmu bazowego. Przekierowanie portów (port forwarding) oraz Git przez SSH to również kanały w ramach tego samego połączenia. Wszystkie korzystają z tego samego portu, tej samej weryfikacji klucza hosta i tego samego logowania. Należy pamiętać, że SFTP to nie FTP z dodanym szyfrowaniem; ten drugi nazywa się FTPS i jest odrębnym protokołem.
Czy uwierzytelnianie kluczem jest rzeczywiście lepsze od hasła?
Tak, w przypadku każdego serwera dostępnego z Internetu. Hasło to krótki sekret przekazywany serwerowi przy każdym logowaniu, a port 22 jest nieustannie atakowany metodą prób i błędów przez zautomatyzowane skrypty. W przypadku pary kluczy, część prywatna nigdy nie opuszcza komputera: klient podpisuje dane powiązane z bieżącą sesją, a serwer sprawdza ten podpis względem klucza publicznego w ~/.ssh/authorized_keys. Zarejestrowany podpis nie może zostać użyty ponownie przeciwko innemu serwerowi. Klucz prywatny należy chronić hasłem (passphrase), ponieważ plik klucza bez hasła stanowi gotowe narzędzie logowania dla każdego, kto go skopiuje.