{"id":21255,"date":"2026-09-02T08:35:33","date_gmt":"2026-09-02T06:35:33","guid":{"rendered":"https:\/\/webhosting.de\/nginx-rate-limiting-schutz-vor-bot-traffic-angriffen-secure\/"},"modified":"2026-09-02T08:35:33","modified_gmt":"2026-09-02T06:35:33","slug":"nginx-limitazione-della-velocita-protezione-dagli-attacchi-del-traffico-bot-sicurezza","status":"publish","type":"post","link":"https:\/\/webhosting.de\/it\/nginx-rate-limiting-schutz-vor-bot-traffic-angriffen-secure\/","title":{"rendered":"Limitazione della frequenza di NGINX: protezione efficace dal traffico generato dai bot e dagli attacchi"},"content":{"rendered":"<p><strong>Tariffa NGINX<\/strong> Limiting blocca le richieste automatizzate, riduce i picchi di carico e protegge gli endpoint di login, API e moduli da bot e attacchi. Ti mostro come definire i limiti e come applicarli a <strong>Protezione dai bot<\/strong> lo utilizza per elaborare un solido sistema di sicurezza per siti web molto frequentati.<\/p>\n\n<h2>Punti centrali<\/h2>\n\n<p><strong>Essenziale<\/strong> Ecco i punti chiave:<\/p>\n<ul>\n  <li><strong>Limiti tariffari<\/strong> frenano gli attacchi malevoli e proteggono le risorse di backend.<\/li>\n  <li><strong>Burst\/senza ritardo<\/strong> intercettano i picchi legittimi senza bloccare gli utenti.<\/li>\n  <li><strong>zone<\/strong> distinguere le persone dai bot in base a limiti diversi.<\/li>\n  <li><strong>Registrazione<\/strong> fornisce dati per affinare i limiti in modo iterativo.<\/li>\n  <li><strong>Integrazione<\/strong> con WAF, protezione DDoS e monitoraggio, ne aumenta l'efficacia.<\/li>\n<\/ul>\n\n<h2>Perch\u00e9 il rate limiting blocca tempestivamente gli attacchi<\/h2>\n\n<p>Gli aggressori puntano su un alto <strong>Frequenze delle richieste<\/strong>, per sfruttare in modo improprio i moduli di accesso, sovraccaricare le API o estrarre contenuti in modo automatizzato. Limito quindi le richieste per chiave \u2013 solitamente per IP \u2013 e decido se limitarle, ritardarle o rispondere con un codice di stato 429. In questo modo tengo lontano il traffico dei bot dalla CPU, dal database e dalla logica applicativa, lasciando passare gli utenti legittimi. Ne traggono grande beneficio in particolare i percorsi sensibili come \/login, \/auth, \/xmlrpc.php o le ricerche che richiedono molte risorse. La fonte di questa procedura \u00e8 la <strong>Documentazione di Nginx<\/strong> sul modulo ngx_http_limit_req_module.<\/p>\n\n\n<figure class=\"wp-block-image size-full is-resized\">\n  <img fetchpriority=\"high\" decoding=\"async\" src=\"https:\/\/webhosting.de\/wp-content\/uploads\/2026\/09\/nginx-rate-limiting-rechenzentrum-4738.png\" alt=\"\" width=\"1536\" height=\"1024\"\/>\n<\/figure>\n\n\n<h2>Come funziona il modulo NGINX nella pratica<\/h2>\n\n<p>Il modulo funziona secondo il <strong>Secchio che perde<\/strong>Principio: per ogni chiave, NGINX memorizza i valori di conteggio in una zona e li confronta con la frequenza consentita. Chiavi tipiche sono $binary_remote_addr per gli indirizzi IP, i token per le chiavi API o i valori derivati tramite map. Se un client supera in modo persistente la frequenza consentita e il buffer di burst, NGINX rifiuta la richiesta prima che raggiunga il backend. Ci\u00f2 consente di risparmiare tempo di elaborazione e riduce la latenza per i visitatori reali. Impostiamo la risposta con 429 Too Many Requests o, a scelta, un altro <strong>Codice di stato<\/strong> um.<\/p>\n\n<h2>Configurazione: spiegata passo dopo passo<\/h2>\n\n<p>Comincio con una zona nella sezione http, imposto una frequenza moderata e la attivo in modo mirato sui percorsi sensibili. Per i picchi di breve durata definisco un \u00abburst\u00bb, opzionalmente con \u00abnodelay\u00bb, per evitare rifiuti bruschi. Successivamente eseguo dei test nell\u2019ambiente di staging e analizzo i log prima di passare all\u2019ambiente di produzione. In questo modo non rischio di bloccare inutilmente gli utenti reali. Un esempio sintetico illustra il <strong>Sintassi<\/strong> tangibile:<\/p>\n\n<pre><code># http {}\nlimit_req_zone $binary_remote_addr zone=req_limit_per_ip:10m rate=10r\/s;\n\nserver {\n  location \/api\/ {\n    limit_req zone=req_limit_per_ip burst=20 nodelay;\n    limit_req_status 429;\n  }\n\n  location \/login {\n    limit_req zone=req_limit_per_ip burst=5;\n    limit_req_status 429;\n  }\n}\n<\/code><\/pre>\n\n<h2>Protezione bot con zone e logica user-agent<\/h2>\n\n<p>I limiti basati sull'IP raramente sono sufficienti contro le botnet distribuite, pertanto suddivido il traffico in <strong>zone<\/strong>: Agli utenti vengono assegnati valori pi\u00f9 generosi, mentre ai crawler generici valori pi\u00f9 restrittivi. Con map valuto gli user-agent, riconosco i bot autorizzati come Googlebot e assegno loro limiti specifici e strettamente monitorati. Per gli scraper sconosciuti impongo limiti rigidi su percorsi che comportano costi elevati. Se rilevo degli schemi ricorrenti, aumento dinamicamente il livello di rigore fino a quando il <strong>Tasso<\/strong> \u00e8 tornato nella norma.<\/p>\n\n<h2>Messa a punto: rate, burst, nodelay e codici di stato<\/h2>\n\n<p>Il parametro \"Rate\" regola la velocit\u00e0 di trasmissione al secondo, \"Burst\" consente picchi temporanei di bufferizzazione, mentre \"nodelay\" determina se preferisco la bufferizzazione o il passaggio immediato. Inizio con impostazioni moderate, ad esempio 10 richieste al secondo con burst 20 sulle API, e poi le affino in base all\u2019analisi dei log. Per le route di login, ad esempio, imposto 1 richiesta al secondo con un burst ridotto, per frenare gli attacchi brute force. In caso di superamento dei limiti, restituisco un 429, perch\u00e9 i client in questo modo <strong>cavarsela<\/strong> e la logica di riprova funzioni correttamente. In casi particolari, utilizzo codici alternativi se i clienti lo richiedono.<\/p>\n\n<h2>Panoramica nella tabella: direttive e utilizzo<\/h2>\n\n<p>Il seguente <strong>Tabella<\/strong> riassume le linee guida fondamentali e illustra in quali casi \u00e8 opportuno applicarle.<\/p>\n\n<table>\n  <thead>\n    <tr>\n      <th>direttiva<\/th>\n      <th>Effetto<\/th>\n      <th>Esempio<\/th>\n      <th>Utilizzo tipico<\/th>\n    <\/tr>\n  <\/thead>\n  <tbody>\n    <tr>\n      <td>limit_req_zone<\/td>\n      <td>Inserire la chiave, la zona e <strong>Tasso<\/strong> fermo<\/td>\n      <td>limit_req_zone $binary_remote_addr zone=perip:10m rate=10r\/s;<\/td>\n      <td>Base per IP, token o user-agent<\/td>\n    <\/tr>\n    <tr>\n      <td>limit_req<\/td>\n      <td>Attiva il limite in <strong>Posizione<\/strong>\/Server<\/td>\n      <td>limit_req zone=perip burst=20 nodelay;<\/td>\n      <td>Controllo granulare per percorso o vHost<\/td>\n    <\/tr>\n    <tr>\n      <td>limit_req_status<\/td>\n      <td>Aggiunge il codice HTTP <strong>Superamento<\/strong><\/td>\n      <td>limit_req_status 429;<\/td>\n      <td>Comportamento corretto del client e tentativi di riconnessione<\/td>\n    <\/tr>\n    <tr>\n      <td>mappa<\/td>\n      <td>Inoltra le richieste a <strong>zone<\/strong> all'indirizzo<\/td>\n      <td>map $http_user_agent $is_bot {\u2026}<\/td>\n      <td>Distituzione tra bot e utenti in base all'User-Agent<\/td>\n    <\/tr>\n  <\/tbody>\n<\/table>\n\n\n<figure class=\"wp-block-image size-full is-resized\">\n  <img decoding=\"async\" src=\"https:\/\/webhosting.de\/wp-content\/uploads\/2026\/09\/NGINXLimitingMeeting1234.png\" alt=\"\" width=\"1536\" height=\"1024\"\/>\n<\/figure>\n\n\n<h2>Esempio pratico: proteggere in modo mirato l'endpoint di accesso<\/h2>\n\n<p>Limito l'accesso a \/login in modo molto rigoroso, perch\u00e9 i bot provano password con un alto <strong>Frequenza<\/strong> Provare diverse impostazioni. 1 richiesta al secondo con burst 3 impedisce tentativi massicci di accesso senza penalizzare eccessivamente gli utenti reali. Inoltre, registro i tentativi falliti ripetuti nel log per bloccare temporaneamente gli indirizzi IP. In combinazione con l\u2019autenticazione a due fattori (2FA) e, facoltativamente, il Captcha, la pressione sul database e sulla gestione delle sessioni si riduce notevolmente. In questo modo mantengo basso il numero di tentativi falliti e garantisco che il <strong>Accesso<\/strong> pronto e stabile.<\/p>\n\n<h2>Pratica: fornire le API in modo equo e controllato<\/h2>\n\n<p>Le API richiedono chiare <strong>Probabilit\u00e0<\/strong>, in modo che i singoli client non monopolizzino l'intera larghezza di banda. Per i percorsi generici imposto 10 richieste al secondo (r\/s) e un picco di 20; per gli endpoint pi\u00f9 costosi, valori pi\u00f9 restrittivi. Se sono disponibili token o chiavi API, impongo una limitazione per token anzich\u00e9 per IP. Ci\u00f2 garantisce equit\u00e0 tra i clienti e previene gli abusi. Per un approfondimento, si veda la mia nota su <a href=\"https:\/\/webhosting.de\/it\/api-rate-limiting-hosting-protezione-contro-gli-abusi-sicurezza\/\">Limitazione della frequenza delle chiamate API<\/a>, che inquadra il concetto in una prospettiva pi\u00f9 ampia.<\/p>\n\n\n<figure class=\"wp-block-image size-full is-resized\">\n  <img decoding=\"async\" src=\"https:\/\/webhosting.de\/wp-content\/uploads\/2026\/09\/nginx-rate-limiting-security-5721.png\" alt=\"\" width=\"1536\" height=\"1024\"\/>\n<\/figure>\n\n\n<h2>Monitoraggio, registrazione dei dati e ottimizzazione iterativa<\/h2>\n\n<p>Registro 429 risposte, comprese <strong>Chiave<\/strong> (ad es. IP o token) e il percorso, per individuare eventuali schemi ricorrenti. I picchi su pochi percorsi indicano attivit\u00e0 di scraping o attacchi di forza bruta; un carico distribuito fa pensare a botnet. Con questi dati, applico limiti solo dove \u00e8 necessario e riduco al minimo i falsi positivi. Le dashboard con frequenze, tasso di errore e latenza mi mostrano l\u2019effetto di ogni modifica. In questo modo, la <strong>Prestazioni<\/strong> elevato, mentre la protezione aumenta.<\/p>\n\n<h2>Inserimento in un approccio olistico alla protezione<\/h2>\n\n<p>Ritengo che il \u201crate limiting\u201d sia un ottimo primo passo <strong>strato<\/strong>, ma lo abbino a regole WAF, reputazione IP e rafforzamento TLS. Contro gli attacchi di volume \u00e8 utile una protezione DDoS a monte, che filtra il traffico a livello di rete prima che NGINX debba entrare in azione. Misuro costantemente le metriche, imposto avvisi in caso di picchi anomali e reagisco aggiornando le regole. In questo modo, i vari elementi si combinano per formare una rete di protezione resiliente. Questi articoli forniscono una panoramica pratica <a href=\"https:\/\/webhosting.de\/it\/mitigazione-del-ddos-strategie-di-webhosting-protezione-della-rete\/\">Strategie DDoS<\/a>.<\/p>\n\n\n<figure class=\"wp-block-image size-full is-resized\">\n  <img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/webhosting.de\/wp-content\/uploads\/2026\/09\/nginx_schutz_tech_office_6352.png\" alt=\"\" width=\"1536\" height=\"1024\"\/>\n<\/figure>\n\n\n<h2>Modelli di configurazione specifici per i bot rispetto alle persone<\/h2>\n\n<p>Con map suddivido i visitatori in categorie e li indirizzo in pagine dedicate <strong>zone<\/strong>. Ai crawler noti vengono assegnati limiti moderati, mentre agli agenti generici vengono applicati limiti pi\u00f9 severi. Per percorsi come \/search o \/report mantengo criteri pi\u00f9 rigorosi, poich\u00e9 richiedono un elevato utilizzo della CPU. In caso di violazioni ricorrenti, non aumento i limiti, ma applico un blocco temporaneo o trasferisco la verifica a un modulo di rilevamento dei bot. In questo modo la <strong>Tasso di uso improprio<\/strong> basso, senza interferire con i motori di ricerca.<\/p>\n\n<h2>Esempio: due zone e mappatura dell'user-agent<\/h2>\n\n<p>Il seguente frammento mostra la suddivisione in base a <strong>Agente utente<\/strong> e l'assegnazione di limiti adeguati. Combino tutto ci\u00f2 con codici di stato differenziati e campi di log per misurare con precisione l'efficacia. I bot con un agente generico finiscono nella zona pi\u00f9 restrittiva. Le persone o i crawler verificati utilizzano la zona pi\u00f9 flessibile. Questo approccio garantisce risultati prevedibili <strong>Produttivit\u00e0<\/strong> per classe:<\/p>\n\n<pre><code>map $http_user_agent $is_bot {\n  default 0;\n  \"~*googlebot\"     0;\n  \"~*bingbot\" 0;\n  \"~*crawler|scraper|bot\" 1;\n}\n\nlimit_req_zone $binary_remote_addr zone=human:10m rate=10r\/s;\nlimit_req_zone $binary_remote_addr zone=bot:10m   rate=1r\/s;\n\nserver {\n  location \/ {\n    if ($is_bot) {\n limit_req zone=bot burst=5;\n    }\n    if ($is_bot = 0) {\n limit_req zone=human burst=20 nodelay;\n    }\n    limit_req_status 429;\n  }\n}\n<\/code><\/pre>\n\n\n<figure class=\"wp-block-image size-full is-resized\">\n  <img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/webhosting.de\/wp-content\/uploads\/2026\/09\/nginx_rate_limiting_schutz_3947.png\" alt=\"\" width=\"1536\" height=\"1024\"\/>\n<\/figure>\n\n\n<h2>Gestione degli errori: comunicare correttamente il codice 429<\/h2>\n\n<p>Su Limits offro una chiara <strong>Risposta<\/strong> indicando quando \u00e8 opportuno effettuare un nuovo tentativo. Per le API, \u00e8 necessario includere l\u2019intestazione Retry-After valida, affinch\u00e9 i client applichino il backoff. Agli utenti umani viene fornita una breve spiegazione senza dettagli tecnici. Ci\u00f2 riduce il numero di ticket e garantisce un comportamento comprensibile. Una soluzione pulita <strong>UX<\/strong> rende i limiti accettabili ed evita la frustrazione.<\/p>\n\n<h2>Host, rete e kernel: rafforzare le basi<\/h2>\n\n<p>Un elevato traffico legittimo e le misure di difesa richiedono soluzioni affidabili <strong>Risorse<\/strong> e impostazioni predefinite adeguate a livello di rete. Mi assicuro che le versioni di NGINX siano aggiornate, che ci sia RAM sufficiente per le zone e che siano attive le funzioni di protezione contro gli attacchi di tipo \u201ctransport\u201d. Per contrastare gli attacchi SYN-flood \u00e8 utile attivare <a href=\"https:\/\/webhosting.de\/it\/tcp-syn-cookies-protezione-syn-flood-kernel\/\">Cookie TCP SYN<\/a> nel kernel, in modo che le connessioni non rimangano bloccate. In definitiva, questo alleggerisce NGINX da un carico superfluo. In questo modo concentro i limiti sui livelli HTTP e mantengo il <strong>Produttivit\u00e0<\/strong> stabile.<\/p>\n\n\n<figure class=\"wp-block-image size-full is-resized\">\n  <img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/webhosting.de\/wp-content\/uploads\/2026\/09\/nginx-ratelimit-schutz-4829.png\" alt=\"\" width=\"1536\" height=\"1024\"\/>\n<\/figure>\n\n\n<h2>In breve: ecco come utilizzo in modo efficace il Rate Limiting di NGINX<\/h2>\n\n<p>Limito le richieste in base a <strong>chiave<\/strong>, isolo i percorsi critici e tengo a distanza i bot grazie a zone rigorosamente definite. Le funzionalit\u00e0 Burst e nodelay aiutano a consentire picchi legittimi senza favorire gli abusi. Attraverso i log 429, calibro continuamente i valori e inasprisco i limiti solo dove \u00e8 necessario. In combinazione con WAF, difesa DDoS, monitoraggio e hardening del kernel, si crea un concetto di protezione resiliente. Chi lo implementa in modo coerente riduce significativamente il traffico dei bot e preserva <strong>Prestazioni<\/strong> anche sotto carico.<\/p>\n\n<h2>Elementi che spesso mancano nella pratica<\/h2>\n\n<p>In molte configurazioni mancano alcuni componenti fondamentali che aumentano sensibilmente l'efficacia del rate limiting:<\/p>\n<ul>\n  <li><strong>IP reali dei client dietro i proxy<\/strong>: Se la gestione dell\u2019IP reale non \u00e8 corretta, NGINX spesso limita l\u2019IP del bilanciatore di carico; in tal caso, i limiti si applicano a tutti gli utenti raggruppati a valle.<\/li>\n  <li><strong>Prove a secco (dry-run)<\/strong>: I limiti vengono attivati \u201ealla cieca\u201c. \u00c8 preferibile registrare in anticipo solo il numero di volte in cui un limite sarebbe scattato.<\/li>\n  <li><strong>Chiavi a grana fine<\/strong>: Anzich\u00e9 limitarsi all\u2019indirizzo IP, \u00e8 opportuno applicare limitazioni per ogni token API, sessione o utente, al fine di garantire una maggiore equit\u00e0.<\/li>\n  <li><strong>Interazione con limit_conn<\/strong>: Le connessioni parallele e le frequenze delle richieste coprono diversi modelli di abuso.<\/li>\n  <li><strong>Eccezioni mirate<\/strong>: Gli health check, i webhook o i servizi interni richiedono spesso limiti meno rigidi o addirittura nessun limite.<\/li>\n<\/ul>\n\n<h2>Proxy inverso: analizzare in modo sicuro l'IP reale del client<\/h2>\n\n<p>Se NGINX si trova dietro un bilanciatore di carico, imposto le direttive Real-IP in modo che $binary_remote_addr rifletta il client effettivo. Mi fido solo delle reti di mia propriet\u00e0 e attivo la valutazione ricorsiva:<\/p>\n\n<pre><code>http {\n  # Intervalli IP proxy affidabili (esempio)\n  set_real_ip_from 10.0.0.0\/8;\n  set_real_ip_from 192.168.0.0\/16;\n  # Aggiungere eventualmente intervalli LB\/CDN pubblici\n\n  real_ip_header X-Forwarded-For;\n  real_ip_recursive on;\n\n  limit_req_zone $binary_remote_addr zone=perip:20m rate=10r\/s;\n}\n<\/code><\/pre>\n\n<p>Senza questa impostazione, un limite finirebbe altrimenti per interessare contemporaneamente molti utenti innocenti. Dopo la configurazione, controllo tramite i log di accesso se compare l\u2019IP del client previsto.<\/p>\n\n<h2>Strategia chiave: IP, utente, token e percorso<\/h2>\n\n<p>La chiave scelta determina l'equit\u00e0 e l'efficacia. Alcuni modelli collaudati:<\/p>\n<ul>\n  <li><strong>Pro IP<\/strong> ($binary_remote_addr): pronto all\u2019uso, ideale per \/login e endpoint anonimi.<\/li>\n  <li><strong>Per ogni token API<\/strong>: Equit\u00e0 tra i clienti; protegge dal raggruppamento NAT. Estraggo i token tramite map.<\/li>\n  <li><strong>Per ogni classe di percorso<\/strong>: Limitare separatamente gli endpoint pi\u00f9 costosi, ad esempio \/search in misura maggiore rispetto a \/status.<\/li>\n<\/ul>\n\n<pre><code>map $http_authorization $api_token {\n  default \"\";\n  \"~*^Bearer\\s+(.+)$\" $1;\n}\n\nlimit_req_zone $api_token zone=per_token:30m rate=5r\/s;\n\nserver {\n  location \/api\/ {\n    # Rilevole solo se \u00e8 presente un token\n    limit_req zone=per_token burst=10;\n    limit_req_status 429;\n  }\n}\n<\/code><\/pre>\n\n<p>Importante: un\u2019elevata cardinalit\u00e0 delle chiavi consuma memoria nella zona. Prevedere dei buffer e monitorare l\u2019utilizzo della memoria.<\/p>\n\n<h2>Accumulo e dimensionamento delle zone<\/h2>\n\n<p>La zona memorizza i metadati per ogni chiave attiva. Il consumo per ogni voce \u00e8 di alcune decine di byte pi\u00f9 l'overhead. Da ci\u00f2 deduco che:<\/p>\n<ul>\n  <li>Per un numero elevato di IP\/token simultanei, scelgo zone pi\u00f9 grandi, ad esempio da 50 a 100 MB.<\/li>\n  <li>Comincio con impostazioni piuttosto generose e leggo i log di NGINX: il messaggio \u201eshared memory zone is full\u201c indica la necessit\u00e0 di una nuova ottimizzazione.<\/li>\n  <li>Le chiavi inutilizzate scadono dopo un breve periodo di inattivit\u00e0; i picchi sono pi\u00f9 importanti della media giornaliera.<\/li>\n<\/ul>\n\n<h2>Utilizzare con precisione le funzioni \"Burst\" e \"nodelay\"<\/h2>\n\n<p>Senza <strong>nodelay<\/strong> NGINX raggruppa i superamenti all\u2019interno del buffer di burst e <em>ritardato<\/em> Richieste. Con <strong>nodelay<\/strong> Le richieste in burst consentite vengono immediatamente accettate, mentre quelle in eccesso vengono respinte. Il mio approccio:<\/p>\n<ul>\n  <li><strong>Percorsi interattivi<\/strong> (HTML): meglio evitare il tag `nodelay`, per generare brevi tempi di attesa anzich\u00e9 un errore 429 definitivo.<\/li>\n  <li><strong>API<\/strong>: spesso con \"nodelay\", in modo che i client ricevano chiaramente il codice di errore 429 e applichino il backoff.<\/li>\n  <li><strong>Terminali costosi<\/strong>: un breve burst per appianare i picchi del backend.<\/li>\n<\/ul>\n\n<h2>Prova generale, livello di log e analisi<\/h2>\n\n<p>Prima di rendere effettivi i limiti, attivo la modalit\u00e0 Dry-Run e regolo il livello di log. In questo modo posso vedere l'effetto senza correre rischi:<\/p>\n\n<pre><code>server {\n  location \/api\/ {\n    limit_req zone=perip burst=20;\n    limit_req_dry_run on; # solo registrazione, nessun blocco\n    limit_req_log_level notice;  # meno grave di 'error'\n  }\n}\n<\/code><\/pre>\n\n<p>Successivamente analizzo i dati di accesso relativi a un periodo di 3\u20137 giorni, individuo i punti critici, regolo la velocit\u00e0 e il burst e solo allora disattivo il Dry-Run.<\/p>\n\n<h2>429: trasporto corretto: HTML, JSON e Retry-After<\/h2>\n\n<p>Per garantire una buona esperienza utente (UX), distinguo tra browser e client API e impiego <strong>Retry-After<\/strong>. Ecco come comunico chiaramente i limiti:<\/p>\n\n<pre><code>map $http_accept $wants_json {\n  default 0;\n  \"~*application\/json|\/json\"    1;\n}\n\nserver {\n  error_page 429 = @rate_limited;\n\n  location @rate_limited {\n    add_header Retry-After 2 always;\n    if ($wants_json) {\n add_header Content-Type application\/json;\n      return 429 '{\"error\":\"too_many_requests\",\"retry_after\":2}';\n    }\n    return 429 \"Si prega di riprovare pi\u00f9 tardi.\";\n  }\n}\n<\/code><\/pre>\n\n<p>Le API possono reagire in modo programmatico, mentre gli utenti ricevono un messaggio chiaro.<\/p>\n\n<h2>Combinare limit_req e limit_conn<\/h2>\n\n<p><strong>limit_req<\/strong> portata per intervallo di tempo, <strong>limit_conn<\/strong> limita il numero di connessioni simultanee. Per contrastare i download, i client \"chatty\" o i picchi di traffico HTTP\/2, combino entrambe le soluzioni:<\/p>\n\n<pre><code>limit_conn_zone $binary_remote_addr zone=perip_conn:10m;\n\nserver {\n  location \/api\/ {\n    limit_req  zone=perip burst=20 nodelay;\n    limit_conn zone=perip_conn 20;  # max. 20 connessioni simultanee per IP\n  }\n}\n<\/code><\/pre>\n\n<p>In questo modo evito che alcuni client, pur rispettando la velocit\u00e0 di trasmissione, occupino troppe risorse con un numero eccessivo di connessioni simultanee.<\/p>\n\n<h2>Eccezioni, controlli di integrit\u00e0 e percorsi interni<\/h2>\n\n<p>Non tutti i percorsi necessitano di limiti. Gli health check (\/healthz), i webhook interni o i callback di pagamento hanno location dedicate senza limit_req \u2013 oppure con valori pi\u00f9 moderati:<\/p>\n\n<pre><code>server {\n  # nessun limite per i controlli di integrit\u00e0\n  location = \/healthz { return 200 \"ok\"; }\n\n  # limiti moderati per i callback di pagamento\n  location \/webhooks\/pay\/ {\n    limit_req zone=perip burst=5;\n  }\n\n  # protezione rigorosa per il login\n  location = \/login {\n    limit_req zone=perip rate=1r\/s burst=3;\n  }\n}\n<\/code><\/pre>\n\n<p>Le eccezioni granulari riducono i falsi positivi e garantiscono la stabilit\u00e0 delle integrazioni.<\/p>\n\n<h2>Un routing a zone pi\u00f9 solido senza la \u201cmagia\u201d di If<\/h2>\n\n<p>Per la separazione \u201ebot vs. utente\u201c, preferisco utilizzare reindirizzamenti interni tramite \u201cnamed locations\u201d. Ci\u00f2 rende la configurazione chiara e prevedibile:<\/p>\n\n<pre><code>map $http_user_agent $is_bot {\n  default 0;\n  \"~*googlebot|bingbot\" 0;\n  \"~*crawler|scraper|bot\" 1;\n}\n\nlimit_req_zone $binary_remote_addr zone=human:20m rate=10r\/s;\nlimit_req_zone $binary_remote_addr zone=bot:10m   rate=1r\/s;\n\nserver {\n  error_page 418 = @bot;\n\n  location \/ {\n    if ($is_bot) { return 418; }   # reindirizzamento interno\n    limit_req zone=human burst=20 nodelay;\n    limit_req_status 429;\n    try_files $uri $uri\/ \/index.html;\n  }\n\n  location @bot {\n    limit_req zone=bot burst=5;\n    limit_req_status 429;\n  }\n}\n<\/code><\/pre>\n\n<p>In questo modo, i bot finiscono in modo deterministico nella zona rigorosa, mentre le persone in quella rilassata \u2013 senza che i due limiti agiscano contemporaneamente.<\/p>\n\n<h2>Provare, misurare, indossare: una procedura pragmatica<\/h2>\n\n<ul>\n  <li><strong>Messa in scena<\/strong>: Scegliere un\u2019impostazione conservativa per Rate\/Burst, attivare Dry-Run, eseguire il carico sintetico sul percorso critico.<\/li>\n  <li><strong>Test del fumo<\/strong>: Generare brevi raffiche con curl o Lasttools e verificare il comportamento del codice 429\/Delay.<\/li>\n  <li><strong>Progetto pilota produttivo<\/strong>: Per prima cosa, applicare la misura a singole sedi e monitorare attentamente i log.<\/li>\n  <li><strong>Affilatura iterativa<\/strong>: Applicare i limiti solo dove si notano degli schemi ricorrenti; ridurre al minimo i falsi allarmi.<\/li>\n<\/ul>\n\n<pre><code>Esempio #: test di burst veloce con curl\nfor i in {1..50}; do curl -s -o \/dev\/null -w \"%{http_code}\\n\" https:\/\/example.com\/login &amp; done; wait\n<\/code><\/pre>\n\n<h2>Frequenze in minuti anzich\u00e9 in secondi e percorsi granulari<\/h2>\n\n<p>NGINX consente di impostare intervalli in secondi o minuti (<strong>r\/s<\/strong>, <strong>r\/m<\/strong>). In caso di abuso di login, spesso imposto 60 richieste al minuto anzich\u00e9 1 al secondo, per consentire brevi doppi clic legittimi ma limitare il fuoco continuo. Ai percorsi costosi vengono applicati limiti pi\u00f9 restrittivi rispetto a quelli economici. Esempio:<\/p>\n\n<pre><code>limit_req_zone $binary_remote_addr zone=perip_min:20m rate=60r\/m;\n\nserver {\n  location \/search\/ {\n    limit_req zone=perip_min burst=10;   # pi\u00f9 rigoroso\n  }\n  location \/status {\n    # nessun limite \u2013 economico e utilizzato internamente\n    return 200;\n  }\n}\n<\/code><\/pre>\n\n<h2>Gli ostacoli e come evitarli<\/h2>\n\n<ul>\n  <li><strong>Chiave sbagliata<\/strong>: Quando utilizzo proxy senza indirizzo IP reale, finisco per limitare inavvertitamente tutti gli utenti contemporaneamente.<\/li>\n  <li><strong>Zone troppo piccole<\/strong>: Il messaggio \u201ezone is full\u201c comporta un comportamento imprevedibile \u2013 prevedere dimensioni generose.<\/li>\n  <li><strong>Un limite per tutto<\/strong>: Percorsi diversi richiedono valori diversi; un approccio \u201cuniversale\u201d genera frustrazione.<\/li>\n  <li><strong>Nessun monitoraggio<\/strong>: Senza l'analisi 429, le configurazioni errate passano inosservate.<\/li>\n  <li><strong>Lista bianca estesa<\/strong>: Eccezioni troppo ampie aprono le porte a ogni sorta di abuso \u2013 occorre creare una lista bianca mirata, temporanea e trasparente.<\/li>\n<\/ul>\n\n<h2>Caratteristiche specifiche di HTTP\/2, SSE e caching<\/h2>\n\n<p>HTTP\/2 raggruppa le richieste su un numero ridotto di connessioni; <strong>limit_conn<\/strong> rimane comunque rilevante, poich\u00e9 gli streaming consumano risorse. Gli eventi inviati dal server o i download di lunga durata raramente attivano i limiti di velocit\u00e0 (pochi request), ma richiedono tempo: in questi casi applico limitazioni in parallelo con `limit_conn` o implemento strategie di gestione della larghezza di banda. Ove possibile, alleggerisco il carico con <strong>Caching<\/strong> (ad es. risorse statiche, richieste GET frequenti), in modo che i limiti vengano applicati meno spesso e gli utenti ricevano risposte pi\u00f9 rapide.<\/p>\n\n<h2>Lista di controllo operativa<\/h2>\n\n<ul>\n  <li>IP reale corretto, chiave definita (IP\/token\/utente)<\/li>\n  <li>Zone di dimensioni generose, metriche\/log disponibili<\/li>\n  <li>frequenza\/burst regolata per classe di percorso, nodelay impostato intenzionalmente<\/li>\n  <li>Testato in modalit\u00e0 dry-run, implementata la comunicazione 429 (Retry-After)<\/li>\n  <li>Eccezioni per Health\/Webhooks, combinazione con limit_conn<\/li>\n  <li>Ricalibrazione iterativa e segnalazione delle anomalie<\/li>\n<\/ul>","protected":false},"excerpt":{"rendered":"<p>Scopri come proteggere il tuo sito web dal traffico dei bot e dagli attacchi grazie al Rate Limiting di NGINX, aumentando cos\u00ec la sicurezza del server web. Sono inclusi esempi pratici e best practice.<\/p>","protected":false},"author":1,"featured_media":21248,"comment_status":"","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"footnotes":""},"categories":[834],"tags":[],"class_list":["post-21255","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-plesk-webserver-plesk-administration-anleitungen"],"acf":[],"_wp_attached_file":null,"_wp_attachment_metadata":null,"litespeed-optimize-size":null,"litespeed-optimize-set":null,"_elementor_source_image_hash":null,"_wp_attachment_image_alt":null,"stockpack_author_name":null,"stockpack_author_url":null,"stockpack_provider":null,"stockpack_image_url":null,"stockpack_license":null,"stockpack_license_url":null,"stockpack_modification":null,"color":null,"original_id":null,"original_url":null,"original_link":null,"unsplash_location":null,"unsplash_sponsor":null,"unsplash_exif":null,"unsplash_attachment_metadata":null,"_elementor_is_screenshot":null,"surfer_file_name":null,"surfer_file_original_url":null,"envato_tk_source_kit":null,"envato_tk_source_index":null,"envato_tk_manifest":null,"envato_tk_folder_name":null,"envato_tk_builder":null,"envato_elements_download_event":null,"_menu_item_type":null,"_menu_item_menu_item_parent":null,"_menu_item_object_id":null,"_menu_item_object":null,"_menu_item_target":null,"_menu_item_classes":null,"_menu_item_xfn":null,"_menu_item_url":null,"_trp_menu_languages":null,"rank_math_primary_category":null,"rank_math_title":null,"inline_featured_image":null,"_yoast_wpseo_primary_category":null,"rank_math_schema_blogposting":null,"rank_math_schema_videoobject":null,"_oembed_049c719bc4a9f89deaead66a7da9fddc":null,"_oembed_time_049c719bc4a9f89deaead66a7da9fddc":null,"_yoast_wpseo_focuskw":null,"_yoast_wpseo_linkdex":null,"_oembed_27e3473bf8bec795fbeb3a9d38489348":null,"_oembed_c3b0f6959478faf92a1f343d8f96b19e":null,"_trp_translated_slug_en_us":null,"_wp_desired_post_slug":null,"_yoast_wpseo_title":null,"tldname":null,"tldpreis":null,"tldrubrik":null,"tldpolicylink":null,"tldsize":null,"tldregistrierungsdauer":null,"tldtransfer":null,"tldwhoisprivacy":null,"tldregistrarchange":null,"tldregistrantchange":null,"tldwhoisupdate":null,"tldnameserverupdate":null,"tlddeletesofort":null,"tlddeleteexpire":null,"tldumlaute":null,"tldrestore":null,"tldsubcategory":null,"tldbildname":null,"tldbildurl":null,"tldclean":null,"tldcategory":null,"tldpolicy":null,"tldbesonderheiten":null,"tld_bedeutung":null,"_oembed_d167040d816d8f94c072940c8009f5f8":null,"_oembed_b0a0fa59ef14f8870da2c63f2027d064":null,"_oembed_4792fa4dfb2a8f09ab950a73b7f313ba":null,"_oembed_33ceb1fe54a8ab775d9410abf699878d":null,"_oembed_fd7014d14d919b45ec004937c0db9335":null,"_oembed_21a029d076783ec3e8042698c351bd7e":null,"_oembed_be5ea8a0c7b18e658f08cc571a909452":null,"_oembed_a9ca7a298b19f9b48ec5914e010294d2":null,"_oembed_f8db6b27d08a2bb1f920e7647808899a":null,"_oembed_168ebde5096e77d8a89326519af9e022":null,"_oembed_cdb76f1b345b42743edfe25481b6f98f":null,"_oembed_87b0613611ae54e86e8864265404b0a1":null,"_oembed_27aa0e5cf3f1bb4bc416a4641a5ac273":null,"_oembed_time_27aa0e5cf3f1bb4bc416a4641a5ac273":null,"_tldname":null,"_tldclean":null,"_tldpreis":null,"_tldcategory":null,"_tldsubcategory":null,"_tldpolicy":null,"_tldpolicylink":null,"_tldsize":null,"_tldregistrierungsdauer":null,"_tldtransfer":null,"_tldwhoisprivacy":null,"_tldregistrarchange":null,"_tldregistrantchange":null,"_tldwhoisupdate":null,"_tldnameserverupdate":null,"_tlddeletesofort":null,"_tlddeleteexpire":null,"_tldumlaute":null,"_tldrestore":null,"_tldbildname":null,"_tldbildurl":null,"_tld_bedeutung":null,"_tldbesonderheiten":null,"_oembed_ad96e4112edb9f8ffa35731d4098bc6b":null,"_oembed_8357e2b8a2575c74ed5978f262a10126":null,"_oembed_3d5fea5103dd0d22ec5d6a33eff7f863":null,"_eael_widget_elements":null,"_oembed_0d8a206f09633e3d62b95a15a4dd0487":null,"_oembed_time_0d8a206f09633e3d62b95a15a4dd0487":null,"_aioseo_description":null,"_eb_attr":null,"_eb_data_table":null,"_oembed_819a879e7da16dd629cfd15a97334c8a":null,"_oembed_time_819a879e7da16dd629cfd15a97334c8a":null,"_acf_changed":null,"_wpcode_auto_insert":null,"_edit_last":null,"_edit_lock":null,"_oembed_e7b913c6c84084ed9702cb4feb012ddd":null,"_oembed_bfde9e10f59a17b85fc8917fa7edf782":null,"_oembed_time_bfde9e10f59a17b85fc8917fa7edf782":null,"_oembed_03514b67990db061d7c4672de26dc514":null,"_oembed_time_03514b67990db061d7c4672de26dc514":null,"rank_math_news_sitemap_robots":null,"rank_math_robots":null,"_eael_post_view_count":"64","_trp_automatically_translated_slug_ru_ru":null,"_trp_automatically_translated_slug_et":null,"_trp_automatically_translated_slug_lv":null,"_trp_automatically_translated_slug_fr_fr":null,"_trp_automatically_translated_slug_en_us":null,"_wp_old_slug":null,"_trp_automatically_translated_slug_da_dk":null,"_trp_automatically_translated_slug_pl_pl":null,"_trp_automatically_translated_slug_es_es":null,"_trp_automatically_translated_slug_hu_hu":null,"_trp_automatically_translated_slug_fi":null,"_trp_automatically_translated_slug_ja":null,"_trp_automatically_translated_slug_lt_lt":null,"_elementor_edit_mode":null,"_elementor_template_type":null,"_elementor_version":null,"_elementor_pro_version":null,"_wp_page_template":null,"_elementor_page_settings":null,"_elementor_data":null,"_elementor_css":null,"_elementor_conditions":null,"_happyaddons_elements_cache":null,"_oembed_75446120c39305f0da0ccd147f6de9cb":null,"_oembed_time_75446120c39305f0da0ccd147f6de9cb":null,"_oembed_3efb2c3e76a18143e7207993a2a6939a":null,"_oembed_time_3efb2c3e76a18143e7207993a2a6939a":null,"_oembed_59808117857ddf57e478a31d79f76e4d":null,"_oembed_time_59808117857ddf57e478a31d79f76e4d":null,"_oembed_965c5b49aa8d22ce37dfb3bde0268600":null,"_oembed_time_965c5b49aa8d22ce37dfb3bde0268600":null,"_oembed_81002f7ee3604f645db4ebcfd1912acf":null,"_oembed_time_81002f7ee3604f645db4ebcfd1912acf":null,"_elementor_screenshot":null,"_oembed_7ea3429961cf98fa85da9747683af827":null,"_oembed_time_7ea3429961cf98fa85da9747683af827":null,"_elementor_controls_usage":null,"_elementor_page_assets":[],"_elementor_screenshot_failed":null,"theplus_transient_widgets":null,"_eael_custom_js":null,"_wp_old_date":null,"_trp_automatically_translated_slug_it_it":null,"_trp_automatically_translated_slug_pt_pt":null,"_trp_automatically_translated_slug_zh_cn":null,"_trp_automatically_translated_slug_nl_nl":null,"_trp_automatically_translated_slug_pt_br":null,"_trp_automatically_translated_slug_sv_se":null,"rank_math_analytic_object_id":null,"rank_math_internal_links_processed":"1","_trp_automatically_translated_slug_ro_ro":null,"_trp_automatically_translated_slug_sk_sk":null,"_trp_automatically_translated_slug_bg_bg":null,"_trp_automatically_translated_slug_sl_si":null,"litespeed_vpi_list":null,"litespeed_vpi_list_mobile":null,"rank_math_seo_score":null,"rank_math_contentai_score":null,"ilj_limitincominglinks":null,"ilj_maxincominglinks":null,"ilj_limitoutgoinglinks":null,"ilj_maxoutgoinglinks":null,"ilj_limitlinksperparagraph":null,"ilj_linksperparagraph":null,"ilj_blacklistdefinition":null,"ilj_linkdefinition":null,"_eb_reusable_block_ids":null,"rank_math_focus_keyword":"NGINX Rate","rank_math_og_content_image":null,"_yoast_wpseo_metadesc":null,"_yoast_wpseo_content_score":null,"_yoast_wpseo_focuskeywords":null,"_yoast_wpseo_keywordsynonyms":null,"_yoast_wpseo_estimated-reading-time-minutes":null,"rank_math_description":null,"surfer_last_post_update":null,"surfer_last_post_update_direction":null,"surfer_keywords":null,"surfer_location":null,"surfer_draft_id":null,"surfer_permalink_hash":null,"surfer_scrape_ready":null,"_thumbnail_id":"21248","footnotes":null,"_links":{"self":[{"href":"https:\/\/webhosting.de\/it\/wp-json\/wp\/v2\/posts\/21255","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/webhosting.de\/it\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/webhosting.de\/it\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/webhosting.de\/it\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/webhosting.de\/it\/wp-json\/wp\/v2\/comments?post=21255"}],"version-history":[{"count":0,"href":"https:\/\/webhosting.de\/it\/wp-json\/wp\/v2\/posts\/21255\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/webhosting.de\/it\/wp-json\/wp\/v2\/media\/21248"}],"wp:attachment":[{"href":"https:\/\/webhosting.de\/it\/wp-json\/wp\/v2\/media?parent=21255"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/webhosting.de\/it\/wp-json\/wp\/v2\/categories?post=21255"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/webhosting.de\/it\/wp-json\/wp\/v2\/tags?post=21255"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}