Jak naprawić błąd SSH „Permission denied (publickey)”

Opublikowano 15 min czytania

Logowanie SSH kończy się błędem Permission denied (publickey)? Siedem przyczyn, od uprawnień plików przez AllowUsers po SELinux, każda z dosłownym wpisem w logu i pasującym środkiem zaradczym.

Próba połączenia urywa się po sekundzie, nie pojawia się żadne pytanie o hasło, tylko jeden jedyny wiersz: Permission denied (publickey). Ten komunikat jest tak nieprzyjemny dlatego, że celowo niczego nie zdradza. Serwer SSH nie mówi potencjalnemu napastnikowi, czy użytkownik istnieje, czy klucz był zły, czy plik jest nieczytelny. Dokładnie ta sama powściągliwość dotyka jednak także ciebie, kiedy stoisz przed drzwiami całkiem legalnie.

Dobra wiadomość: lista przyczyn jest skończona, da się je sprawdzić w ustalonej kolejności, a w większości przypadków chodzi po prostu o uprawnienia do plików. Ten artykuł omawia przyczyny w kolejności ich częstości, przy każdej pokazuje dosłowne brzmienie wpisu w logu i wyjaśnia, jak za pomocą ssh -vvv w trzydzieści sekund rozstrzygniesz, czy problem leży na twoim komputerze, czy na serwerze.

Co dokładnie oznacza ten komunikat

Nawias na końcu nie jest ozdobnikiem, to najważniejsza informacja w całym wierszu. Zawiera listę metod uwierzytelniania, które serwer nadal oferuje po nieudanej próbie:

Permission denied (publickey).
Permission denied (publickey,password).
Permission denied (publickey,gssapi-keyex,gssapi-with-mic).

Jeśli widnieje tam samo publickey, logowanie hasłem jest na serwerze wyłączone. Jeśli na liście jest też password, logowanie hasłem byłoby w zasadzie możliwe, tylko nie zostało podjęte albo również się nie powiodło. Wariant z gssapi jest typowy dla AlmaLinuksa, Rocky Linux i RHEL, gdzie obsługa Kerberosa jest wkompilowana w pakiet.

Ważne jest odróżnienie od komunikatów, które wyglądają podobnie, ale opisują zupełnie inny problem:

  • Permission denied, please try again. bez nawiasu to złe hasło, a nie problem z kluczem.
  • Host key verification failed. dotyczy klucza serwera w twoim pliku known_hosts, a nie twojego własnego klucza.
  • Received disconnect from 203.0.113.7 port 22:2: Too many authentication failures oznacza, że twój agent podał po kolei zbyt wiele kluczy, a serwer przerwał po osiągnięciu MaxAuthTries.
  • Connection refused albo timeout to sprawy sieci lub firewalla. Jeśli wcześniej majstrowałeś przy firewallu UFW albo przy Fail2ban, zacznij właśnie tam.

Rozwidlenie dróg: jak poprawnie czytać ssh -vvv

Zanim cokolwiek zmienisz, każ sobie pokazać cały przebieg. Trzy litery v to nie przypadek, przy jednym v brakuje najważniejszych wierszy:

ssh -vvv deploy@203.0.113.7

Wynik jest długi, ale szukasz tylko czterech miejsc. Po pierwsze nazwy użytkownika, pod którą klient naprawdę się łączy:

debug1: Authenticating to 203.0.113.7:22 as 'deploy'

Po drugie, które klucze klient w ogóle bierze pod uwagę, i po trzecie, który z nich naprawdę wysyła:

debug1: Will attempt key: /home/tom/.ssh/id_ed25519 ED25519 SHA256:8Qk... agent
debug1: Offering public key: /home/tom/.ssh/id_ed25519 ED25519 SHA256:8Qk... agent
debug1: Authentications that can continue: publickey
debug1: No more authentication methods to try.

I po czwarte komunikat o powodzeniu, którego w razie błędu po prostu nie ma:

debug1: Server accepts key: /home/tom/.ssh/id_ed25519 ED25519 SHA256:8Qk...
debug1: Authenticated to 203.0.113.7 ([203.0.113.7]:22) using "publickey".

Stąd bierze się rozwidlenie, które oszczędza ci połowę diagnostyki:

  • Nie pojawia się Offering public key z twoim kluczem. Wtedy problem leży na twoim komputerze, klucz nigdy nie został wysłany. Przeskocz do przyczyny 3.
  • Pojawia się Offering public key, ale zaraz potem znowu Authentications that can continue. Wtedy serwer zobaczył twój klucz i go odrzucił. To przyczyny 1, 2, 4, 5 i 6, wszystkie po stronie serwera.
  • Pojawia się send_pubkey_test: no mutual signature algorithm. Wtedy chodzi o typ klucza, przeskocz do przyczyny 7.

Na dwa kolejne wiersze z wyjścia debugowania warto rzucić okiem. debug3: no such identity: /home/tom/.ssh/id_rsa: No such file or directory jest nieszkodliwy, klient po prostu przechodzi po wszystkich standardowych nazwach. Za to Permissions 0644 for '/home/tom/.ssh/id_ed25519' are too open. to prawdziwe trafienie: twój klucz prywatny zostaje wtedy zignorowany.

Strona serwera: sshd -T i logi

ssh -vvv pokazuje wyłącznie perspektywę klienta. Dlaczego serwer odmówił, dowiesz się tylko z logu serwera. Jeśli masz jeszcze otwartą sesję albo wchodzisz przez konsolę w panelu klienta, zajrzyj najpierw właśnie tam.

Na Debianie i Ubuntu usługa nazywa się ssh, na AlmaLinuksie, Rocky Linux i RHEL nazywa się sshd. To klasyczna pułapka przy kopiowaniu poleceń:

journalctl -u ssh -n 50 --no-pager      # Debian, Ubuntu
journalctl -u sshd -n 50 --no-pager     # AlmaLinux, Rocky, RHEL

Klasycznego pliku tekstowego nie ma już wszędzie. Ubuntu 22.04 i 24.04 nadal prowadzą w instalacji serwerowej /var/log/auth.log, bo rsyslog jest tam dostarczany razem z systemem. Debian 12 i Debian 13 nie instalują już rsysloga w instalacji minimalnej, plik zwyczajnie nie istnieje, a wszystko ląduje w journalu. W rodzinie Red Hata plik nazywa się /var/log/secure. Kto chce odzyskać plik tekstowy na Debianie, doinstalowuje rsyslog: na Debianie i Ubuntu poleceniem apt-get install -y rsyslog, w rodzinie Red Hata poleceniem dnf install -y rsyslog.

Drugie polecenie po stronie serwera jest jeszcze ważniejsze, bo wypisuje faktycznie obowiązującą konfigurację i rozwija przy tym wszystkie dołączone pliki:

sshd -T | grep -Ei 'pubkeyauth|authorizedkeysfile|strictmodes|permitrootlogin'

Jeśli polecenie zamiast konfiguracji odpowiada tylko komunikatem Missing privilege separation directory: /run/sshd i nie wypisuje ani jednego wiersza, brakuje po prostu katalogu czasu wykonania. Zdarza się to na Debianie 11, Debianie 12, Ubuntu 22.04 i Ubuntu 24.04 bezpośrednio po instalacji pakietu, dopóki usługa nie została ani razu uruchomiona, a także w kontenerach. W normalnej pracy jednostka systemd zakłada ten katalog sama przez RuntimeDirectory=sshd. Gdy komunikat się pojawi, pomaga wcześniejsze mkdir -p /run/sshd, po czym sshd -T czysto zwraca permitrootlogin, pubkeyauthentication yes, strictmodes yes oraz authorizedkeysfile. Debian 13 z OpenSSH 10 i cała rodzina Red Hata tego ograniczenia już nie znają. Uważaj, bo w potoku komunikat ginie: sshd -T | grep ... pokazuje wtedy tylko puste wyjście, a właściwy kod powrotu 255 znika w grepie.

A jeśli naprawdę chcesz zobaczyć, co myśli serwer, nie ruszając działającej usługi: uruchom drugą instancję w trybie debugowania na wolnym porcie. Kończy się sama po jednym połączeniu i nie jest w stanie cię zablokować.

/usr/sbin/sshd -ddd -p 2222

Ze swojego komputera wywołujesz wtedy ssh -p 2222 deploy@203.0.113.7, a w terminalu serwera odmowa jest wypisana otwartym tekstem. Port musi być do tego oczywiście otwarty w firewallu.

Przyczyna 1: uprawnienia i właściciel, zdecydowanie najczęstszy przypadek

OpenSSH ma opcję StrictModes yes włączoną domyślnie. Serwer odmawia odczytania klucza z pliku, do którego oprócz samego użytkownika mógłby pisać ktoś jeszcze. To nie szykana, tylko zabezpieczenie przed tym, żeby inny użytkownik po prostu dopisał swój własny klucz do twojego authorized_keys.

Stan docelowy jest wąsko zdefiniowany:

chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
chmod 750 ~
chown -R "$(id -un):$(id -gn)" ~/.ssh

Sprawdzisz to jedną linijką:

stat -c "%a %U %G %n" ~ ~/.ssh ~/.ssh/authorized_keys

Oczekiwane są 750 albo 700 dla katalogu domowego, 700 dla .ssh600 dla authorized_keys, a we wszystkich trzech wierszach twoja własna nazwa użytkownika. Decydujące jest to, że katalog domowy nie może być zapisywalny dla grupy ani dla pozostałych, więc 770 albo 777 wystarczą już, żeby logowanie padło.

Jednej liczby nie wolno przy tym wziąć za błąd: na AlmaLinuksie, Rocky Linux i Oracle Linux katalog /root ma uprawnienia 550, a nie 700 jak na Debianie i Ubuntu. stat -c pokazuje to poprawnie i jest to całkowicie w porządku. Dla StrictModes liczy się tylko to, że grupa i pozostali nie mają prawa zapisu, a dokładnie to spełnia 550. Kto dorzuci tu chmod 700 /root, wcale nie naprawił logowania, tylko jeszcze bardziej zasłonił przyczynę.

W logu serwera pojawia się wtedy bardzo wyraźny wpis:

Authentication refused: bad ownership or modes for directory /home/deploy/.ssh
Authentication refused: bad ownership or modes for file /home/deploy/.ssh/authorized_keys
error: Could not open authorized keys '/home/deploy/.ssh/authorized_keys': Permission denied

Dwa szczegóły, które inne poradniki chętnie pomijają. Po pierwsze właściciel: jeśli utworzyłeś plik poleceniem sudo nano ~/.ssh/authorized_keys, należy on do roota, a nie do użytkownika, i logowanie nie przechodzi mimo idealnych uprawnień 600. Po drugie, sshd sprawdza całą ścieżkę w górę. Jeśli katalog domowy nie leży pod /home, tylko na przykład pod /srv/klienci/deploy, to również /srv/srv/klienci muszą należeć do roota albo do użytkownika i nie mogą być zapisywalne dla grupy ani dla pozostałych.

Przyczyna 2: zła nazwa użytkownika

Nieistniejący użytkownik daje dokładnie ten sam komunikat co zły klucz, bo serwer świadomie nie zdradza, który z tych dwóch przypadków zachodzi. W logu różnicę widać od razu:

Invalid user deply from 203.0.113.7 port 51234

Najczęstszy powód to sytuacja, w której klucz leży w /root/.ssh/authorized_keys, a ty logujesz się jako zwykły użytkownik, albo odwrotnie. W gotowych obrazach chmurowych logowanie na roota bywa zablokowane, a zamiast niego istnieje przygotowany użytkownik, zależnie od dystrybucji debian, ubuntu, almalinux albo rocky. W standardowych obrazach na serwerze root od KernelHosta logujesz się natomiast wprost jako root.

Sprawdź poza tym, czy twój plik ~/.ssh/config nie podsuwa ci innego użytkownika. Poniższe polecenie nie nawiązuje połączenia, pokazuje tylko, jakie ustawienia faktycznie obowiązują dla tego celu:

ssh -G deploy@203.0.113.7

W wyniku interesują cię user, hostname, port oraz lista wpisów identityfile.

Przyczyna 3: klucz w ogóle nie zostaje zaoferowany

Jeśli w ssh -vvv nie pojawia się Offering public key z twoim kluczem, serwer nigdy nie dostał szansy. Są ku temu cztery typowe powody.

Klucz ma własną nazwę

Automatycznie OpenSSH sprawdza tylko standardowe nazwy id_ed25519, id_ecdsaid_rsa. Klucz o nazwie id_produkcja zostanie użyty wyłącznie wtedy, gdy sam go wskażesz:

ssh -i ~/.ssh/id_produkcja -o IdentitiesOnly=yes deploy@203.0.113.7

IdentitiesOnly=yes nie jest tutaj dodatkiem. Bez tej opcji ssh podaje dodatkowo wszystkie klucze z agenta, a przy zbyt wielu próbach serwer przerywa komunikatem Too many authentication failures, zanim właściwy klucz w ogóle dojdzie do głosu.

Agent nie ma tego klucza

ssh-add -l

Jeśli polecenie odpowiada The agent has no identities. albo Could not open a connection to your authentication agent., doładuj klucz poleceniem ssh-add ~/.ssh/id_ed25519.

Uprawnienia klucza prywatnego

Klucz prywatny musi mieć 600, inaczej klient odmówi posłuszeństwa. W Windowsie chmod nie działa, tam pracuje się na listach ACL:

icacls %USERPROFILE%\.ssh\id_ed25519 /inheritance:r /grant:r "%USERNAME%":R

Plik authorized_keys jest uszkodzony

Klucz publiczny to dokładnie jeden wiersz. Przy kopiowaniu przez edytory, systemy zgłoszeń albo okna czatu chętnie robi się z tego złamanie linii w środku bloku Base64 i wtedy nic już nie pasuje. Policz:

grep -c '^ssh-' ~/.ssh/authorized_keys
awk '{print NR": "NF" pola, typ "$1}' ~/.ssh/authorized_keys

Każdy wiersz musi zaczynać się od ssh-ed25519, ssh-rsa albo ecdsa-sha2- i składać się z dwóch do trzech pól. Liczba wierszy musi zgadzać się z liczbą kluczy. Drugi klasyk to sytuacja, w której przez pomyłkę wpisano klucz prywatny zamiast publicznego, co poznasz po BEGIN OPENSSH PRIVATE KEY. A klucz w formacie PuTTY (.ppk) tak nie zadziała, trzeba go najpierw wyeksportować do formatu OpenSSH.

Czy klucz prywatny i publiczny do siebie pasują, wyjaśni porównanie odcisków palca:

ssh-keygen -lf ~/.ssh/id_ed25519.pub
ssh-keygen -lf ~/.ssh/authorized_keys

W obu wynikach musi wystąpić ta sama wartość SHA256. Jak wygląda całość porządnie ustawiona, opisuje nasz artykuł o tym, jak zabezpieczyć SSH i skonfigurować logowanie kluczem.

Przyczyna 4: PubkeyAuthentication jest wyłączone

Rzadsze, ale za to zupełnie jednoznaczne. Sprawdzaj nie plik konfiguracyjny, tylko wynik:

sshd -T | grep -i pubkeyauthentication

Tu czai się pułapka, która kosztuje wiele godzin. Debian od wersji 12 i Ubuntu od 22.04 mają na samej górze pliku /etc/ssh/sshd_config wiersz Include /etc/ssh/sshd_config.d/*.conf. W sshd obowiązuje zasada: dla każdego słowa kluczowego liczy się wartość znaleziona jako pierwsza. Ponieważ dołączenie znajduje się na samym początku, każdy drobiazg z sshd_config.d wygrywa z plikiem głównym, niezależnie od tego, co zapisano w nim niżej. Jeśli twoja zmiana nie przynosi żadnego skutku, zajrzyj właśnie tam:

grep -rniE 'pubkeyauthentication|authorizedkeysfile|allowusers|allowgroups' /etc/ssh/

Drugi punkt w tej kategorii to AuthorizedKeysFile. Domyślnie są to .ssh/authorized_keys oraz .ssh/authorized_keys2. Niektóre skrypty hartujące ustawiają tę ścieżkę na coś w rodzaju /etc/ssh/authorized_keys/%u. Twój plik w katalogu domowym jest wtedy całkowicie ignorowany, bez żadnego komunikatu o błędzie. To również pokaże sshd -T.

Przyczyna 5: w grę wchodzą AllowUsers, AllowGroups i Match

Te dyrektywy odcinają całe grupy użytkowników, i to zanim klucz w ogóle zostanie sprawdzony. Brzmienie wpisu w logu:

User root from 203.0.113.7 not allowed because not listed in AllowUsers
User deploy from 203.0.113.7 not allowed because none of user's groups are listed in AllowGroups
User root from 203.0.113.7 not allowed because "PermitRootLogin no"

Zapamiętaj kolejność: DenyUsers bije AllowUsers, a gdy tylko AllowUsers zostanie w ogóle ustawione, wszyscy niewymienieni użytkownicy są odcięci. Przy AllowGroups musi zgadzać się przynależność do grupy, co sprawdzisz poleceniem id deploy.

Przy PermitRootLogin ważne jest rozróżnienie: prohibit-password pozwala na logowanie roota kluczem. Dopiero no blokuje roota całkowicie. W wyniku sshd -T nie spodziewaj się jednak słowa prohibit-password: widnieje tam starsza, równoznaczna nazwa without-password. A wartość domyślna wcale nie jest wszędzie taka sama, co przy porównywaniu dwóch serwerów regularnie wywołuje zamieszanie:

SystemWartość z sshd -T
Debian 11, 12, 13without-password
Rocky Linux 9, Oracle Linux 9without-password
AlmaLinux 9, AlmaLinux 10yes

Na AlmaLinuksie root może więc wejść także hasłem, na pozostałych wymienionych systemach nie. Kto przenosi usługę z AlmaLinuksa na Debiana i dotąd logował się jako root hasłem, ląduje potem dokładnie na Permission denied (publickey).

Jeśli reguła siedzi w bloku Match, pomaga opcja, która wylicza konfigurację dla konkretnego przypadku:

sshd -T -C user=deploy,host=client.example.com,addr=203.0.113.7 | grep -Ei 'pubkeyauth|allowusers|permitrootlogin'

To najpewniejsza droga, żeby zobaczyć, co obowiązuje dokładnie dla tego użytkownika łączącego się dokładnie z tego adresu IP.

Przyczyna 6: SELinux na AlmaLinuksie, Rocky i RHEL

W rodzinie Red Hata SELinux działa domyślnie w trybie Enforcing, na Debianie i Ubuntu nie odgrywa żadnej roli. Proces sshd może odczytać authorized_keys tylko wtedy, gdy plik nosi kontekst ssh_home_t. Tak jest, gdy powstał normalnie w katalogu domowym. Tak nie jest, gdy ściągnąłeś go poleceniem mv/tmp albo założyłeś katalog domowy ręcznie, bo mv zabiera ze sobą stary kontekst.

getenforce
ls -Z ~/.ssh

Poprawny jest wpis kończący się na ssh_home_t. Jeśli jest tam user_tmp_t albo user_home_t, przyczyna została znaleziona. Naprawa:

restorecon -R -v ~/.ssh

Ten krok dotyczy wyłącznie rodziny Red Hata. Na Debianie i Ubuntu nie ma domyślnej konfiguracji SELinuksa, shell odpowiada tam restorecon: command not found, co nie jest błędem, tylko po prostu nie ma zastosowania. Ale również na AlmaLinuksie i Rocky Linux polecenia brakuje w odchudzonej instalacji, bo odpowiedni pakiet nie jest zainstalowany. Wtedy najpierw go doinstaluj:

dnf install -y policycoreutils

Dowody znajdziesz w logu audytu, odmowa jest tam opisana otwartym tekstem:

ausearch -m avc -ts recent

Jeśli katalogi domowe leżą w nietypowym miejscu, samo restorecon nie wystarczy, bo SELinux w ogóle nie zna tej ścieżki jako katalogu domowego. Wtedy jednorazowo zgłaszasz zrównanie ścieżek, a potem przywracasz konteksty:

semanage fcontext -a -e /home /srv/klienci
restorecon -R -v /srv/klienci

semanage siedzi w pakiecie policycoreutils-python-utils. Nie wyłączaj SELinuksa po to, żeby logowanie zaczęło działać: to załatwianie problemu na dwa polecenia kosztem bezpieczeństwa całej maszyny.

Przyczyna 7: stary serwer, niewłaściwy typ klucza

Od OpenSSH 8.8 klient odrzuca podpisy RSA z SHA-1. Dotyczy to już Ubuntu 22.04, a Debian 13 dostarcza obecnie OpenSSH 10. Jeśli z tak aktualnego systemu chcesz dostać się na bardzo stary serwer, który zna wyłącznie stare ssh-rsa, w wyjściu debugowania zobaczysz:

debug1: send_pubkey_test: no mutual signature algorithm

To nie jest problem z uprawnieniami, twój klucz jest całkiem w porządku. Na jednorazowy dostęp pomaga:

ssh -o PubkeyAcceptedAlgorithms=+ssh-rsa -o HostKeyAlgorithms=+ssh-rsa deploy@203.0.113.7

Na stałe wpisuje się to do ~/.ssh/config pod wpisem Host, żeby dotyczyło tylko tego jednego serwera. Na bardzo starych klientach opcja nazywa się jeszcze PubkeyAcceptedKeyTypes. Właściwym rozwiązaniem jest aktualizacja starego serwera, bo od OpenSSH 7.2 zna on również warianty SHA-2, a twój dotychczasowy klucz RSA działa dalej bez zmian. Zmienia się tylko metoda podpisu.

Istnieje też przypadek odwrotny. Klucz ed25519 wymaga co najmniej OpenSSH 6.5 po obu stronach, a tokeny sprzętowe typu ed25519-sk co najmniej 8.2. DSA zaś przeszło do historii: od OpenSSH 10.0 ssh-dss jest całkowicie usunięte, takie stare klucze wobec Debiana 13 nie działają już wcale. Jakie typy zna twój klient, pokaże:

ssh -Q key

Jeśli na świeżo postawionym AlmaLinuksie, Rocky Linux albo RHEL ssh brakuje całkowicie, odpowiada za to pułapka w nazwach pakietów: dnf install openssh-server przynosi wyłącznie usługę, bez narzędzi klienckich. Bez nich nie ma ssh ani ssh-add, a więc także ssh -Qssh -G. Doinstalowuje się je pod nazwą w liczbie mnogiej, inaczej niż w debianowym pakiecie openssh-client:

dnf install -y openssh-clients

Na AlmaLinuksie, Rocky i RHEL 9 dochodzi druga warstwa. Systemowe polityki kryptograficzne współdecydują tam o tym, co jest dozwolone, niezależnie od konfiguracji sshd:

update-crypto-policies --show

To narzędzie także należy wyłącznie do świata Red Hata, na Debianie i Ubuntu nie istnieje. Nawet na Oracle Linux 9 brakuje go w instalacji minimalnej, doinstaluje je tam dnf install -y crypto-policies-scripts, po czym zgodnie z oczekiwaniem wychodzi DEFAULT. Jeśli widnieje tam DEFAULT, podpisy SHA-1 są już zablokowane w całym systemie. update-crypto-policies --set LEGACY to rozwiązuje, ale osłabia całą maszynę i powinno być najwyżej rozwiązaniem przejściowym na czas migracji.

Jeśli zablokowałeś sobie dostęp

Niebezpieczny moment to nie sam błąd, tylko naprawianie sshd_config. Trzy zasady, dzięki którym zablokowanie sobie dostępu staje się praktycznie niemożliwe:

  1. Zostaw otwartą drugą sesję. Restart sshd nie zrywa istniejących połączeń. Dopóki jeden terminal pozostaje otwarty, możesz cofnąć każdą zmianę.
  2. Przed każdym restartem sprawdź składnię. sshd -t przy błędach podaje numer wiersza, a gdy wszystko się zgadza, milczy. W przeciwnym razie literówka w konfiguracji uniemożliwi start usługi i wtedy nikt już nie wejdzie. Jeśli zamiast tego pojawi się Missing privilege separation directory: /run/sshd, twoja konfiguracja jest w porządku, brakuje tylko katalogu czasu wykonania, patrz wyżej.
  3. Testuj z drugiej sesji, zanim zamkniesz pierwszą.

Przy restarcie systemy się różnią. Na Debianie i Ubuntu jednostka nazywa się ssh, w rodzinie Red Hata sshd. Od Ubuntu 22.10 oraz w Debianie 13 SSH startuje dodatkowo przez aktywację socketu: konfiguracja z sshd_config nadal obowiązuje, ale zmieniony wpis Port zadziała dopiero po restarcie również ssh.socket.

sshd -t
systemctl restart ssh          # Debian, Ubuntu
systemctl restart ssh.socket   # dodatkowo, jeśli zmieniono port
systemctl restart sshd         # AlmaLinux, Rocky, RHEL

Jeśli mimo wszystko do tego doszło, potrzebujesz drogi z pominięciem SSH. Przy serwerze root od KernelHosta otwierasz w panelu klienta konsolę VNC i logujesz się tam hasłem roota, całkiem bez usługi sieciowej. Jeśli to nie doprowadzi do celu, na przykład dlatego, że sshd w ogóle już nie startuje, pomaga system ratunkowy: bootujesz do środowiska awaryjnego, montujesz główny system plików i poprawiasz authorized_keys oraz uprawnienia bezpośrednio na dysku. Pamiętaj, żeby po zamontowaniu sprawdzić właścicieli plików, bo w systemie ratunkowym jesteś rootem i inaczej zakładasz pliki z błędnym właścicielem.

Po czym poznasz, że to naprawdę działa

To, że logowanie się udaje, wcale nie znaczy, że przebiegło kluczem. Dopóki logowanie hasłem jest aktywne, serwer może po cichu wpuścić cię właśnie tą drogą. Uczciwy test wyklucza każdą inną metodę:

ssh -o BatchMode=yes -o PreferredAuthentications=publickey deploy@203.0.113.7 'id -un; hostname'

BatchMode=yes tłumi każde interaktywne pytanie. Jeśli wróci twoja nazwa użytkownika i nazwa hosta, a echo $? zwróci potem 0, zadziałał wyłącznie klucz.

Drugi dowód znajduje się w logu serwera i podaje nawet odcisk palca użytego klucza:

Accepted publickey for deploy from 203.0.113.7 port 51234 ssh2: ED25519 SHA256:8Qk...

Porównaj tę wartość SHA256 z wynikiem ssh-keygen -lf ~/.ssh/id_ed25519.pub. Jeśli obie się zgadzają, wiesz nie tylko, że logowanie działa, ale też który klucz zadziałał. Ma to znaczenie, gdy w grze jest kilka kluczy i chcesz jeden z nich wycofać.

Kolejność sprawdzania krok po kroku

Jeśli nie masz czasu na teorię, przejdź tę listę od góry do dołu. Jest posortowana według częstości, a nie według elegancji.

  1. Uruchom ssh -vvv i ustal, czy pojawia się Offering public key. To dzieli problem na stronę klienta i stronę serwera.
  2. Sprawdź uprawnienia: 700 na ~/.ssh, 600 na authorized_keys, katalog domowy niezapisywalny dla grupy, wszystko w posiadaniu użytkownika.
  3. Sprawdź nazwę użytkownika, w razie wątpliwości odpytaj ssh -G i poszukaj w logu wpisu Invalid user.
  4. Porównaj odciski palca klucza prywatnego i authorized_keys, skontroluj liczbę wierszy w pliku.
  5. Przeanalizuj sshd -T: pubkeyauthentication, authorizedkeysfile, strictmodes, permitrootlogin.
  6. Sprawdź AllowUsers, AllowGroups, DenyUsers oraz bloki Match, razem z katalogiem sshd_config.d.
  7. W rodzinie Red Hata ls -Z ~/.ssh, a w razie potrzeby restorecon -R -v ~/.ssh.
  8. Tylko przy bardzo starych serwerach po drugiej stronie: rozszerz algorytmy podpisu przez PubkeyAcceptedAlgorithms=+ssh-rsa.

Najpóźniej w tym miejscu przyczyna jest znaleziona. Jeśli potem chcesz porządnie postawić dostęp od nowa, dobrymi punktami zaczepienia są wprowadzenie do połączenia przez SSH oraz lista kontrolna dla nowego serwera root.

Najczęstsze pytania

Co oznacza nawias w komunikacie „Permission denied (publickey,password)”?
Wymienia metody uwierzytelniania, które serwer nadal oferuje po nieudanej próbie. Jeśli widnieje tam samo publickey, logowanie hasłem jest wyłączone. Jeśli na liście jest też password, logowanie hasłem byłoby możliwe. Wariant z gssapi-keyex i gssapi-with-mic jest typowy dla AlmaLinuksa, Rocky Linux i RHEL.
Jakie uprawnienia muszą mieć ~/.ssh i authorized_keys?
700 dla ~/.ssh, 600 dla ~/.ssh/authorized_keys, a katalog domowy nie może być zapisywalny dla grupy ani dla pozostałych, czyli 750 albo 700. Wszystkie trzy muszą należeć do danego użytkownika, a nie do roota. Sprawdzisz to poleceniem: stat -c "%a %U %G %n" ~ ~/.ssh ~/.ssh/authorized_keys
Po czym poznam w ssh -vvv, czy problem leży po stronie klienta, czy serwera?
Po wierszu „Offering public key”. Jeśli go brakuje, klient nigdy nie wysłał twojego klucza, a problem jest lokalny (zła nazwa pliku, pusty agent, zbyt szerokie uprawnienia klucza prywatnego). Jeśli wiersz się pojawia, a zaraz po nim znowu „Authentications that can continue”, serwer zobaczył klucz i go odrzucił: wtedy chodzi o uprawnienia, nazwę użytkownika, konfigurację sshd albo SELinuksa.
Dlaczego logowanie kluczem nie działa na AlmaLinuksie, choć uprawnienia się zgadzają?
Najczęściej odpowiada za to kontekst SELinuksa. Plik authorized_keys musi mieć typ ssh_home_t. Jeśli został przeniesiony poleceniem mv z /tmp, zachowuje stary kontekst i sshd nie może go odczytać. Sprawdzisz to poleceniem ls -Z ~/.ssh, a naprawisz przez restorecon -R -v ~/.ssh. Gdy w odchudzonej instalacji brakuje restorecon, doinstaluje go dnf install -y policycoreutils. Dowody znajdziesz w logu audytu, dostępnym przez ausearch -m avc -ts recent.
Co oznacza „no mutual signature algorithm”?
Klient to OpenSSH 8.8 lub nowszy i odrzuca podpisy RSA z SHA-1, a serwer po drugiej stronie zna wyłącznie stare ssh-rsa. Na jednorazowy dostęp pomaga opcja PubkeyAcceptedAlgorithms=+ssh-rsa razem z HostKeyAlgorithms=+ssh-rsa. Czystym rozwiązaniem jest aktualizacja starego serwera: twój klucz RSA działa potem bez zmian, zmienia się tylko metoda podpisu.
Moja zmiana w /etc/ssh/sshd_config nie działa. Z czego to wynika?
Na Debianie od wersji 12 i Ubuntu od 22.04 na samej górze znajduje się wiersz Include /etc/ssh/sshd_config.d/*.conf. Ponieważ sshd bierze dla każdego słowa kluczowego wartość znalezioną jako pierwsza, każdy plik w tym katalogu przebija plik główny. Miarodajny jest zawsze wynik sshd -T, a nie zawartość samego pliku.
Jak wrócić na serwer, jeśli zablokowałem sobie dostęp?
Przez konsolę VNC w panelu klienta logujesz się hasłem roota bezpośrednio na maszynie, całkiem bez SSH. Jeśli sshd w ogóle już nie startuje, bootujesz do systemu ratunkowego, montujesz główny system plików i poprawiasz authorized_keys, uprawnienia oraz właściciela bezpośrednio na dysku.

SSH OpenSSH Rozwiązywanie problemów Linux Administracja serwerem Uwierzytelnianie SELinux Debian Ubuntu AlmaLinux