Lo sappiamo tutti: in un panorama digitale in continua evoluzione, la sicurezza informatica non è più un optional, ma un pilastro fondamentale di qualsiasi infrastruttura web seria. La recente decisione di migrare l’infrastruttura di questo blog sotto la “protezione” di Cloudflare non è stata solo una mossa per l’ottimizzazione delle performance, ma un passo per rinforzare la postura di sicurezza.
Questo post esplorerà due aspetti critici: come è stato tecnicamente integrato Cloudflare con la configurazione Nginx, quali sono i limiti di questa soluzione, come mitigarli e gli attacchi più comuni in uno scenario di offuscamento delle risorse esposte.
Per prima cosa è stato creato uno script che permetta di interrogare e scaricare le liste degli IP della CDN di Cloudflare: questo script può essere inserito in un job cron per tenere costantemente aggiornate le subnet.
#!/bin/bash
# File di configurazione Nginx in cui verranno salvate le direttive 'allow'
NGINX_ALLOW_CONF="/etc/nginx/conf.d/cloudflare_allow_ips.conf"
# URL da cui scaricare gli IP di Cloudflare (IPv4 e IPv6)
IPV4_URL="https://www.cloudflare.com/ips-v4/"
IPV6_URL="https://www.cloudflare.com/ips-v6/"
# Percorso temporaneo per i file scaricati
TEMP_IPV4=$(mktemp)
TEMP_IPV6=$(mktemp)
# 1. Scarica gli IP di Cloudflare
echo "Scarico gli intervalli IP Cloudflare..."
curl -s $IPV4_URL > $TEMP_IPV4
if [ $? -ne 0 ]; then
echo "ERRORE: Impossibile scaricare gli IP IPv4 di Cloudflare."
rm -f $TEMP_IPV4 $TEMP_IPV6
exit 1
fi
curl -s $IPV6_URL > $TEMP_IPV6
if [ $? -ne 0 ]; then
echo "ERRORE: Impossibile scaricare gli IP IPv6 di Cloudflare."
rm -f $TEMP_IPV4 $TEMP_IPV6
exit 1
fi
# 2. Genera il nuovo file di configurazione Nginx
echo "Generazione del file di configurazione Nginx..."
cat <<EOF > $NGINX_ALLOW_CONF
# Aggiornato da script il $(date)
#
# Permetti solo il traffico Cloudflare (IPv4)
$(cat $TEMP_IPV4 | sed 's/^/allow /g; s/$/;/g')
# Permetti solo il traffico Cloudflare (IPv6)
$(cat $TEMP_IPV6 | sed 's/^/allow /g; s/$/;/g')
# Blocca tutto il traffico restante
deny all;
EOF
# 3. Pulisci i file temporanei
rm -f $TEMP_IPV4 $TEMP_IPV6
Lo script crea un file dentro la /etc/nginx/conf.d/ chiamato cloudflare_allow_ips.conf che avrà questa sintassi
# Aggiornato da script il Thu Dec 11 18:55:48 UTC 2025
#
# Permetti solo il traffico Cloudflare (IPv4)
allow 173.245.48.0/20;
allow 103.21.244.0/22;
allow 103.22.200.0/22;
allow 103.31.4.0/22;
allow 141.101.64.0/18;
allow 108.162.192.0/18;
allow 190.93.240.0/20;
allow 188.114.96.0/20;
allow 197.234.240.0/22;
allow 198.41.128.0/17;
allow 162.158.0.0/15;
allow 104.16.0.0/13;
allow 104.24.0.0/14;
allow 172.64.0.0/13;
allow 131.0.72.0/22;
# Permetti solo il traffico Cloudflare (IPv6)
allow 2400:cb00::/32;
allow 2606:4700::/32;
allow 2803:f800::/32;
allow 2405:b500::/32;
allow 2405:8100::/32;
allow 2a06:98c0::/29;
allow 2c0f:f248::/32;
# Blocca tutto il traffico restante
deny all;
Il file dovrà successivamente essere inserito nel blocco http della configurazione di nginx (/etc/nginx/nginx.conf) se si vuole che le impostazioni vengano implementate su tutti i virtual host, diversamente dovranno essere inserite nei blocchi di configurazioni del singolo virtual host.
Sebbene CF aggiunga molti di questi headers ritengo essere importante aggiungerli comunque alle configurazioni originali: questo perchè laddove si volesse anche solo momentaneamente bypassare il proxy, si garantirebbe un buon livello di sicurezza crittografica di transito.
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Permissions-Policy "interest-cohort=()" always; # blocca FLoC
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
Limitate le versioni TLS, andando a deprecare quelle obsolete
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256';
Per il momento abbiamo esplorato come limitare tutte le connessioni in ingresso sull’nginx: tuttavia questo non è sufficiente in quanto il server, se un attaccante fosse in grado di scoprire il vero indirizzo dietro il WAF (in seguito vedremmo un esempio pratico di come fare), accetterà comunque tutte le connessioni in ingresso rendendolo di fatto passibile ad attacchi di tipo DDoS, SSRF, Amplification, etc.

La soluzione ottimale è quella di agire direttamente sul firewall di sistema, andando a bloccare immediatamente il traffico in ingresso laddove si dovesse presentare da un IP non appartenente alla CDN.
Lo script in bash scarica gli intervalli IP di Cloudflare (IPv4 e IPv6) e aggiunge le regole corrispondenti a iptables e ip6tables per permettere solo il traffico in ingresso proveniente da quegli indirizzi sulle porte 80 (HTTP) e 443 (HTTPS).
Lo script include anche una funzione per pulire le regole precedenti prima di aggiungere le nuove, rendendolo ideale per l’esecuzione periodica (ad esempio, tramite cron).
#!/bin/bash
# ===============================================
# Configurazione
# ===============================================
IPTABLES_V4_URL="https://www.cloudflare.com/ips-v4/"
IPTABLES_V6_URL="https://www.cloudflare.com/ips-v6/"
LOG_FILE="/var/log/cloudflare_iptables.log"
# Iniziale delle catene personalizzate per una facile pulizia
IPT_CHAIN="CLOUDFLARE_V4"
IP6T_CHAIN="CLOUDFLARE_V6"
# Porte da permettere
PORTS="80,443"
# ===============================================
# Funzioni
# ===============================================
# Funzione per loggare i messaggi
log() {
echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE"
}
# Funzione per pulire le regole esistenti di Cloudflare
cleanup_existing_rules() {
log "Pulizia delle catene e delle regole esistenti di Cloudflare..."
# 1. Pulizia catena IPv4 (iptables)
iptables -D INPUT -p tcp -m multiport --dports "$PORTS" -j "$IPT_CHAIN" 2>/dev/null
iptables -F "$IPT_CHAIN" 2>/dev/null
iptables -X "$IPT_CHAIN" 2>/dev/null
# 2. Pulizia catena IPv6 (ip6tables)
ip6tables -D INPUT -p tcp -m multiport --dports "$PORTS" -j "$IP6T_CHAIN" 2>/dev/null
ip6tables -F "$IP6T_CHAIN" 2>/dev/null
ip6tables -X "$IP6T_CHAIN" 2>/dev/null
log "Pulizia completata."
}
# Funzione principale per aggiornare le regole
update_cloudflare_rules() {
# 1. Creazione catene personalizzate
iptables -N "$IPT_CHAIN" || log "La catena $IPT_CHAIN esiste già o errore nella creazione."
ip6tables -N "$IP6T_CHAIN" || log "La catena $IP6T_CHAIN esiste già o errore nella creazione."
# 2. Aggiunta delle regole alle catene INPUT (solo se non esistono già)
# L'uso di "-C" (Check) è più sicuro
if ! iptables -C INPUT -p tcp -m multiport --dports "$PORTS" -j "$IPT_CHAIN" 2>/dev/null; then
iptables -I INPUT -p tcp -m multiport --dports "$PORTS" -j "$IPT_CHAIN"
log "Regola di salto IPv4 aggiunta alla catena INPUT."
else
log "Regola di salto IPv4 già esistente nella catena INPUT."
fi
if ! ip6tables -C INPUT -p tcp -m multiport --dports "$PORTS" -j "$IP6T_CHAIN" 2>/dev/null; then
ip6tables -I INPUT -p tcp -m multiport --dports "$PORTS" -j "$IP6T_CHAIN"
log "Regola di salto IPv6 aggiunta alla catena INPUT."
else
log "Regola di salto IPv6 già esistente nella catena INPUT."
fi
# 3. Scaricamento IP Cloudflare e aggiunta delle regole IPv4
log "Scarico e applico gli IP IPv4..."
local ip_count_v4=0
if curl -sS "$IPTABLES_V4_URL" | grep -E '^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}/[0-9]{1,2}$' | while IFS= read -r ip; do
iptables -A "$IPT_CHAIN" -s "$ip" -j ACCEPT
ip_count_v4=$((ip_count_v4 + 1))
done; then
log "Aggiunte $ip_count_v4 regole IPv4."
else
log "ERRORE: Impossibile scaricare o applicare gli IP IPv4."
return 1
fi
# 4. Scaricamento IP Cloudflare e aggiunta delle regole IPv6
log "Scarico e applico gli IP IPv6..."
local ip_count_v6=0
if curl -sS "$IPTABLES_V6_URL" | grep -E '^[0-9a-fA-F:/]+/[0-9]{1,3}$' | while IFS= read -r ip; do
ip6tables -A "$IP6T_CHAIN" -s "$ip" -j ACCEPT
ip_count_v6=$((ip_count_v6 + 1))
done; then
log "Aggiunte $ip_count_v6 regole IPv6."
else
log "ERRORE: Impossibile scaricare o applicare gli IP IPv6."
return 1
fi
# 5. Regola di default: DROP per tutto il resto
# Questa regola di DROP deve essere l'ultima nelle catene CLOUDFLARE_V4 e CLOUDFLARE_V6.
# Attenzione: Questo blocca *tutto* il traffico non-Cloudflare verso le porte 80/443!
iptables -A "$IPT_CHAIN" -j DROP
ip6tables -A "$IP6T_CHAIN" -j DROP
log "Aggiunta regola finale DROP nelle catene di Cloudflare."
# 6. Salvataggio delle regole (necessario su Ubuntu per la persistenza)
if command -v iptables-save >/dev/null 2>&1 && command -v netfilter-persistent >/dev/null 2>&1; then
log "Salvataggio delle regole tramite netfilter-persistent..."
netfilter-persistent save
elif command -v iptables-save >/dev/null 2>&1; then
log "Salvataggio delle regole con iptables-save/ip6tables-save (richiede configurazione)."
# Potrebbe essere necessario un comando specifico per la tua configurazione di persistenza,
# come 'service netfilter-persistent save' o 'iptables-save > /etc/iptables/rules.v4'
# Aggiungo un placeholder comune per sistemi più vecchi o generici:
# iptables-save > /etc/iptables/rules.v4
# ip6tables-save > /etc/iptables/rules.v6
else
log "ATTENZIONE: Nessun comando di salvataggio persistente trovato (iptables-save o netfilter-persistent)."
fi
log "Aggiornamento Cloudflare completato con successo."
}
# ===============================================
# Esecuzione
# ===============================================
# Esegue prima la pulizia
cleanup_existing_rules
# Esegue l'aggiornamento
update_cloudflare_rules
exit 0
Il risultato

Fino ad ora abbiamo visto come l’adozione di una CDN come Cloudflare è prassi standard per la mitigazione dei vettori di attacco di Layer 7 e per l’occultamento dell’indirizzo IP d’origine. Implementare un reverse proxy di questo tipo è un passo cruciale per la difesa, ma la sicurezza di questa configurazione dipende intrinsecamente dalla configurazione del server retrostante. Una delle tecniche di fingerprinting più efficaci e storicamente sfruttate contro le installazioni WordPress è l’abuso della funzionalità Pingback tramite l’endpoint XML-RPC.
La funzione Pingback è un meccanismo intrinseco del protocollo XML-RPC di WordPress, progettato per notificare un blog quando un altro blog linka il suo contenuto. Quando un sistema Pingback viene invocato, il server target (il nostro server d’origine protetto da Cloudflare) esegue una richiesta HTTP in uscita verso l’URL specificato nel payload della richiesta XML-RPC.
Il vettore di attacco sfrutta il fatto che, in una configurazione standard, le richieste Pingback in uscita vengono risolte ed eseguite direttamente dall’indirizzo IP del server d’origine, ignorando completamente il proxy e i range IP della CDN.
L’attaccante esegue i seguenti passi per la Rivelazione dell’IP:
/xmlrpc.php.pingback.ping e indirizza il server d’origine a connettersi a un server Listener controllato dall’attaccante (l’indirizzo è iniettato nel parametro targetUri).Il payload per l’attacco è strutturato come segue (dove listener-attacker.com è il server controllato):

L’immagine è volutamente stata creata con una IA
La vulnerabilità Pingback non è limitata alla sola rivelazione dell’IP. La sua natura, che permette l’inizializzazione di connessioni HTTP arbitrarie da parte del server target, la rende un vettore ideale per attacchi di SSRF e DDoS per Amplificazione.
Poiché il Pingback abilita il server d’origine a connettersi a qualsiasi URI specificato dall’attaccante, anche URI interni o locali, la funzionalità si trasforma in un vettore SSRF. Un attaccante può tentare di indirizzare il server a porte e servizi accessibili solo dalla rete interna o dalla loopback interface (e.g., 127.0.0.1 o localhost).
Questo consente l’enumerazione di servizi interni (come metadati cloud, API locali di gestione, o pannelli di amministrazione non esposti pubblicamente) e, in combinazione con servizi vulnerabili, può portare a esfiltrazione di dati, attacchi port scanning interni o esecuzione di comandi remoti. La capacità di manipolare il targetUri per puntare a risorse non-pubbliche è la chiave per trasformare il Pingback in un problema di sicurezza interna.
Un’ulteriore e più diffusa conseguenza è l’utilizzo del meccanismo XML-RPC Pingback per attacchi di Denial of Service (DDoS) distribuiti e riflessi. Un attaccante può creare un botnet di server WordPress vulnerabili. Inviando migliaia di richieste Pingback simultanee, tutte indirizzate (tramite il targetUri) alla vittima finale, ogni server WordPress sfrutta la sua larghezza di banda per inviare una richiesta HTTP in uscita, amplificando il traffico DDoS e mascherando la fonte reale dell’attacco.
Per dimostrare l’efficacia di questa tecnica, un professionista può eseguire un test attivo (PoC) che richiede un server Listener controllato esternamente e l’utilizzo di strumenti HTTP standard.
listener-test.com) in grado di registrare l’indirizzo IP d’origine di qualsiasi connessione TCP/HTTP in entrata. Strumenti semplici come netcat o uno script Python in ascolto su una porta specifica sono sufficienti.curl: inviare la richiesta XML-RPC manipolata al server WordPress protetto, utilizzando il FQDN del Listener come destinazione del Pingback.# Eseguito da una workstation di testing
ATTACKER_URI="http://listener-test.com:8080/test-pingback"
TARGET_URI="https://sito-protetto.com/post-arbitrario"
PAYLOAD='<?xml version="1.0" encoding="iso-8859-1"?>
<methodCall>
<methodName>pingback.ping</methodName> </methodCall>'
curl -X POST -H 'Content-Type: text/xml' \ --data "$PAYLOAD" \ https://sito-protetto.com/xmlrpc.php
Analisi dei Risultati: Se il log del Listener mostra un accesso HTTP proveniente da un IP non appartenente ai range Cloudflare, la vulnerabilità di IP-leakage è confermata.
La mitigazione più robusta per questi exploit consiste nel blocco completo dell’accesso all’endpoint /xmlrpc.php.
Questo può essere realizzato tramite:
iptables): utilizzare il meccanismo descritto nello script precedente per permettere il traffico in ingresso solo dai range IP ufficiali di Cloudflare per le porte 80 e 443. Questo assicura che qualsiasi richiesta a /xmlrpc.php non proveniente dal CDN venga bloccata a livello di rete.EOF