
Un server acceso giorno e notte e raggiungibile da internet riceve tentativi di accesso fin dal primo giorno: basta guardare i log per vedere quanti bot provano password a caso su SSH o cercano pagine di login sui siti. In questo articolo raccolgo le protezioni che uso sul mio Raspberry: SSH su una porta diversa e con il codice a due fattori, un firewall che lascia passare solo il necessario, e fail2ban che blocca chi insiste.
Non le ho messe tutte insieme: le ho aggiunte man mano che installavo i servizi. Qui trovi la base; negli articoli dei singoli servizi indico quale porta aprire o quale protezione aggiungere.
Cosa serve
- Raspberry Pi con Raspberry Pi OS (Debian 12), accesso SSH e IP fisso
- un’app per i codici a due fattori sul telefono (Google Authenticator, Aegis, 2FAS o simili)
Attenzione: in questi passaggi modifichi proprio l’accesso con cui sei collegato. Tieni sempre aperta una seconda sessione SSH già collegata, e chiudila solo dopo aver verificato che il nuovo accesso funziona. Se qualcosa va storto, la sessione aperta ti permette di rimediare.
1. Spostare SSH su un’altra porta
La porta standard di SSH è la 22, ed è la prima che i bot provano. Spostarla non rende il server inattaccabile, ma elimina quasi tutto il “rumore” dei tentativi automatici dai log.
sudo nano /etc/ssh/sshd_config
Cerca la riga #Port 22, togli il # e metti un numero a tua scelta tra 1024 e 65535, per esempio:
Port 2222
Se il firewall è già attivo (passo 3), apri prima la nuova porta, altrimenti resti chiuso fuori. Poi controlla la configurazione e riavvia SSH:
sudo sshd -t
sudo systemctl restart ssh
sshd -t non mostra nulla se il file è corretto. Da un altro terminale prova a collegarti sulla nuova porta, senza chiudere la sessione attuale:
ssh -p 2222 TUO_UTENTE@IP_DEL_RASPBERRY
2. Il codice a due fattori su SSH
Con la verifica in due passaggi, per entrare non basta la password: serve anche il codice di sei cifre che cambia ogni 30 secondi sull’app del telefono. Il codice lo chiedo solo quando mi collego da fuori casa; dalla rete di casa basta la password.
Installazione e generazione della chiave
sudo apt install libpam-google-authenticator
google-authenticator
Il secondo comando va lanciato con il tuo utente, senza sudo. Rispondi così alle domande:
- time-based tokens: y, poi inquadra il codice QR con l’app del telefono;
- update the .google_authenticator file: y;
- disallow multiple uses of the same token: y;
- increase the time skew window: n;
- enable rate-limiting: y.
Il programma mostra anche alcuni codici di emergenza: salvali in un posto sicuro, servono se perdi il telefono.
Collegare il codice all’accesso SSH
sudo nano /etc/pam.d/sshd
Aggiungi in fondo al file:
# Codice a due fattori, non richiesto dalla rete di casa
auth [success=done default=ignore] pam_access.so accessfile=/etc/security/access-local.conf
auth required pam_google_authenticator.so
La prima riga controlla da dove arriva il collegamento: se è dalla rete di casa, l’accesso finisce lì, dopo la password; altrimenti si passa alla seconda riga, che chiede il codice. Crea poi il file con la rete di casa:
sudo nano /etc/security/access-local.conf
+ : ALL : 192.168.1.0/24
- : ALL : ALL
Se la tua rete usa indirizzi diversi da 192.168.1.x, adatta la prima riga.
Abilitare la richiesta del codice in SSH
sudo nano /etc/ssh/sshd_config
Cerca la riga KbdInteractiveAuthentication no e cambiala in:
KbdInteractiveAuthentication yes
Molte guide parlano di ChallengeResponseAuthentication: è il vecchio nome della stessa opzione, che su Debian 12 non va più usato. Controlla anche che sia presente UsePAM yes, che è il valore predefinito. Poi:
sudo sshd -t
sudo systemctl restart ssh
Per provare la richiesta del codice devi collegarti da fuori casa, per esempio dal portatile collegato all’hotspot del telefono. Nel mio caso il codice ha cominciato a essere richiesto solo dopo un riavvio completo del Raspberry (sudo reboot).
FileZilla e altri programmi
Se usi FileZilla per trasferire file via SFTP, nelle impostazioni del sito imposta Tipo di accesso: Interattivo e, nella scheda Impostazioni di trasferimento, Numero massimo di connessioni: 1. Altrimenti FileZilla apre più connessioni e chiede il codice per ognuna.
3. Il firewall
Il firewall blocca tutte le connessioni in arrivo tranne quelle che autorizzi esplicitamente. Su Raspberry Pi OS il più semplice da usare è ufw.
sudo apt install ufw
Prima di attivarlo, aggiungi le regole. La prima lascia passare tutto dalla rete di casa, la seconda apre SSH dall’esterno con un limite ai tentativi:
sudo ufw allow from 192.168.1.0/24 comment 'Rete di casa'
sudo ufw limit 2222/tcp comment 'SSH'
limit funziona come allow, ma blocca per un po’ un indirizzo che tenta sei o più connessioni in 30 secondi. Usa la porta SSH scelta al passo 1. Poi attiva il firewall:
sudo ufw enable
Il comando avvisa che potrebbe interrompere le connessioni SSH: con le regole qui sopra non succede, rispondi y.
Man mano che installi servizi raggiungibili da internet aggiungi le loro porte. Per esempio, per un server web:
sudo ufw allow 80/tcp comment 'HTTP'
sudo ufw allow 443/tcp comment 'HTTPS'
Per i programmi P2P si aprono le porte scelte nella loro configurazione (vedi gli articoli su Transmission e aMule). Conviene dare ai programmi porte consecutive, così bastano due regole, una per TCP e una per UDP:
sudo ufw allow 50000:50002/tcp comment 'P2P'
sudo ufw allow 50000:50003/udp comment 'P2P'
L’intervallo UDP arriva una porta più in là perché aMule, oltre alla porta TCP e a quella UDP impostate nella configurazione, usa anche la porta UDP pari alla porta TCP + 3 per comunicare con i server.
Sul router. Perché i programmi P2P ricevano connessioni da internet, le stesse porte vanno aperte anche sul router e inoltrate all’IP del Raspberry, con gli stessi numeri e protocolli usati in ufw. Sul Fritz!Box si fa in Internet → Abilitazioni → Abilitazioni porte, aggiungendo il Raspberry e due regole: una per l’intervallo TCP e una per quello UDP. Se in casa hai più di un Raspberry con programmi P2P, ognuno deve avere un intervallo diverso, per esempio 50000–50003 per il primo e 51000–51003 per il secondo: il router non può inoltrare la stessa porta a due dispositivi.
Le porte di SSH e dei servizi web si inoltrano sul router solo se devono essere raggiungibili da fuori casa. Comandi utili di ufw:
sudo ufw status numbered
mostra le regole numerate, e
sudo ufw delete NUMERO
cancella la regola con quel numero.
Attenzione con Docker. Le porte dei container Docker pubblicate con -p o con ports: in docker compose non passano da ufw: Docker scrive le sue regole direttamente nel firewall del sistema, e quelle porte restano aperte anche se ufw non le prevede. Se un container non deve essere raggiungibile da internet, non inoltrare la sua porta dal router, oppure pubblicala solo in locale, per esempio con 127.0.0.1:8080:8080, e raggiungila tramite il server web.
4. fail2ban
fail2ban legge i log e, quando un indirizzo sbaglia l’accesso troppe volte, lo blocca nel firewall per un certo tempo. Funziona per SSH e, con le regole giuste, anche per siti web, WordPress e altri servizi.
sudo apt install fail2ban python3-systemd
La configurazione predefinita sta in /etc/fail2ban/jail.conf, che non va modificato perché viene sovrascritto dagli aggiornamenti. Le tue impostazioni vanno in un file a parte:
sudo nano /etc/fail2ban/jail.local
[DEFAULT]
ignoreip = 127.0.0.1/8 ::1 192.168.1.0/24
bantime = 1h
findtime = 10m
maxretry = 5
[sshd]
enabled = true
port = 2222
backend = systemd
[recidive]
enabled = true
ignoreip: indirizzi mai bloccati, cioè il Raspberry stesso e la rete di casa. Così non rischi di chiuderti fuori da solo.bantime,findtime,maxretry: con questi valori, chi sbaglia 5 volte in 10 minuti resta bloccato per un’ora.[sshd]: la protezione di SSH.portè la porta scelta al passo 1.backend = systemdè indispensabile su Debian 12: il sistema non scrive più il file/var/log/auth.logma usa il journal, e senza questa riga fail2ban non parte.[recidive]: controlla i blocchi fatti da fail2ban stesso, e chi viene bloccato più volte in un giorno resta fuori per una settimana.
Riavvia e controlla:
sudo systemctl restart fail2ban
sudo fail2ban-client status
Il secondo comando elenca le protezioni attive (in gergo jail). Per vedere i dettagli di una, con gli indirizzi bloccati:
sudo fail2ban-client status sshd
Per sbloccare un indirizzo bloccato per errore:
sudo fail2ban-client set sshd unbanip INDIRIZZO_IP
[DA COMPLETARE: le protezioni per i siti web (apache-auth, apache-badbots, le regole personalizzate per i codici 301 e 404 e per WordPress) e lo script del report]
Note
- Un ulteriore passo avanti è l’accesso SSH con chiave invece che con password: la chiave è praticamente impossibile da indovinare, e si può combinare con il codice a due fattori.
- Riferimenti: le guide di Pi My Life Up su SSH con due fattori, sul firewall ufw e su fail2ban, e l’articolo di techlabs.blog su fail2ban per WordPress.