200 28/03/2026 07/04/2026 8 min

Diagnosi probabile

Il caso più comune è che nginx stia ricevendo richieste automatiche verso file sensibili come .env, wp-config.php, backup .zip, .sql, directory .git o file di configurazione esposti. Se questi accessi compaiono nei log, fail2ban può leggere gli accessi ripetuti e bloccare l’IP sorgente prima che il rumore diventi un problema serio.

La causa tecnica più probabile non è un “attacco riuscito”, ma scansioni massiva e brute probing su porte e percorsi noti. In pratica: nginx registra le richieste, fail2ban intercetta i pattern, crea una regola nel firewall e sospende temporaneamente l’host che insiste. È una misura di contenimento, non sostituisce la protezione applicativa o la rimozione del file sensibile dal web root.

La configurazione corretta dipende da tre punti: il formato reale dei log di nginx, il tipo di file o percorso da proteggere e il backend firewall disponibile sul server. Su sistemi moderni la combinazione più comune è nginx + fail2ban + nftables o iptables. Se il log non viene parsato bene o la regex è troppo aggressiva, si rischiano falsi positivi o nessun ban.

Verifiche immediate

  1. Controlla che nginx stia registrando gli accessi nel file giusto. Su molte installazioni il log è in /var/log/nginx/access.log oppure in un file per virtual host. L’esito atteso è vedere righe con IP, timestamp, metodo HTTP, URL e codice risposta.
  2. Verifica che fail2ban sia installato e attivo. Su sistemi con systemd il controllo base è systemctl status fail2ban; l’esito atteso è active (running). Se non è attivo, non applicare ancora la jail: prima va risolto il servizio.
  3. Controlla se il server espone davvero i percorsi da difendere. Un test rapido può essere curl -I https://tuodominio.tld/.env o verso un file noto. L’esito corretto, se il file non deve essere pubblico, è 403 oppure 404. Se risponde 200, il problema principale è prima di fail2ban: il file è accessibile e va chiuso subito.

Soluzione consigliata passo-passo

La strategia più sicura è: prima impedire l’accesso diretto a file sensibili in nginx, poi usare fail2ban per bloccare chi insiste. In questo modo riduci il rischio di dipendere solo dal ban e migliori la sicurezza anche se fail2ban dovesse essere fermato.

  1. Metti in sicurezza nginx con regole di negazione
    Apri il file di configurazione del virtual host o del server block. Su Debian/Ubuntu può essere in /etc/nginx/sites-available/; su RHEL/Alma/Rocky spesso in /etc/nginx/conf.d/ o in percorsi gestiti dal pannello. Prima di modificare, crea un backup del file:
    cp /percorso/del/file.conf /percorso/del/file.conf.bak
    Inserisci regole per bloccare i file più sensibili, ad esempio:
    location ~* ^/(?:\.env|\.git|composer\.(?:json|lock)|wp-config\.php|phpinfo\.php)$ { deny all; }
    location ~* \.(?:sql|bak|old|orig|save|swp|zip|tar|tgz|gz)$ { deny all; }
    Il risultato atteso è che nginx risponda con 403 o 404 alle richieste dirette.
  2. Verifica la configurazione nginx
    Dopo la modifica, esegui un controllo sintattico:
    nginx -t
    L’esito atteso è syntax is ok e test is successful. Se fallisce, non riavviare nginx: correggi prima l’errore segnalato.
  3. Ricarica nginx in modo sicuro
    Se il test è passato, ricarica il servizio senza interrompere le connessioni attive:
    systemctl reload nginx
    L’esito atteso è che il servizio resti operativo e la nuova regola entri in vigore subito.
  4. Crea la filtro fail2ban per nginx
    Il metodo più pulito è usare un filtro dedicato, ad esempio per richieste verso file sensibili. Crea un file come /etc/fail2ban/filter.d/nginx-sensitive.conf con un backup del contenuto precedente se esiste. Una traccia di filtro possibile è:
    [Definition]
    failregex = ^<HOST> - .* "(GET|POST|HEAD) (?:/|.*)(?:\.env|\.git|wp-config\.php|composer\.(?:json|lock)|phpinfo\.php|.*\.(?:sql|bak|old|zip|tar|tgz|gz)) .*" (?:403|404|400|444) .*$
    ignoreregex =
    Questa regex è un punto di partenza, non universale: va adattata al formato reale del tuo access.log. Se nginx usa un log format personalizzato, la regex deve combaciare con quel formato.
  5. Testa la regex prima di attivare la jail
    Usa il test di fail2ban su un campione di log reale. Un comando utile è:
    fail2ban-regex /var/log/nginx/access.log /etc/fail2ban/filter.d/nginx-sensitive.conf
    L’esito atteso è che il tool trovi corrispondenze sulle richieste sospette. Se non trova match, la regex va corretta prima di proseguire.
  6. Crea la jail dedicata
    La configurazione consigliata va in /etc/fail2ban/jail.d/nginx-sensitive.local oppure in /etc/fail2ban/jail.local. Prima fai un backup del file se esiste. Un esempio ragionevole è:
    [nginx-sensitive]
    enabled = true
    filter = nginx-sensitive
    port = http,https
    logpath = /var/log/nginx/access.log
    maxretry = 3
    findtime = 10m
    bantime = 1h
    backend = auto
    Questa impostazione è prudente: tre tentativi in dieci minuti fanno scattare un ban di un’ora. Se il traffico legittimo è molto alto o hai proxy/CDN, il valore va adattato per evitare falsi positivi.
  7. Riavvia fail2ban e verifica lo stato
    Dopo aver creato filtro e jail, riavvia il servizio:
    systemctl restart fail2ban
    Controlla poi lo stato della jail:
    fail2ban-client status
    e, nello specifico:
    fail2ban-client status nginx-sensitive
    L’esito atteso è vedere la jail attiva, con un elenco di tentativi trovati e, se presenti, IP bannati.
  8. Fai un test controllato
    Da un IP di test o da una sessione non critica, genera richieste ripetute verso un file sensibile fittizio o verso un path bloccato. Dopo alcuni tentativi, controlla i log di fail2ban e lo stato del ban. L’esito atteso è che l’IP finisca nella lista dei bannati e non possa più raggiungere il servizio per la durata impostata.

Dettaglio tecnico utile per una configurazione robusta

Il punto più importante è il logpath. Se nginx scrive in più file, come log separati per virtual host, una sola jail può non bastare. In quel caso puoi usare un percorso wildcard, ad esempio /var/log/nginx/*access.log, purché il backend e i permessi del servizio lo consentano. Se usi un pannello come Plesk, cPanel o FastPanel, verifica prima dove vengono salvati i log dei domini, perché spesso non sono nel percorso standard.

Un’altra attenzione riguarda i reverse proxy. Se davanti a nginx c’è un CDN o un bilanciatore, nei log potresti vedere sempre l’IP del proxy e non quello reale del client. In quel caso fail2ban bannerebbe il proxy, causando un impatto molto ampio. La correzione è configurare correttamente real_ip in nginx e far sì che i log contengano l’IP reale. Senza questo allineamento, la jail è tecnicamente funzionante ma operativamente pericolosa.

Per file sensibili come .env o wp-config.php, la difesa migliore resta non esporli proprio. Per WordPress, ad esempio, puoi bloccare l’accesso a file di configurazione e backup, e in parallelo usare fail2ban su richieste ripetute a path sospetti come /wp-login.php o /xmlrpc.php. Per siti non WordPress, i pattern più utili sono scansioni su .git, .svn, file di backup e dump database.

Se vuoi ridurre i falsi positivi, puoi separare le jail: una per file sensibili, una per login brute force, una per errori 404 anomali. È meglio avere regole più piccole e precise che una sola regex troppo larga. In questo modo è più facile capire quale evento ha causato il ban.

Controlli finali / rollback

  1. Controllo finale della protezione
    Esegui una richiesta verso un file sensibile noto e verifica che il codice sia 403 o 404. Il risultato atteso è che il file non sia scaricabile dal browser o da curl.
  2. Controllo finale di fail2ban
    Verifica che la jail sia attiva e che i log mostrino i ban quando il pattern si ripete. Il risultato atteso è un output coerente di fail2ban-client status nginx-sensitive e la presenza di eventi nel log di fail2ban.
  3. Rollback sicuro
    Se la regex causa falsi positivi o blocca traffico legittimo, disabilita temporaneamente la jail commentando enabled = true o impostando enabled = false nel file della jail, poi riavvia fail2ban con systemctl restart fail2ban. Se il problema è nella regola nginx, ripristina il file dal backup creato prima della modifica e ricarica nginx con nginx -t seguito da systemctl reload nginx solo dopo esito positivo.

Assunzione operativa: i percorsi dei log e dei file di configurazione vanno adattati alla distribuzione e all’eventuale pannello di hosting in uso.

Checklist rapida

  • Il file sensibile non è più accessibile direttamente via HTTP.
  • La regex di fail2ban corrisponde davvero alle righe del log di nginx.
  • La jail è attiva e il ban avviene solo dopo tentativi ripetuti.
  • I log mostrano IP reali, non solo l’eventuale proxy/CDN.
  • Esiste sempre un backup del file di configurazione prima delle modifiche.

Per un ambiente di produzione, la combinazione migliore resta: blocco diretto in nginx, test regex su log reali, jail fail2ban prudente e monitoraggio dei falsi positivi nelle prime 24-48 ore.