Cambiare la porta SSH con SELinux e firewalld
Su Rocky Linux e AlmaLinux, cambia la porta di sshd nell'ordine corretto: firewalld, etichetta SELinux e sshd_config, evitando di perdere l'accesso.
Perché qui la modifica della porta SSH richiede tre passaggi
Per modificare la porta SSH su Rocky Linux, AlmaLinux, CentOS Stream o Fedora, una sola modifica non è sufficiente. Tre sistemi distinti determinano se una connessione sulla nuova porta può funzionare. firewalld stabilisce se il pacchetto può raggiungere la macchina. SELinux stabilisce se sshd può eseguire il bind su quel numero di porta. sshd_config stabilisce quale porta richiede il demone. Se si salta il passaggio relativo a SELinux, il demone non si avvia. Se si salta il passaggio relativo a firewalld, il demone si avvia e resta in ascolto, ma nessuno può raggiungerlo.
Su Ubuntu la stessa operazione richiede una sola modifica e un riavvio, perché Ubuntu usa AppArmor invece di SELinux e non include alcun profilo che limiti le porte su cui sshd può eseguire il bind. Se ufw è in esecuzione, è necessario aggiungere una regola. Questa è l'unica differenza. Nella famiglia RHEL, firewalld è in esecuzione e SELinux è in modalità enforcing dopo una nuova installazione; entrambi considerano i numeri di porta.
Eseguire le operazioni in questo ordine mantiene attiva la sessione corrente durante tutti i passaggi:
- Aprire la nuova porta in firewalld, lasciando per il momento aperta la porta 22.
- Aggiungere l'etichetta SELinux per la nuova porta con
semanage. - Impostare la porta nella configurazione di sshd.
- Riavviare
sshd, quindi accedere sulla nuova porta da un secondo terminale prima di chiudere il primo.
Individuare la console web del provider (VNC o seriale) prima di iniziare e verificare di potervi accedere. Questa console consente di ripristinare l'accesso se la modifica causa problemi. La modifica di una porta è uno dei motivi più comuni per cui un tenant perde l'accesso a un server appena acquistato.
Per prima cosa, installare semanage
semanage è lo strumento che modifica le impostazioni delle policy SELinux. Un'installazione minima di Rocky Linux o AlmaLinux non lo include. Il pacchetto si trova in policycoreutils-python-utils.
sudo dnf install -y policycoreutils-python-utilsEseguendo il comando prima di installare il pacchetto si ottiene sudo: semanage: command not found. È a questo punto che molti lettori concludono che SELinux non sia installato e saltano il passaggio. SELinux è installato. Manca soltanto lo strumento di gestione. Se la sintassi dnf è nuova, gli equivalenti dei comandi dnf e apt consentono di ricondurla a comandi già noti.
Scegli una porta e verifica che non sia già utilizzata
È sufficiente una porta TCP libera compresa tra 1024 e 65535. Esegui questi due controlli prima di sceglierne una:
sudo ss -tlnp | grep -w 2222
sudo semanage port -l | grep -w 2222Il primo comando verifica se un processo è già in ascolto su quel numero. Il secondo verifica se la policy SELinux lo assegna già a un altro tipo di servizio. Una porta libera non restituisce alcun risultato in nessuno dei due controlli. Se la policy la utilizza già, semanage port -a nel passaggio 2 fallisce con ValueError: Port tcp/2222 already defined. In questo caso, scegli un altro numero.
In questa guida viene usata 2222 come esempio. È anche la prima porta che uno scanner prova dopo la 22, quindi su un server reale scegli un numero meno prevedibile.
Passaggio 1: aprire la porta in firewalld
sudo firewall-cmd --permanent --add-port=2222/tcp
sudo firewall-cmd --reload
sudo firewall-cmd --list-ports--permanent scrive la regola nel file della zona sul disco e non modifica il firewall in esecuzione. --reload carica la configurazione presente sul disco nel firewall in esecuzione. Se si omette il reload, la regola esiste ma non ha effetto fino al successivo riavvio di firewalld. Questo è uno dei motivi più comuni per cui l'intera procedura sembra non funzionare senza una causa apparente.
Per ora, lascia invariata la voce del servizio ssh. Questa voce mantiene aperta la porta 22 e costituisce il fallback durante i test.
Controlla anche il pannello di controllo del provider. Molti provider applicano un firewall di rete davanti al VPS, esterno al sistema operativo. Di conseguenza, una porta aperta in firewalld può essere comunque bloccata a monte. La guida di base a firewalld per un VPS illustra le zone e la distinzione tra configurazione runtime e permanente, se questo modello non ti è familiare.
Passaggio 2: assegnare un'etichetta alla porta per SELinux
sudo semanage port -a -t ssh_port_t -p tcp 2222
sudo semanage port -l | grep ssh_port_t-a aggiunge una nuova assegnazione alla porta. -t ssh_port_t è il tipo associato alle porte SSH. Il secondo comando elenca tutto ciò che ssh_port_t comprende ora, così puoi verificare che il numero sia stato aggiunto prima di modificare il demone.
Perché SELinux blocca la porta
SELinux (Security-Enhanced Linux) assegna un'etichetta a ogni oggetto del sistema, e i numeri delle porte TCP sono oggetti come gli altri. Il demone SSH viene eseguito in un dominio confinato chiamato sshd_t. La policy consente a sshd_t di associarsi alle porte TCP con etichetta ssh_port_t e, nella configurazione predefinita, l'unica porta con questa etichetta è la 22. Se si chiede al demone di associarsi alla porta 2222, il kernel controlla l'etichetta, rileva il tipo generico assegnato dalla policy a quel numero e rifiuta il permesso name_bind sul socket.
Per questo il problema non ha l'aspetto di un problema del firewall. Il kernel rifiuta l'operazione prima che esista un socket in ascolto, quindi sshd segnala l'errore e termina. Un problema del firewall è l'immagine speculare: il demone è in esecuzione e funziona correttamente, ma i pacchetti vengono scartati durante il percorso in ingresso.
getenforce indica la modalità attiva sul sistema. In Permissive un rifiuto viene registrato ma non applicato. Perciò la modifica della porta sembra funzionare, ma poi il servizio si interrompe quando qualcuno esegue setenforce 1 o quando il sistema si riavvia in modalità enforcing. Etichettare la porta in ogni caso. La guida di base a SELinux per i server descrive in dettaglio modalità, contesti e booleani.
Passaggio 3: impostare la porta nella configurazione di sshd
Su Rocky Linux 9 e 10, AlmaLinux 9 e 10 e nelle versioni correnti di Fedora, /etc/ssh/sshd_config inizia con una direttiva include. Il punto più ordinato per la modifica è quindi un file drop-in. Gli aggiornamenti dei pacchetti non sovrascriveranno mai la modifica.
grep -n '^Include' /etc/ssh/sshd_config
echo 'Port 2222' | sudo tee /etc/ssh/sshd_config.d/10-port.conf
sudo sshd -tSe grep non trova alcuna direttiva Include, come accade su Rocky Linux 8 e su altre immagini meno recenti, inserire direttamente Port 2222 in /etc/ssh/sshd_config. sshd -t analizza l'intera configurazione, inclusi i file drop-in, e segnala gli errori di sintassi. Correggere ogni errore segnalato prima del riavvio, perché una configurazione che non può essere analizzata impedisce al demone di avviarsi nuovamente.
Port può comparire più di una volta e sshd resta in ascolto su ogni porta indicata. Mantenere Port 22 insieme a Port 2222 per il primo giorno è una semplice misura di sicurezza, purché ci si ricordi di rimuoverlo.
Il servizio sshd viene avviato da una socket unit?
Alcune immagini avviano SSH tramite l’attivazione socket di systemd invece che come servizio a esecuzione continua. In questo caso, systemd gestisce la socket in ascolto e passa le connessioni a sshd, quindi la riga Port in sshd_config viene completamente ignorata. Verifica questa condizione prima di riavviare qualsiasi componente:
systemctl is-enabled sshd.socketUna risposta enabled indica che la porta è impostata nella socket unit e non in sshd_config:
sudo systemctl edit sshd.socket[Socket]
ListenStream=
ListenStream=2222Il valore ListenStream= senza argomenti è necessario. I valori si sommano tra i diversi drop-in. Senza un’assegnazione vuota che cancelli prima l’elenco, la socket continuerà ad ascoltare sia sulla porta 22 sia sulla porta 2222. Applica la modifica con sudo systemctl daemon-reload, quindi esegui sudo systemctl restart sshd.socket. Se la unit è disabilitata o non è presente sul server, questa sezione non è applicabile.
Passaggio 4: riavviare, quindi verificare da un secondo terminale
sudo systemctl restart sshd
systemctl status sshd
sudo ss -tlnp | grep sshdLascia aperto questo terminale. Non disconnetterti. Apri un secondo terminale sul tuo computer e connettiti alla nuova porta:
ssh -p 2222 youruser@203.0.113.10Chiudi la prima sessione solo dopo che il secondo accesso è riuscito. Se non funziona, hai ancora una shell da cui puoi annullare tutte le modifiche. Questa semplice procedura distingue una modifica di cinque minuti da un pomeriggio trascorso nella console del provider.
Firewall drop o diniego SELinux? Come distinguerli
Dal laptop, i due errori sembrano quasi identici. Sul server, invece, hanno cause completamente diverse.
- Se
systemctl status sshdindica che l'unità è fallita, il demone non ha mai ottenuto il proprio socket. Si tratta di un errore di configurazione o di un diniego SELinux. - Se l'unità è attiva e
ss -tlnpmostra sshd in ascolto sulla nuova porta, il demone funziona correttamente e il problema si trova nel percorso di rete: firewalld, il firewall separato del provider oppure l'indirizzo e la porta utilizzati per la connessione.
Nel caso di SELinux, leggi il record di audit invece di procedere per ipotesi:
sudo ausearch -m AVC -ts recent
sudo journalctl -u sshd -n 50 --no-pagerUn diniego name_bind sulla classe tcp_socket indica il processo in comm="sshd", il numero di porta in src= e l'etichetta effettivamente assegnata alla porta in tcontext=. Quest'ultimo campo fornisce la risposta. Qualsiasi valore diverso da ssh_port_t indica che il passaggio 2 non è stato applicato alla porta in uso, di solito a causa di un errore nel numero o dell'uso del protocollo sbagliato. Installa setroubleshoot-server se preferisci che sealert trasformi il record in una frase.
Il messaggio scritto da sshd quando il kernel rifiuta il bind è simile al seguente:
error: Bind to port 2222 on 0.0.0.0 failed: Permission denied.Permission denied su una porta superiore a 1024, per la quale non sono necessari privilegi root per eseguire il bind, è la firma di SELinux. Address already in use nella stessa riga indica invece un problema diverso: un altro processo sta utilizzando la porta. Dal lato client, la differenza tra connessione rifiutata e timeout della connessione consente di distinguere i due casi di rete: un rifiuto indica che il pacchetto ha raggiunto l'host e che nessun processo era in ascolto, mentre un timeout indica che non ha risposto nulla.
Chiudere la porta 22 e aggiornare i client
Dopo aver verificato che diversi accessi sulla nuova porta abbiano funzionato, rimuovere la porta 22:
sudo firewall-cmd --permanent --remove-service=ssh
sudo firewall-cmd --reload
sudo firewall-cmd --list-allLasciare invariata l'etichetta SELinux sulla porta 22. Proviene dalla policy di base e non concede nulla quando il firewall non consente più l'ingresso dei pacchetti.
Aggiornare quindi i client, perché ogni strumento che presupponeva la porta predefinita deve ora ricevere questa informazione. Inserirla una sola volta in ~/.ssh/config sul proprio computer, invece di digitare continuamente -p:
Host myvps
HostName 203.0.113.10
Port 2222
User youruserscp, sftp, rsync e Ansible leggono quel file. I processi di backup, i controlli di monitoraggio e gli script cron che specificano direttamente la porta 22 non lo fanno. Individuarli mentre la modifica è ancora recente.
Cosa comporta e cosa non comporta cambiare la porta
Riduce il rumore nei log. Gli scanner automatici colpiscono continuamente la porta 22 e spostare il servizio su un'altra porta elimina la maggior parte di queste righe dal journal, rendendo più visibili gli eventi reali. Non è una misura di sicurezza. Qualsiasi scanner che esegua una scansione completa dell'intervallo di porte individua il daemon e legge comunque il relativo banner della versione. Considera il cambio di porta un'attività di manutenzione e applica la protezione effettiva usando l'autenticazione basata esclusivamente su chiavi e disabilitando gli accessi con password, come illustrato passo per passo nella guida alla messa in sicurezza di SSH per un VPS.
Tutto quanto descritto sopra funziona nello stesso modo su entrambe le principali distribuzioni RHEL derivate, perché sono compilate a partire dagli stessi sorgenti. Se devi ancora scegliere tra le due, consulta Confronto tra Rocky Linux e AlmaLinux. Prima di seguire una guida meno recente, verifica quale release ti è stata effettivamente assegnata usando cat /etc/os-release. Le guide scritte per Rocky Linux 8 continuano a comparire tra i primi risultati e le relative procedure semanage e firewall-cmd restano corrette, ma Rocky 8 non contiene alcuna direttiva include sshd_config.d né una socket unit da considerare; per questo, la parte di quelle guide relativa a sshd non corrisponde a un sistema attuale.
fail2ban deve essere configurato per il nuovo port
fail2ban non è incluso nei repository di base. Viene fornito da EPEL (extra packages for enterprise Linux):
sudo dnf install -y epel-release
sudo dnf install -y fail2ban fail2ban-firewalldIl sottopacchetto fail2ban-firewalld fa in modo che fail2ban applichi i ban tramite firewalld. È la scelta corretta su un server in cui firewalld gestisce il ruleset.
La jail sshd predefinita imposta port = ssh. Questo nome viene risolto tramite /etc/services nell’indirizzo 22. Dopo la modifica, la jail monitora un port che nessuno sta attaccando. Di conseguenza non applica ban, mentre i tentativi di accesso non riusciti si accumulano sul port 2222. Imposta il port tramite il numero in /etc/fail2ban/jail.local:
[sshd]
enabled = true
port = 2222
backend = systemd
maxretry = 5
bantime = 3600backend = systemd legge i tentativi falliti dal journal invece che da /var/log/secure. È la scelta più sicura in un’installazione minimale, dove rsyslog potrebbe non essere presente. Avvialo con sudo systemctl enable --now fail2ban e controlla la jail con sudo fail2ban-client status sshd. La sintassi della jail è la stessa usata in la configurazione di fail2ban per SSH su Ubuntu 24.04. Differiscono soltanto l’origine del pacchetto e l’azione di ban.
L'applicazione delle patch conta più della porta
Un server con la porta SSH modificata e quattro mesi di aggiornamenti di sicurezza non applicati è più esposto di un server che usa la porta 22 ma installa automaticamente le patch ogni notte. Attiva gli aggiornamenti automatici nella stessa sessione, mentre hai già effettuato l'accesso come root: aggiornamenti automatici di dnf su Rocky Linux e AlmaLinux illustra la configurazione del timer e la scelta tra scaricare gli aggiornamenti e applicarli.
FAQ
Perché sshd non si avvia dopo aver cambiato la porta su Rocky Linux?
Quasi sempre manca l'etichetta della porta SELinux. sshd viene eseguito nel dominio sshd_t e la policy consente di associarlo solo a porte con etichetta ssh_port_t, che per impostazione predefinita corrisponde esclusivamente alla porta 22. Il kernel rifiuta l'associazione, quindi il demone termina invece di mettersi in ascolto e journalctl -u sshd contiene una riga del tipo error: Bind to port 2222 on 0.0.0.0 failed: Permission denied.. Esegui sudo semanage port -a -t ssh_port_t -p tcp 2222 usando il numero della tua porta, quindi riavvia il servizio. Se semanage non è disponibile, installa prima policycoreutils-python-utils.
Devo usare semanage anche se SELinux è in modalità permissiva?
Sì. In modalità permissiva il rifiuto viene registrato, ma l'associazione viene comunque consentita, quindi sembra che la modifica abbia funzionato. L'etichetta continua a mancare. Non appena qualcuno esegue setenforce 1, oppure il sistema avvia SELINUX=enforcing in /etc/selinux/config, sshd smette di avviarsi su quella porta. Aggiungere l'etichetta richiede un solo comando ed evita un errore che altrimenti potrebbe manifestarsi dopo settimane senza una causa evidente.
La porta ha l'etichetta corretta e sshd è in esecuzione: perché la connessione va in timeout?
Un demone in esecuzione indica che SELinux non sta bloccando la porta, quindi il pacchetto viene scartato durante il percorso in ingresso. Controlla sudo firewall-cmd --list-ports per verificare la tua porta e assicurati di aver eseguito firewall-cmd --reload dopo la regola --permanent, perché una regola permanente, da sola, non viene applicata al firewall in esecuzione. Controlla quindi il pannello di controllo del tuo host per verificare la presenza di un firewall di rete separato davanti al VPS. È il secondo punto in cui le connessioni vengono spesso bloccate e il sistema operativo non può mostrare questo problema.
Quale porta devo usare al posto della 22?
Qualsiasi porta TCP libera compresa tra 1024 e 65535. Su un server reale evita 2222 e 22222, perché gli scanner le provano subito dopo la 22. Verifica che il numero sia libero con sudo ss -tlnp, controlla che la policy SELinux non lo abbia già assegnato con sudo semanage port -l ed evita le porte assegnate a servizi che potresti installare in seguito. Un numero alto e difficile da ricordare va bene, perché lo inserirai una volta in ~/.ssh/config e non dovrai più digitarlo.