1,842 25/03/2026 07/04/2026 10 min

Introduzione

I bot che colpiscono Nginx non cercano pagine utili. Cercano errori, backup, file di configurazione e percorsi lasciati scoperti per sbaglio. Il traffico sembra normale, ma il ritmo non lo è. Vedi richieste ripetute verso .env, .git, wp-config.php, backup.zip o file simili. Se non reagisci, il server risponde per ore a tentativi automatizzati. Fail2ban è una risposta semplice e concreta. Legge i log, riconosce il pattern e blocca l’IP prima che il rumore cresca.

In questo articolo vediamo come proteggere Nginx dai bot che cercano file sensibili con Fail2ban. Usiamo una configurazione reale, testabile, e adatta sia a chi lavora da shell sia a chi gestisce il server da pannello. Dove serve, segnalo anche il percorso grafico. Note: la parte di installazione e configurazione avanzata di Fail2ban resta comunque più veloce da terminale.

Prerequisiti

  • Un server Linux con Nginx attivo.
  • Accesso root o sudo.
  • Log di Nginx abilitati e leggibili, in genere /var/log/nginx/access.log e /var/log/nginx/error.log.
  • Fail2ban installato. Su molte distribuzioni è nei repository standard.
  • Un editor da terminale, oppure accesso SSH da pannello come Plesk, cPanel o web terminal.

Se usi un pannello, il punto di partenza cambia poco. Vai in Server o Strumenti e cerca Terminale, SSH Access o Gestione servizi. Da lì puoi verificare i log e modificare i file di jail. Se il pannello non espone Fail2ban, la configurazione avviene da shell. Note: l’attivazione del ban a livello di firewall è quasi sempre operazione da riga di comando.

Step 1: capire cosa stanno cercando i bot

Prima di bloccare, devi sapere quali richieste vuoi intercettare. I bot più comuni provano percorsi prevedibili. Puntano su file di backup, repository esposti, configurazioni web, vecchi editor, endpoint di admin e file temporanei. In molti casi il pattern è ripetitivo. Una sequenza tipica è questa: /.env, /.git/config, /wp-login.php, /phpinfo.php, /backup.tar.gz.

Controlla il log accessi e cerca richieste sospette. Se usi SSH, il comando è diretto:

sudo grep -E '(\.env|\.git|wp-config|phpinfo|backup|adminer|sql|dump)' /var/log/nginx/access.log | tail -n 50

# Output: righe con IP, data, path richiesto e status code, per esempio 404, 403 o 200.

Se lavori da pannello, vai in DominiLogs o Access Log. Cerca gli stessi path. Il valore pratico non è solo il file richiesto. Conta anche la frequenza. Dieci richieste in un minuto da uno stesso IP sono già un segnale utile. Cinquanta richieste in pochi secondi sono quasi certamente automatiche.

Warning: non usare una regola troppo ampia al primo colpo. Se blocchi tutto ciò che contiene admin o backup, rischi falsi positivi su URL legittimi.

Step 2: installare Fail2ban e verificare i servizi

Fail2ban deve leggere i log e applicare un ban tramite il firewall. Su Debian e Ubuntu l’installazione è rapida. Su RHEL, AlmaLinux o Rocky il nome del pacchetto resta spesso uguale. Dopo l’installazione, verifica che il servizio sia attivo. Questo passaggio è importante perché una jail ben scritta non serve se il demone non gira.

sudo apt update && sudo apt install fail2ban -y
sudo systemctl enable --now fail2ban
sudo systemctl status fail2ban --no-pager

# Output: servizio active (running) e abilitato all’avvio.

Su sistemi basati su RHEL:

sudo dnf install epel-release -y
sudo dnf install fail2ban -y
sudo systemctl enable --now fail2ban
sudo systemctl status fail2ban --no-pager

Se hai un pannello come Plesk, controlla in Tools & SettingsServices Management. Cerca Fail2ban. Se è presente, avvialo e impostalo su automatico. Se non compare, installalo da SSH. Note: alcuni pannelli integrano Fail2ban solo dopo un modulo o una estensione dedicata.

Step 3: creare una jail dedicata a Nginx

Una jail è la regola che collega un filtro ai log e definisce il comportamento del ban. Per questo scenario conviene creare una jail separata, invece di riusare quelle generiche. In questo modo puoi regolare meglio soglia, finestra temporale e durata del blocco. È utile anche in fase di debug.

Apri o crea /etc/fail2ban/jail.d/nginx-sensibili.local:

[nginx-sensibili]
enabled  = true
port     = http,https
filter   = nginx-sensibili
logpath  = /var/log/nginx/access.log
maxretry = 3
findtime = 600
bantime  = 86400
backend  = auto

# Output: una jail attiva che banna per 24 ore dopo 3 hit sospette in 10 minuti.

La scelta di maxretry = 3 è pratica. Un bot scannerizza e ripete. Un utente umano raramente prova tre file sensibili in sequenza nello stesso minuto. findtime = 600 significa finestra di 10 minuti. bantime = 86400 corrisponde a 24 ore. Se il sito è molto esposto, puoi iniziare con 12 ore e alzare dopo l’analisi.

Se usi un pannello, puoi comunque caricare il file via File Manager. Vai in File Manager/etc/fail2ban/jail.d/ e crea il file. Se il pannello non permette modifiche in quella path, usa SSH. Note: su hosting condiviso non hai sempre il controllo del firewall, quindi questa soluzione richiede un VPS o un server dedicato.

Step 4: scrivere il filtro per i file sensibili

Il filtro dice a Fail2ban quali righe del log considerare sospette. Qui conviene puntare su richieste a file e directory che non dovrebbero essere pubblici. Il filtro deve essere preciso. Deve riconoscere anche query string e varianti comuni, ma senza diventare troppo largo.

Crea /etc/fail2ban/filter.d/nginx-sensibili.conf:

[Definition]
failregex = ^<HOST> - .* "(GET|POST|HEAD) /(?:\.env|\.git(?:/config)?|wp-config\.php|phpinfo\.php|adminer(?:\.php)?|backup(?:\.|/)|.*\.(?:sql|bak|old|zip|tar|gz|7z))(?:\?.*)? HTTP/.*" (?:404|403|400|401|429)
ignoreregex =

# Output: richieste verso file sensibili con risposte tipiche di probing, come 404, 403 o 429.

La regex è volutamente pragmatica. Copre i casi più frequenti senza cercare di leggere il mondo. Se vuoi aggiungere altri bersagli, puoi estendere la lista. Per esempio, in ambienti WordPress spesso conviene includere readme.html, license.txt, xmlrpc.php e vecchi backup .sql. Non inserire subito tutto. Ogni aggiunta aumenta il rischio di errore.

Warning: se il tuo Nginx usa log format non standard, la regex potrebbe non corrispondere. In quel caso va adattata alla struttura reale della riga di log.

Step 5: collegare il filtro ai log e testare il match

Prima di riavviare, testa il filtro. È il passaggio che evita ore di debug. Fail2ban include uno strumento per verificare se una riga di log viene riconosciuta dal filtro. Usa un esempio reale preso dal tuo access log.

sudo fail2ban-regex /var/log/nginx/access.log /etc/fail2ban/filter.d/nginx-sensibili.conf

# Output: conteggio dei match, righe testate e nessun errore di parsing.

Se il match è zero, non significa per forza che il filtro sia sbagliato. Può voler dire che il formato del log è diverso o che il path non compare in quel file. Prova con una riga estratta dal log:

sudo grep -m 1 -E '(\.env|\.git|wp-config|phpinfo|backup)' /var/log/nginx/access.log

Se il pannello offre un visualizzatore dei log, copia una riga e confrontala con la regex. Questo è il modo più rapido per correggere un filtro senza tentativi ciechi.

Step 6: ricaricare Fail2ban e verificare la jail

Quando filtro e jail sono pronti, ricarica il servizio. Poi controlla che la jail sia attiva e associata al log giusto. Questo conferma che Fail2ban sta leggendo il file corretto e non una path vuota.

sudo systemctl restart fail2ban
sudo fail2ban-client status
sudo fail2ban-client status nginx-sensibili

# Output: lista delle jail attive, numero di tentativi trovati e IP bannati, se presenti.

Se tutto è corretto, vedrai la jail nginx-sensibili tra quelle attive. Il dettaglio più utile è Currently failed e Currently banned. Se sono entrambi a zero, non è un problema. Vuol dire solo che nessun IP ha superato la soglia da quando hai attivato la regola.

Da pannello, se disponibile, la strada è ServiziFail2banReload o Restart. Dopo il riavvio, controlla i log del servizio nella stessa area o nella dashboard di sistema.

Step 7: aggiungere una protezione complementare in Nginx

Fail2ban funziona meglio se Nginx restituisce risposte coerenti ai tentativi sospetti. Non devi inventare una trappola elaborata. Basta limitare l’esposizione dei file sensibili e rispondere in modo uniforme. L’obiettivo è ridurre il rumore e rendere il pattern più chiaro.

Se gestisci tu la configurazione di Nginx, aggiungi blocchi espliciti per i file che non devono essere pubblici. Per esempio:

location ~* /(\.env|\.git|wp-config\.php|phpinfo\.php|adminer\.php) {
    deny all;
    access_log off;
    log_not_found off;
    return 404;
}

# Output: richieste verso quei file ricevono 404 e non generano log inutili.

Questo blocco non sostituisce Fail2ban. Lo aiuta. Nginx rifiuta subito le richieste note. Fail2ban intercetta il comportamento ripetuto e blocca la sorgente. La combinazione è più solida di una sola misura. Se usi un pannello, cerca la sezione Configurazione Nginx o Advanced Configuration del dominio. Su Plesk, il percorso tipico è Dominiexample.comApache & nginx Settings. Lì puoi inserire direttive personalizzate, se il provider le consente.

Note: la direttiva return 404 è spesso più utile di 403 per non confermare l’esistenza del file.

Verifica finale

La verifica migliore è pratica. Simula una richiesta sospetta e guarda se Fail2ban la rileva. Puoi farlo con curl da una macchina di test o dal server stesso, se il test non altera il tuo IP reale in modo indesiderato.

curl -I https://tuodominio.tld/.env
curl -I https://tuodominio.tld/.git/config
curl -I https://tuodominio.tld/wp-config.php

# Output: risposta 404 o 403, mai contenuto del file.

Poi controlla i log di Fail2ban:

sudo tail -n 50 /var/log/fail2ban.log

# Output: righe con Found, Ban e l’IP sorgente.

Se vuoi una conferma ancora più netta, usa un IP esterno controllato, come una VPS di test o una connessione mobile. Dopo tre richieste sospette, l’IP dovrebbe finire bannato. Se il ban non arriva, il problema è quasi sempre uno tra questi: log path errato, regex troppo stretta, firewall non gestito da Fail2ban.

Troubleshooting

1) ERROR Failed during configuration: Have not found any log file for nginx-sensibili jail

Causa: il percorso indicato in logpath non esiste o Nginx scrive altrove.

Fix:

sudo ls -l /var/log/nginx/
sudo grep -R "access_log" /etc/nginx /etc/nginx/conf.d /etc/nginx/sites-enabled

# Output: path reale dei log e direttive access_log usate dal server.

2) WARNING No failure-id group in 'failregex'

Causa: la regex non contiene correttamente <HOST> o la sintassi del filtro è rotta.

Fix:

sudo nano /etc/fail2ban/filter.d/nginx-sensibili.conf
sudo fail2ban-regex /var/log/nginx/access.log /etc/fail2ban/filter.d/nginx-sensibili.conf

# Output: il filtro viene validato e le righe matchano senza warning.

3) ERROR Unable to find a corresponding IP address for ban

Causa: il formato del log non mette l’IP dove Fail2ban se lo aspetta, spesso per un log format personalizzato o proxy davanti a Nginx.

Fix:

sudo grep -n "log_format" /etc/nginx/nginx.conf /etc/nginx/conf.d/*.conf
sudo nano /etc/fail2ban/jail.d/nginx-sensibili.local

# Output: individuazione del formato log e aggiornamento della jail o del filtro con il formato corretto.

Se hai un reverse proxy, devi spesso far leggere a Nginx l’IP reale con real_ip_header e set_real_ip_from. Altrimenti Fail2ban banna il proxy, non il client.

Conclusione

Proteggere Nginx dai bot che cercano file sensibili con Fail2ban è una misura concreta, non cosmetica. Riduce il rumore, blocca gli scanner più insistenti e ti dà visibilità sui tentativi ripetuti. Se la regola è precisa e i log sono corretti, il risultato arriva subito.

Il prossimo passo concreto è aggiungere un secondo filtro per un’altra famiglia di probe, per esempio xmlrpc.php o .git. Poi controlla i ban ogni settimana e affina soglie e path in base ai log reali. È lì che la protezione diventa davvero utile.