Torna al blog

Come leggere i log di accesso di Nginx

2025-08-2012 min di lettura

Quando qualcosa non funziona, il log di accesso racconta una storia. Chi ha colpito il sito. Cosa hanno chiesto. Quali URL sono falliti. Quando è iniziata un'impennata. Ho usato questi passaggi in un progetto reale e hanno funzionato. Gli esempi seguenti sono sicuri da copiare ed eseguire, quindi da adattare alla tua configurazione.

Cosa sono i log di accesso di Nginx?

I log di accesso di Nginx sono file di testo che registrano ogni richiesta HTTP ricevuta dal tuo web server. Ogni riga rappresenta una richiesta e contiene dettagli come l'indirizzo IP del client, il timestamp, il metodo HTTP, il percorso dell'URL, il codice di stato, la dimensione della risposta e altro ancora.

Questi log vengono generati automaticamente da Nginx durante l'elaborazione delle richieste. Ogni volta che qualcuno visita il tuo sito, fa clic su un link, invia un modulo o raggiunge un URL non valido, Nginx scrive una riga nel log di accesso. Ciò avviene in tempo reale, quindi il file di log cresce costantemente.

Come funzionano i log di accesso

Nginx utilizza un formato di log configurabile definito nel file nginx.conf. Il formato predefinito è il seguente:

log_format main '$remote_addr - $remote_user [$time_local] "$request" '
                '$status $body_bytes_sent "$http_referer" '
                '"$http_user_agent"';

Ciò crea voci di log come:

192.168.1.100 - - [20/Aug/2025:10:30:45 +0000] "GET /blog/post HTTP/1.1" 200 1234 "https://example.com/" "Mozilla/5.0..."

Molte configurazioni moderne utilizzano un formato più dettagliato simile a JSON con coppie chiave=valore, che è ciò che gli esempi in questo post presuppongono.

CDN vs. Origine: dove cercare i log

Se stai utilizzando una CDN (come Cloudflare, CloudFront o Fastly), ci sono due diversi set di log da considerare:

Log edge della CDN: mostrano le richieste degli utenti effettivi che raggiungono la CDN. Questi contengono gli IP client reali, gli user agent e le posizioni geografiche.

Log del server di origine (ciò che questo post copre): mostrano le richieste che hanno superato la CDN fino al tuo server Nginx. Questi log spesso mostrano l'indirizzo IP della CDN come client, non l'IP dell'utente finale.

Per la risoluzione dei problemi, di solito si desiderano prima i log della CDN. Controlla i log di origine solo quando è necessario vedere cosa ha effettivamente raggiunto il tuo server o quando si risolvono problemi lato server.

Tutti gli esempi presuppongono log chiave=valore (campi come status="404" e request="GET /path HTTP/1.1"), e file in /var/log/nginx/. Modifica i nomi secondo necessità.

Cosa imparerai

  • Come leggere log live e gzipped in un'unica volta
  • Come trovare gli IP principali e gli URL falliti principali
  • Come estrarre tutto da un singolo IP
  • Come ingrandire una breve finestra temporale
  • Come collegare i log di accesso ai blocchi WAF
  • Come mantenere i risultati veloci e utili

Avvio rapido

Leggi tutto, indipendentemente dal fatto che il file sia .log o .gz:

zgrep -h . /var/log/nginx/ssl-*.access.log*

Quel trucco zgrep gestisce sia i file normali che quelli ruotati. Aggiungi filtri dopo di esso.

Strumenti che utilizzerai

zgrep: simile a grep ma funziona sia su file regolari che su file compressi (.gz). Perfetto per i file di log che vengono ruotati e compressi.

awk: un potente strumento di elaborazione del testo che può dividere le righe per delimitatori ed estrarre campi specifici. Ottimo per analizzare formati di log strutturati.

cut: estrae colonne o campi specifici dal testo. Usa -d per specificare un delimitatore (come virgolette o virgole) e -f per scegliere quale numero di campo desideri.

Trova gli IP principali dietro le tempeste di 404

Quando gli editori segnalano "molti link interrotti", inizia da qui.

zgrep -h . /var/log/nginx/ssl-*.access.log* \
| awk -F'status="' '$2 ~ /^404"/' \
| awk -F'x_forwarded_for="' '{print $2}' \
| cut -d'"' -f1 | cut -d',' -f1 \
| LC_ALL=C sort | uniq -c | sort -nr | head

Perché aiuta. Vedi prima i peggiori trasgressori. Se un IP sta scansionando percorsi casuali, lo individuerai velocemente.

Vedi tutto ciò che ha fatto un singolo IP

Utile quando devi spiegare un blocco o un picco da una sorgente.

IP="112.134.209.112"
zgrep -h . /var/log/nginx/ssl-*.access.log* \
| grep -F 'x_forwarded_for="'$IP

Suggerimento. In alcuni stack l'IP del client può trovarsi in src o src_ip. In tal caso, scambia il nome del campo nel grep.

URL principali colpiti da quell'IP (ignora le stringhe di query)

IP="112.134.209.112"
zgrep -h . /var/log/nginx/ssl-*.access.log* \
| grep -F 'x_forwarded_for="'$IP \
| awk -F'request="' '{print $2}' | cut -d'"' -f1 \
| awk '{print $2}' | cut -d'?' -f1 \
| LC_ALL=C sort | uniq -c | sort -nr | head

Perché aiuta. L'eliminazione della stringa di query raggruppa "la stessa pagina con parametri diversi", il che rende i pattern evidenti.

URL falliti principali per stato

404:

zgrep -h . /var/log/nginx/ssl-*.access.log* \
| awk -F'status="' '$2 ~ /^404"/' \
| awk -F'request="' '{print $2}' | cut -d'"' -f1 \
| awk '{print $2}' | cut -d'?' -f1 \
| LC_ALL=C sort | uniq -c | sort -nr | head

5xx:

zgrep -h . /var/log/nginx/ssl-*.access.log* \
| awk -F'status="' '{split($2,a,"\""); if (a[1] ~ /^5[0-9][0-9]$/) print}' \
| awk -F'request="' '{print $2}' | cut -d'"' -f1 \
| awk '{print $2}' | cut -d'?' -f1 \
| LC_ALL=C sort | uniq -c | sort -nr | head

Perché aiuta. Questo ti fornisce un elenco classificato dei percorsi problematici. Correggi i primi cinque e spesso risolverai la maggior parte dei problemi.

Ingrandisci una breve finestra temporale

Quando un picco colpisce in un momento noto, vuoi il prima e il dopo.

Semplice e veloce (abbastanza buono per una finestra di 10 minuti all'interno della stessa ora):

# Esempio: 09/Aug/2025 23:15–23:25
zgrep -h 'time_local="' /var/log/nginx/ssl-*.access.log* \
| egrep '09/Aug/2025:23:1[5-9]|09/Aug/2025:23:2[0-5]'

Invia il risultato a uno qualsiasi dei conteggi sopra.

Perché aiuta. Confronti il traffico subito prima e subito dopo un evento, che è spesso tutto ciò che ti serve per vedere cosa è cambiato.

Post di moduli e corpi di grandi dimensioni

POST di grandi dimensioni a un modulo possono attivare le regole WAF. Misurale.

PATH_RE="/about/.*speaker-request-form"
zgrep -h . /var/log/nginx/ssl-*.access.log* \
| awk -F'request="' -v r="$PATH_RE" '
  { split($2,a,"\""); split(a[1],b," "); m=b[1]; u=b[2];
    if (m=="POST" && u ~ r) print }' \
| awk -F'request_length="' '{print $2}' | cut -d'"' -f1 \
| awk '{sum+=$1; c++} END{print "POST count="c, "avg_request_length=" (c?sum/c:0)}'

Perché aiuta. Se la dimensione media della richiesta è elevata, la tua WAF potrebbe bloccare l'ispezione. Ora hai prove e numeri.

Collega i log di accesso ai blocchi WAF

  1. Prendi l'ora esatta e la regola dall'evento WAF.
  2. Filtra i log di accesso per quella finestra utilizzando il trucco della "finestra temporale".
  3. Cerca lo stesso percorso, lo stesso IP o una request_length elevata.
  4. Se la regola WAF parla di dimensioni del corpo o limiti di ispezione, conferma con l'analisi POST sopra.

Questo chiude il cerchio. Puoi dire cosa è successo e perché è successo.

Suggerimenti sulla velocità che contano

  • Filtra presto. Aggiungi grep 'status="404"' prima di ordinare.
  • Usa LC_ALL=C sort per un ordinamento più veloce e stabile.
  • Elimina le stringhe di query per raggruppare le pagine per percorso.
  • Esegui prima un campionamento. Esegui head su una pipeline per verificare di estrarre il campo corretto.
  • Documenta il tuo log_format nel repository. Il tuo futuro te ne sarà grato.

Errori comuni

  • Contare per remote_addr quando la tua app si trova dietro un proxy. Usa x_forwarded_for o il tuo campo IP client reale.
  • Presupporre che tutti i file di log utilizzino lo stesso formato. Controlla il tuo log_format nginx.conf prima di analizzare.
  • Dimenticare che i log ruotati (file .gz) richiedono zgrep, non grep.
  • Utilizzare pattern regex complessi che si interrompono quando i formati di log cambiano. Mantienilo semplice.

Punti chiave

I log rispondono rapidamente a domande reali. Inizia con una domanda chiara, invia solo ciò di cui hai bisogno e conta. Collega ciò che vedi in Nginx a ciò che riporta la tua WAF. Passerai da "qualcosa sembrava lento" a "questo URL è fallito 2.379 volte da un IP in dieci minuti, ed ecco la correzione".