O cheie SSH înlocuiește parola la conectarea pe server. Generezi pe calculatorul tău o pereche de chei, pui partea publică pe server, iar de acolo te autentifici fără să mai trimiți vreo parolă prin rețea. Ghidul e pentru cine administrează singur un server Linux, de exemplu un VPS Self, unde ai root complet și răspunzi tu de sistem și de aplicații.
Pașii sunt testați pe Ubuntu 24.04 LTS. Unde Debian 12/13 sau AlmaLinux/Rocky Linux 9 se comportă altfel, găsești o notă scurtă.
Pe scurt
- Pe calculatorul tău:
ssh-keygen -t ed25519 -C "eticheta-ta", cu o frază de acces (passphrase). - Copiezi cheia publică pe server:
ssh-copy-id utilizator@203.0.113.10(sau manual, în~/.ssh/authorized_keys). - Verifici că intri cu cheia, într-o sesiune nouă, fără să o închizi pe cea veche.
- Pe server, într-un fișier din
/etc/ssh/sshd_config.d/:PasswordAuthentication noșiPermitRootLogin no, apoisudo sshd -tșisudo systemctl reload ssh. - Instalezi fail2ban, care blochează adresele ce greșesc login-ul de mai multe ori la rând.
De ce cheie și nu parolă
Orice server cu portul 22 deschis spre internet primește încercări automate de login, zi și noapte. O parolă poate fi ghicită, refolosită din altă scurgere de date sau furată de un keylogger. O cheie ed25519 nu se poate ghici în practică, iar partea privată nu pleacă niciodată de pe calculatorul tău: serverul verifică doar că o deții.
Perechea are două fișiere:
- cheia privată (
~/.ssh/id_ed25519) rămâne la tine și nu se trimite nimănui; - cheia publică (
~/.ssh/id_ed25519.pub) se pune pe orice server la care vrei acces.
Ca să aibă efect complet, după ce cheia funcționează oprești autentificarea cu parolă. Altfel, atacatorii pot încerca în continuare parole.
Cerințe
- Un server cu Ubuntu 24.04 (sau Debian 12/13, AlmaLinux/Rocky 9) și acces SSH cu parolă, deocamdată.
- Un utilizator cu drept de
sudope server, nu doarroot. Dacă nu l-ai creat încă, urmează întâi configurarea inițială a unui server Ubuntu. - Pe calculatorul tău: un terminal cu OpenSSH. Linux și macOS îl au din start; Windows 10 și 11 au clientul OpenSSH inclus, accesibil din PowerShell.
În exemple, utilizator e numele contului de pe server, iar 203.0.113.10 e adresa IP a serverului. Înlocuiește-le cu ale tale.
Pasul 1: generezi perechea de chei
Comanda se rulează pe calculatorul tău, nu pe server:
ssh-keygen -t ed25519 -C "utilizator@laptop"
-t ed25519 alege tipul de cheie, scurt și rapid, suportat de orice OpenSSH din ultimii ani. -C pune o etichetă în cheia publică, ca să știi mai târziu de pe ce dispozitiv vine (de exemplu ana@laptop-birou).
Programul te întreabă două lucruri:
- Unde salvează cheia. Apasă Enter pentru locul implicit,
~/.ssh/id_ed25519. Dacă fișierul există deja, răspundenlaOverwrite (y/n)?și rulează din nou comanda cu alt nume, de exemplu-f ~/.ssh/id_ed25519_vps; altfel suprascrii cheia veche și pierzi accesul pe serverele unde era folosită. - Fraza de acces (passphrase). Pune una. Dacă cineva îți copiază cheia privată de pe laptop, fără frază nu o poate folosi.
Verifici că ai ambele fișiere:
ls -l ~/.ssh/id_ed25519 ~/.ssh/id_ed25519.pub
Cheia privată trebuie să aibă permisiunile -rw------- (600). ssh-keygen le setează singur.
Dacă trebuie să te conectezi la un sistem foarte vechi, care nu cunoaște ed25519, generează o cheie RSA de 4096 de biți, într-un fișier separat:
ssh-keygen -t rsa -b 4096 -C "utilizator@laptop" -f ~/.ssh/id_rsa_vechi
Nu vrei să scrii fraza la fiecare conectare: ssh-agent
ssh-agent ține cheia deblocată în memorie cât timp ești logat. Pe Ubuntu Desktop și pe macOS rulează deja un agent, pornit de sesiunea grafică. Într-un terminal unde nu rulează, îl pornești și adaugi cheia așa:
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_ed25519
ssh-add cere fraza o singură dată. Vezi ce chei are agentul încărcate cu:
ssh-add -l
Pasul 2: copiezi cheia publică pe server
Varianta simplă: ssh-copy-id
Din Linux sau macOS:
ssh-copy-id -i ~/.ssh/id_ed25519.pub utilizator@203.0.113.10
La prima conectare vezi amprenta serverului și răspunzi yes, apoi introduci parola contului de pe server (nu fraza cheii). ssh-copy-id creează ~/.ssh/authorized_keys pe server, cu permisiunile corecte, și nu adaugă cheia a doua oară dacă e deja acolo.
Varianta manuală
Dacă nu ai ssh-copy-id, afișezi cheia publică pe calculatorul tău și o copiezi (un singur rând, începe cu ssh-ed25519):
cat ~/.ssh/id_ed25519.pub
Apoi, pe server, logat cu utilizatorul pentru care pui cheia:
mkdir -p ~/.ssh
chmod 700 ~/.ssh
nano ~/.ssh/authorized_keys
Lipești rândul cheii publice pe o linie nouă, salvezi (Ctrl+O, Enter) și ieși (Ctrl+X). Apoi:
chmod 600 ~/.ssh/authorized_keys
Permisiunile nu sunt un detaliu: dacă directorul home, ~/.ssh sau authorized_keys pot fi scrise de alți utilizatori, serverul ignoră cheia fără să-ți spună de ce, iar clientul trece la parolă.
Același lucru, dintr-o singură comandă rulată de pe calculatorul tău:
cat ~/.ssh/id_ed25519.pub | ssh utilizator@203.0.113.10 "mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"
Din Windows 10 sau 11
Clientul OpenSSH e inclus în Windows. Deschide PowerShell (nu e nevoie de drepturi de administrator) și generezi cheia la fel:
ssh-keygen -t ed25519 -C "utilizator@pc-windows"
Cheile ajung în C:\Users\<nume>\.ssh\. Windows nu are ssh-copy-id, așa că trimiți cheia publică printr-o conexiune SSH obișnuită, tot din PowerShell:
type $env:USERPROFILE\.ssh\id_ed25519.pub | ssh utilizator@203.0.113.10 "mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"
Îți cere parola contului de pe server, o singură dată. Din acel moment, ssh utilizator@203.0.113.10 din PowerShell folosește cheia.
Dacă vrei ca Windows să țină fraza cheii, serviciul ssh-agent e oprit implicit. Îl pornești dintr-un PowerShell deschis ca administrator:
Get-Service ssh-agent | Set-Service -StartupType Automatic
Start-Service ssh-agent
Apoi adaugi cheia dintr-o fereastră PowerShell obișnuită:
ssh-add $env:USERPROFILE\.ssh\id_ed25519
Pasul 3: verifici că intri cu cheia
Nu închide sesiunea SSH în care ești deja conectat. Deschide un terminal nou și conectează-te:
ssh utilizator@203.0.113.10
Dacă ți se cere fraza cheii (sau nimic, când cheia e în agent), cheia funcționează. Dacă ți se cere parola contului de pe server, cheia nu a fost acceptată: vezi secțiunea „Probleme frecvente” de mai jos înainte să mergi mai departe.
Poți confirma exact metoda folosită:
ssh -v utilizator@203.0.113.10 exit 2>&1 | grep "Authenticated"
Rândul afișat trebuie să se termine în using "publickey".
Pasul 4: oprești autentificarea cu parolă
Abia acum, cu cheia verificată, închizi ușa pentru parole. Pe Ubuntu 24.04 nu editezi /etc/ssh/sshd_config direct: fișierul principal include la început tot ce e în /etc/ssh/sshd_config.d/*.conf, iar la majoritatea opțiunilor câștigă prima valoare citită. Un fișier propriu în acel director e mai curat și nu intră în conflict cu actualizările pachetului.
Capcana 50-cloud-init.conf
Pe multe imagini de server, cloud-init a lăsat un fișier /etc/ssh/sshd_config.d/50-cloud-init.conf care conține PasswordAuthentication yes. Fișierele se citesc în ordine alfabetică, deci dacă îți pui setarea într-un fișier numit, să zicem, 60-securizare.conf, valoarea din 50-cloud-init.conf e citită prima și câștigă: parola rămâne activă, fără nicio eroare. Vezi ce ai în director:
ls /etc/ssh/sshd_config.d/
sudo grep -ri "passwordauthentication" /etc/ssh/sshd_config /etc/ssh/sshd_config.d/
Soluția e să îți numești fișierul astfel încât să fie citit primul, de exemplu cu prefixul 00-.
Fișierul de configurare
sudo nano /etc/ssh/sshd_config.d/00-securizare.conf
Conținutul:
PasswordAuthentication no
KbdInteractiveAuthentication no
PubkeyAuthentication yes
PermitRootLogin no
PermitRootLogin no oprește complet login-ul direct ca root, chiar și cu cheie; lucrezi cu utilizatorul tău și sudo. Dacă ai nevoie de root prin SSH (de exemplu pentru un script de backup care vine de pe alt server), pune în loc PermitRootLogin prohibit-password: root poate intra doar cu cheie, niciodată cu parolă. În sshd -T valoarea apare sub vechiul ei nume, without-password; e același lucru.
Verifici sintaxa. Dacă nu afișează nimic, fișierul e corect:
sudo sshd -t
Dacă lucrezi din consolă și nu s-a conectat nimeni prin SSH de la pornire, sshd -t poate afișa Missing privilege separation directory: /run/sshd. Nu e o eroare de configurare: directorul îl creează serviciul ssh când pornește. Îl creezi cu sudo mkdir -p /run/sshd sau pornești serviciul cu sudo systemctl start ssh, apoi repeți testul.
Apoi verifici ce valori folosește efectiv serverul, după ce a citit toate fișierele:
sudo sshd -T | grep -E "^(passwordauthentication|kbdinteractiveauthentication|pubkeyauthentication|permitrootlogin) "
Trebuie să vezi:
permitrootlogin no
pubkeyauthentication yes
passwordauthentication no
kbdinteractiveauthentication no
Dacă passwordauthentication e încă yes, un alt fișier din sshd_config.d/ îl setează înaintea ta.
Aplici modificarea
sudo systemctl reload ssh
Pe Ubuntu 24.04 serviciul se numește ssh (nu sshd) și e activat prin socket: ssh.socket ascultă pe portul 22 și pornește ssh.service la prima conexiune, după care serviciul rămâne pornit. Ce înseamnă asta în practică:
- Pentru opțiuni de autentificare (parolă, root, chei),
reloade suficient, iar sesiunile deschise rămân deschise. Dacă primeștissh.service is not active, cannot reload., nimeni nu s-a conectat încă de la pornire și nu ai ce reîncărca: serviciul va citi configurația nouă la prima conexiune. - Pentru
Port,ListenAddresssauAddressFamily, portul pe care se ascultă nu îl deschidesshd, cissh.socket. Un generator systemd citește aceste valori din configurația SSH, dar numai ladaemon-reload. Deci, după ce schimbi portul:
sudo systemctl daemon-reload
sudo systemctl restart ssh.socket
Doar reload nu mută portul: serverul continuă să asculte pe 22 până la restart ssh.socket. Sesiunea în care ești conectat nu se închide la restart, dar conexiunile noi merg doar pe portul nou. Dacă ai firewall, deschide noul port înainte de restart (pe Ubuntu cu UFW, sudo ufw allow 2222/tcp, unde 2222 e portul ales). De acolo te conectezi cu ssh -p 2222 utilizator@203.0.113.10 sau pui Port 2222 în aliasul de la pasul 6.
Pe Debian 12 și 13 serviciul se numește tot ssh, dar pornește clasic, fără socket (ssh.socket există, dar nu e activat): sudo systemctl reload ssh aplică orice modificare, inclusiv portul. Pe orice sistem verifici în ce mod rulează cu systemctl is-enabled ssh.socket ssh.service.
Pe AlmaLinux / Rocky Linux 9 serviciul se numește sshd (sudo systemctl reload sshd), iar directorul sshd_config.d/ funcționează la fel. Acolo găsești 50-redhat.conf și, în funcție de imagine, poate exista și un fișier *-permitrootlogin.conf (01- sau 25-) cu PermitRootLogin yes. Fișierul tău cu prefixul 00- e citit înaintea lor, deci câștigă, dar confirmă oricum cu sudo sshd -T. La schimbarea portului, SELinux și firewalld trebuie anunțate și ele (semanage port și firewall-cmd).
Testul final
Din alt terminal, forțează o încercare cu parolă:
ssh -o PubkeyAuthentication=no -o PreferredAuthentications=password utilizator@203.0.113.10
Răspunsul corect e refuzul imediat, fără să ți se ceară parola:
utilizator@203.0.113.10: Permission denied (publickey).
Apoi conectează-te normal, cu cheia, ca să confirmi că accesul tău a rămas. Abia după aceea închide sesiunea veche.
Pasul 5: fail2ban blochează încercările repetate
Fără parolă, încercările de login nu mai au șanse, dar tot umplu jurnalele și consumă resurse. fail2ban citește jurnalul SSH și blochează din firewall, pentru un timp, adresele care greșesc de prea multe ori.
sudo apt update
sudo apt install fail2ban
Pe Ubuntu 24.04, pachetul vine cu /etc/fail2ban/jail.d/defaults-debian.conf, care activează deja jail-ul sshd cu backend = systemd (citește direct din jurnalul systemd) și blocare prin nftables. Nu modifici fișierele pachetului; pui ajustările tale în jail.local, care e citit după ele:
sudo nano /etc/fail2ban/jail.local
[DEFAULT]
bantime = 1h
findtime = 10m
maxretry = 5
ignoreip = 127.0.0.1/8 ::1
[sshd]
enabled = true
backend = systemd
Dacă ai mutat SSH pe alt port (pasul 4), adaugă în secțiunea [sshd] și rândul port = 2222, cu portul tău. Altfel fail2ban blochează doar portul 22, iar adresa blocată ajunge în continuare la SSH pe portul nou. Regula e aceeași pe Debian și pe AlmaLinux/Rocky.
Dacă te conectezi mereu de la o adresă IP fixă (birou, VPN), adaug-o la ignoreip, separată prin spațiu, ca să nu te blochezi singur.
Verifici configurația, pornești serviciul și te uiți la jail:
sudo fail2ban-client -t
sudo systemctl enable fail2ban
sudo systemctl restart fail2ban
sudo fail2ban-client status sshd
Dacă fail2ban-client -t afișează WARNING 'allowipv6' not defined in 'Definition', e inofensiv; contează linia OK: configuration test is successful.
În Banned IP list apar adresele blocate. Pentru ele, portul SSH răspunde cu Connection refused până expiră bantime. Dacă ai blocat din greșeală o adresă, o scoți așa:
sudo fail2ban-client set sshd unbanip 198.51.100.7
Pe Debian 12, fișierul implicit doar activează jail-ul, fără backend; cum Debian 12 nu scrie /var/log/auth.log decât dacă ai instalat rsyslog, rândul backend = systemd din jail.local e cel care face fail2ban să pornească. Asta nu ajunge, însă: acțiunea implicită de blocare pe Debian 12 folosește iptables, care nu e instalat (vine doar nftables). fail2ban pornește, adresa apare în Banned IP list, dar în /var/log/fail2ban.log apare iptables: not found și nu se creează nicio regulă de firewall, deci adresa ajunge în continuare la SSH. Pe Debian 12 adaugi în secțiunea [DEFAULT] din jail.local și aceste două rânduri:
banaction = nftables
banaction_allports = nftables[type=allports]
După primul ban, verifici că regula există cu adevărat:
sudo nft list ruleset
Trebuie să apară tabela f2b-table, cu adresa blocată în setul addr-set-sshd. Debian 13 vine configurat ca Ubuntu, cu nftables, și nu are nevoie de cele două rânduri. Nu le pune nici pe AlmaLinux/Rocky: acolo ar înlocui blocarea prin firewalld. Pe AlmaLinux / Rocky 9, fail2ban vine din EPEL, cu blocare prin firewalld; jail-ul sshd nu e activat implicit, așa că jail.local de mai sus e necesar:
sudo dnf install epel-release
sudo dnf install fail2ban fail2ban-firewalld
Pasul 6: un alias în ~/.ssh/config
Ca să nu scrii de fiecare dată utilizatorul, adresa și portul, creezi pe calculatorul tău fișierul ~/.ssh/config:
nano ~/.ssh/config
Host vps-bts
HostName 203.0.113.10
User utilizator
Port 22
IdentityFile ~/.ssh/id_ed25519
IdentitiesOnly yes
chmod 600 ~/.ssh/config
ssh vps-bts
IdentitiesOnly yes face clientul să ofere doar cheia indicată. Fără el, dacă agentul are multe chei încărcate, serverul poate închide conexiunea după prea multe încercări, înainte să ajungă la cheia bună. Aliasul funcționează și cu scp, rsync sau sftp: scp fisier.txt vps-bts:/tmp/. Pe Windows, fișierul este C:\Users\<nume>\.ssh\config, cu același conținut.
Probleme frecvente
Serverul îți cere parola deși ai copiat cheia. Aproape mereu sunt permisiunile sau proprietarul. Pe server:
ls -ld ~ ~/.ssh ~/.ssh/authorized_keys
~/.ssh trebuie să fie drwx------ (700), authorized_keys -rw------- (600), ambele deținute de utilizatorul tău, iar directorul home nu trebuie să poată fi scris de alți utilizatori. Dacă ai creat fișierele ca root, cu sudo, corectează proprietarul:
sudo chown -R utilizator:utilizator /home/utilizator/.ssh
Motivul exact apare în jurnalul serverului:
sudo journalctl -u ssh -n 50
Două mesaje apar des:
Could not open user 'utilizator' authorized keys '/home/utilizator/.ssh/authorized_keys': Permission denied: fișierele au alt proprietar, de obicei root, pentru că le-ai creat cusudo. Se rezolvă cuchown-ul de mai sus.Authentication refused: bad ownership or modes for directory /home/utilizator/.ssh: directorul indicat (~/.sshsau chiar home-ul) poate fi scris de alți utilizatori. Îl repari cuchmod 700 ~/.ssh, respectivchmod go-w ~.
Pe AlmaLinux/Rocky unitatea se numește sshd, iar SELinux poate bloca un authorized_keys creat în alt loc și mutat; restorecon -Rv ~/.ssh îi reface contextul.
„Too many authentication failures”. Clientul a oferit prea multe chei din agent. Adaugă IdentitiesOnly yes și IdentityFile în ~/.ssh/config, ca la pasul 6.
„WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!”. Apare când serverul a fost reinstalat și are chei de host noi. Dacă știi sigur că l-ai reinstalat, ștergi amprenta veche de pe calculatorul tău:
ssh-keygen -R 203.0.113.10
Dacă nu ai reinstalat nimic, nu ignora mesajul: poate însemna că vorbești cu alt server decât crezi.
Parola încă merge după pasul 4. Un fișier din /etc/ssh/sshd_config.d/ o reactivează înaintea ta (de obicei 50-cloud-init.conf) sau nu ai făcut reload. sudo sshd -T | grep passwordauthentication îți spune valoarea efectivă.
Ai pierdut cheia privată. Cu parola dezactivată, nu mai intri prin SSH. Ai nevoie de acces la consola serverului, în afara SSH, ca să pui o cheie nouă în authorized_keys. De aceea merită să ai cheia pe două dispozitive (două chei diferite, fiecare cu rândul ei în authorized_keys) sau o copie de rezervă a cheii private, protejată de frază. Pe un VPS BTS, dacă ai rămas fără acces, deschide un tichet la suport.
Rezumat
- Generezi cheia cu
ssh-keygen -t ed25519 -C "eticheta", cu frază de acces, și foloseștissh-agentca să nu o scrii mereu. - Pui cheia publică pe server cu
ssh-copy-idsau manual, cu~/.sshla 700 șiauthorized_keysla 600. Din Windows, o trimiți printype ... | ssh .... - Testezi login-ul cu cheia într-o sesiune nouă, apoi dezactivezi parola într-un fișier
00-din/etc/ssh/sshd_config.d/, verifici cusshd -tșisshd -T, și daisystemctl reload ssh. - Pe Ubuntu 24.04, schimbarea portului cere
daemon-reloadșirestart ssh.socket, nu doar reload. - fail2ban, cu jail-ul
sshdpebackend = systemd, blochează adresele care insistă.
Pentru restul pașilor de după instalare (utilizator cu sudo, firewall, actualizări automate), continuă cu configurarea inițială a unui server Ubuntu. Toate opțiunile serverului sunt descrise în manualele OpenSSH, iar particularitățile Ubuntu în documentația OpenSSH server de pe ubuntu.com.



