Implementare un server SSH su Ubuntu/Debian, configurazioni differenziate e accesso esterno con port forwarding

Introduzione

In questo articolo approfondiremo la configurazione di un server SSH su Ubuntu/Debian con un livello di sicurezza un po’ piu’ elevato. Non ci limiteremo alla semplice attivazione del servizio, ma esploreremo una strategia di configurazione modulare utilizzando la directory sshd_config.d. Questo approccio consente di creare differenti casistiche di accesso in base alla rete di provenienza, al metodo di autenticazione e all’utente che tenta di collegarsi. Inoltre, vedremo come:

  • Limitare gli accessi esterni a determinati utenti e chiavi pubbliche, filtrando per indirizzi IP di origine.
  • Permettere, da rete interna, l’accesso anche con password per tutti gli utenti.
  • Integrare firewall e fail2ban per mitigare i tentativi di accesso non autorizzati.
  • Esporre la porta SSH su una porta alta tramite port forwarding, aumentandone la sicurezza.
  • Preparare il terreno per automatizzare questi processi in futuro.

Assumeremo i seguenti prerequisiti:

  • Il server è basato su Ubuntu/Debian con sudo abilitato per l’utente di amministrazione.
  • OpenSSH Server è installato.
  • Un firewall (ad esempio ufw) è attivo e configurato.
  • Fail2ban è installato per prevenire i tentativi di brute-force.
  • Il server dispone di un IP interno (LAN) e di un IP pubblico (o di un router con port forwarding configurabile).
  • L’utente di amministrazione appartiene al gruppo sudo.

Perche’� adottare una configurazione modulare con sshd_config.d

Il file principale /etc/ssh/sshd_config definisce il comportamento globale del server SSH. Tuttavia, utilizzando la directory /etc/ssh/sshd_config.d, possiamo inserire file aggiuntivi che sovrascrivono o integrano la configurazione di base. Questo approccio modulare permette di mantenere il file principale pulito e di organizzare le diverse casistiche di accesso in file separati. È particolarmente utile quando si gestiscono scenari complessi e si ha necessità di apportare modifiche incrementali senza rischiare di compromettere l’intera configurazione.

Configurazione di base di OpenSSH

Installazione

Se non lo avete già fatto, procedete all’installazione:

1
2
sudo apt update
sudo apt install openssh-server

Il servizio sshd sarà avviato e abilitato automaticamente.

Configurazione del firewall (UFW)

Assicuratevi che il firewall ufw sia installato e attivato:

1
2
sudo apt install ufw
sudo ufw enable

Per consentire la connessione sulla porta SSH standard (22), eseguite:

1
sudo ufw allow 22/tcp

Successivamente, quando imposteremo un port forwarding su una porta differente, modificheremo le regole di conseguenza.

Configurazione di fail2ban

Fail2ban blocca gli indirizzi IP che tentano di eseguire accessi non autorizzati (brute-force). Se non presente:

1
sudo apt install fail2ban

Nella configurazione predefinita, fail2ban monitorerà il file di log di SSH e bloccherà automaticamente gli IP che generano troppi tentativi falliti. È possibile personalizzare /etc/fail2ban/jail.local per definire tempi di ban, numero di tentativi e altro. Un esempio basilare (da aggiungere o modificare in /etc/fail2ban/jail.local):

1
2
3
4
5
6
7
8
[sshd]
enabled = true
port = 22
filter = sshd
logpath = /var/log/auth.log
maxretry = 5
findtime = 600
bantime = 3600

Dopo aver modificato i parametri:

1
sudo systemctl restart fail2ban

Con questa configurazione di base, fallimenti ripetuti di autenticazione verranno puniti con il blocco temporaneo dell’IP.

Gestione utenti e privilegi sudo

L’utente amministrativo dovrebbe appartenere al gruppo sudo. Se state utilizzando un utente diverso, potete aggiungerlo al gruppo:

1
2
sudo adduser mio_utente
sudo usermod -aG sudo mio_utente

In questo modo mio_utente potrà eseguire comandi sudo e gestire la configurazione del sistema.

Creazione di scenari differenziati

L’obiettivo è creare due casi d’uso:

  1. Accessi dall’esterno:

    • Limitati a specifici utenti (ad esempio deploy)
    • Limitati a specifici IP di origine
    • Autenticazione solo con chiave, niente password.
  2. Accessi dalla rete interna:

    • Consentiti per tutti gli utenti di sistema (ad esempio mio_utente o altri)
    • Autenticazione con password abilitata e chiavi ammessa
    • Nessuna restrizione di IP (ma ci si basa sul fatto che l’indirizzo IP provenga dalla rete interna, ad esempio 192.168.0.0/24).

Configurazione di base di /etc/ssh/sshd_config

Nel file principale /etc/ssh/sshd_config lasceremo impostazioni generali di sicurezza:

1
sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak

Modifichiamo /etc/ssh/sshd_config per disabilitare l’accesso root e alcune opzioni generali:

1
2
3
4
5
6
7
UsePAM yes
PermitRootLogin no
ChallengeResponseAuthentication no
PasswordAuthentication yes # Abilitiamo qui la password come default, poi la limitiamo nei match esterni
PubkeyAuthentication yes
# Includiamo la directory di configurazione aggiuntiva
Include /etc/ssh/sshd_config.d/*.conf

Salviamo e chiudiamo. Con Include /etc/ssh/sshd_config.d/*.conf abbiamo dato istruzioni a sshd di leggere file aggiuntivi nella directory sshd_config.d.

Creazione dei file di configurazione modulari

Creeremo due file all’interno di /etc/ssh/sshd_config.d:

  • 00-internal.conf per la rete interna
  • 01-external.conf per l’accesso esterno

Configurazione interna: /etc/ssh/sshd_config.d/00-internal.conf

Questa configurazione consente a chiunque si trovi all’interno della rete interna (es. 192.168.0.0/24) di autenticarsi con password:

1
sudo nano /etc/ssh/sshd_config.d/00-internal.conf

Inseriamo:

1
2
3
4
Match address 192.168.0.0/24
PasswordAuthentication yes
PubkeyAuthentication yes
# In questo scenario lasciamo qualsiasi utente della LAN entrare con password o chiave.

Salviamo e chiudiamo.

Configurazione esterna: /etc/ssh/sshd_config.d/01-external.conf

Per l’accesso esterno, supponiamo di avere un IP pubblico o di filtrare l’accesso tramite firewall. Ad esempio, immaginiamo che solo da un certo IP pubblico o da un range (ad esempio aa.bb.cc.dd) possa accedere l’utente deploy. Inoltre, vogliamo obbligare l’autenticazione solo tramite chiave.

1
sudo nano /etc/ssh/sshd_config.d/01-external.conf

Inseriamo:

1
2
3
Match User deploy, Address aa.bb.cc.dd
PasswordAuthentication no
PubkeyAuthentication yes

In questo modo, se la connessione proviene dall’indirizzo aa.bb.cc.dd e l’utente che tenta di accedere è deploy, la password non sarà accettata, ma solo la chiave pubblica. Nessun altro IP o utente potrà usufruire di queste impostazioni.

Riavviare il servizio SSH per applicare le modifiche

Dopo aver creato i file di configurazione, riavviamo SSH:

1
sudo systemctl restart ssh

Chiavi SSH

L’utente deploy che accede da remoto dovrà avere una coppia di chiavi. Sul client remoto, generiamo una chiave:

1
ssh-keygen -t ed25519 -C "deploy@example.com"

Copiare la chiave pubblica sul server (da remoto):

1
ssh-copy-id deploy@ip_o_dominio_del_server

Il comando ssh-copy-id aggiungerà la chiave a ~/.ssh/authorized_keys dell’utente deploy.

Configurazione del firewall per differenti casistiche

Poiché da esterno si deve accedere solo con chiave e da determinati IP, si puo’ò rafforzare il tutto tramite ufw, consentendo solo l’IP esterno specifico:

1
sudo ufw allow from aa.bb.cc.dd to any port 22

Se desiderate bloccare tutti gli altri tentativi di accesso esterni, assicuratevi di non eseguire un ufw allow 22/tcp generico, ma solo quello limitato all’IP sopra indicato. In caso foste costretti ad aprire a tutti l’accesso per qualche motivo, ricordate che fail2ban entra in azione per mitigare i tentativi di brute force.

Fail2ban e le due casistiche di accesso

Fail2ban non fa distinzioni tra accessi interni o esterni di default, ma grazie alla sua configurazione blocca gli IP che tentano numerosi accessi non autorizzati. Questo è utile specialmente per gli attacchi provenienti da Internet. Se notate che IP interni vengono bloccati, potete modificare la configurazione ignoreip in /etc/fail2ban/jail.local:

1
2
3
4
5
6
7
8
9
[sshd]
enabled = true
port = 22
filter = sshd
logpath = /var/log/auth.log
maxretry = 5
findtime = 600
bantime = 3600
ignoreip = 127.0.0.1/8 192.168.0.0/24

In questo modo gli IP interni non saranno bloccati, permettendo maggiore flessibilità nella LAN.

Dopo le modifiche:

1
sudo systemctl restart fail2ban

Spostare la porta SSH esterna su una porta alta con port forwarding

È una buona pratica non esporre la porta 22 direttamente su Internet. Si può configurare il router per effettuare un port forwarding da una porta alta (ad esempio 22222) verso la porta 22 del server.

Passi generali

  1. Sul router/NAT:
    Accedete all’interfaccia di gestione del vostro router e individuate la sezione “Port Forwarding” o “Virtual Server”.
    Create una regola che inoltri la porta esterna 22222 (TCP) all’indirizzo IP interno del vostro server sulla porta 22.

  2. Configurazione del firewall interno per la nuova porta:

    Poiché la porta 22 rimane aperta internamente, nella rete LAN tutto rimane come prima. Dall’esterno, però, l’utente si collegherà a ssh -p 22222 deploy@mio_dominio (se avete un nome di dominio puntato sul vostro IP pubblico).

    Se volete che il firewall accetti esplicitamente connessioni solo su 22 in LAN e non dall’esterno, potete chiudere la 22 dall’esterno e lasciare aperta solo tramite la regola del router:

    1
    sudo ufw deny 22/tcp

    Ma questo bloccherebbe completamente SSH via 22 (anche internamente), quindi meglio gestire il firewall sul router o, se il server deve essere raggiungibile da LAN su 22, lasciare ufw allow 22/tcp ma consentire accesso esterno solo tramite l’IP specifico. Dipende dalla vostra topologia di rete.
    Se volete segmentare, potete usare regole UFW avanzate per differenziare l’accesso esterno/interno (ad esempio definendo allow from 192.168.0.0/24 to any port 22 per la LAN, e negare tutto il resto).

Collegamento esterno sulla porta alta

Da un host remoto:

1
ssh -p 22222 deploy@mio_dominio

La connessione arriverà al vostro router, che la inoltrerà alla porta 22 del server, passando le regole di sshd. Ricordate che l’utente deploy ha l’accesso da quell’IP autorizzato e soltanto con chiave.

Considerazioni finali e spunti per l’automazione

Abbiamo creato una configurazione modulare che differenzia gli accessi SSH sulla base della rete di provenienza, del metodo di autenticazione e dell’utente, utilizzando i file in sshd_config.d. Abbiamo integrato firewall, fail2ban e illustrato come effettuare un port forwarding per aumentare la sicurezza.

Questo approccio è solido, ma la sua gestione manuale puo’ò diventare complessa in ambienti di grandi dimensioni o con frequenti variazioni. Nel prossimo articolo potremmo esplorare meccanismi di automazione, utilizzando tool come Ansible, Puppet o Chef, per distribuire e mantenere queste configurazioni in maniera scalabile e ripetibile. L’automazione permetterebbe di applicare, testare e aggiornare queste configurazioni su un parco macchine esteso, riducendo il rischio di errori umani e semplificando il lavoro dell’amministratore di sistema.

Con questi spunti, si chiude questo lungo articolo, augurandoci che le informazioni fornite siano utili per implementare un accesso SSH sicuro, flessibile e ben organizzato.

Possibili Miglioramenti

Un ulteriore passo avanti verso una configurazione più robusta e scalabile potrebbe essere l’utilizzo di un reverse proxy posizionato davanti alla porta SSH esposta su Internet. In particolare, adottare un servizio come Cloudflare (gratuito nella fascia free per il traffico su porte HTTP/HTTPS, ma non per la porta SSH) consentirebbe di usufruire della loro rete globale di distribuzione, di strumenti di mitigazione avanzati contro attacchi DDoS, e di ulteriori livelli di filtraggio del traffico.

Tuttavia, questa configurazione introduce complessità aggiuntive: occorrerebbe consentire l’accesso solo agli indirizzi IP di Cloudflare, con una conseguente modifica delle regole firewall, una gestione più granulare delle liste di trusted IP e una combinazione di impostazioni su Cloudflare stesso.

Questa soluzione, pur più articolata, incrementa significativamente la resilienza del sistema e riduce l’esposizione diretta della vostra infrastruttura, rendendola meno vulnerabile alle minacce provenienti da Internet. Consideratela un’evoluzione del setup descritto in quest’articolo, una strada da intraprendere quando le esigenze di sicurezza e affidabilità diventano più stringenti.