I commenti spam non sono un fastidio estetico: sono un vettore di link tossici verso il tuo sito, un consumo improduttivo di risorse server e una fonte continua di falsi negativi che Akismet, da solo, non riesce più a contenere. La strategia che funziona nel 2026 non è un singolo plugin, ma una difesa stratificata che intercetta i bot prima che raggiungano WordPress.
Questa guida implementa un approccio defense in depth articolato su tre layer: applicativo (WordPress + plugin), edge (CDN/WAF) e server (web server e firewall). Ogni layer filtra una porzione del traffico ostile e riduce il carico su quelli sottostanti. Tutti gli snippet che seguono sono testati e pronti da incollare; le configurazioni sono adatte sia ad Apache che a Nginx.

Perché ricevi commenti spam su WordPress
WordPress alimenta oltre il 40% del web e questa posizione dominante lo rende il bersaglio numero uno dei tool di spam automatizzato. Capire come funzionano questi attacchi è il prerequisito per costruire contromisure efficaci.
Anatomia di un attacco spam ai commenti
I bot spammer non commentano leggendo l’articolo. Eseguono richieste HTTP POST dirette verso l’endpoint /wp-comments-post.php, l’unico punto di ingresso per i commenti nei temi WordPress standard. Le tipologie principali che incontrerai nei log di un sito attivo sono tre.
- Bot “dumb”: software come Scrapebox, GSA Search Engine Ranker, XRumer. POSTano direttamente sull’endpoint dei commenti senza visitare la pagina, senza eseguire JavaScript, spesso con User-Agent vuoto o falsificato in modo grossolano. Rappresentano il 70-80% del volume in un blog medio.
- Bot con browser headless: utilizzano Puppeteer o Playwright per simulare un utente reale, eseguono il JavaScript della pagina, gestiscono i cookie. Più costosi da realizzare ma in crescita: superano gli honeypot semplici e alcuni CAPTCHA legacy.
- Spam umano outsource: operatori reali in farm a basso costo che compilano manualmente i form. Volume basso ma capacità di bypassare qualsiasi challenge automatica. La difesa qui è di natura editoriale (moderazione, blacklist semantica).

Impatto reale: SEO, performance, moderazione, security
Sottovalutare lo spam significa accettare quattro problemi concreti.
- SEO: i commenti spam approvati per errore inseriscono link in uscita verso domini di pessima reputazione. Anche con
rel="ugc nofollow"applicato automaticamente da WordPress, una concentrazione anomala di link outbound verso casinò, farmaci o servizi finanziari grigi può attivare segnali di rischio sul tuo profilo. Trattare correttamente i link nei commenti è un argomento che affronto nell’articolo sull’attributo rel ugc e sponsored. - Performance: ogni POST verso
wp-comments-post.phpesegue il bootstrap completo di WordPress (caricamentowp-load.php, init plugin, query a DB). Un sito che riceve 10.000 tentativi di spam al giorno spreca decine di minuti CPU/giorno solo per accogliere richieste che finiranno scartate. - Moderazione: ogni falso positivo che entra in coda richiede del tuo tempo per essere classificato. Un blog medio ben difeso dovrebbe vedere meno di 5 commenti spam settimanali in moderazione.
- Security: gli stessi tool che spammano commenti sondano anche endpoint deboli (
xmlrpc.php, REST API non protetta, file di backup esposti). Il commento spam è spesso il sintomo visibile di un’attività di scansione più ampia.
Perché un solo layer di difesa non basta
Affidarsi al solo Akismet è la configurazione più diffusa e anche la più fragile. Akismet è un servizio in cloud che riceve i commenti già dentro WordPress, dopo che il POST è stato accettato e processato: ottimo come classificatore semantico, inutile come barriera. Il principio defense in depth è esattamente l’opposto: filtrare presto e a basso costo, riservare i filtri costosi (e fallibili) all’ultimo miglio.
L’analogia che uso quando spiego questo concetto in audit è quella della cipolla: ogni strato che attraversi senza essere fermato è un fallimento del livello precedente. In un setup ben architettato, oltre il 90% dei tentativi di spam viene scartato a livello edge, prima di toccare il PHP del tuo server. Akismet diventa l’ultimo filtro, non il primo.
Layer 1 — Application: blindare WordPress dall’interno
Il primo passo è ridurre la superficie d’attacco e configurare correttamente le difese native che WordPress già offre. Sono interventi gratuiti, reversibili e a impatto immediato.
Configurazione nativa: Discussione settings
Da Impostazioni → Discussione nel backend WordPress hai a disposizione un set di leve spesso ignorate. Le configurazioni che applico di default in ogni progetto sono quattro.
- Moderazione preventiva: attiva “Il commento deve essere approvato manualmente”. Sì, aumenta il lavoro di moderazione, ma azzera il rischio che uno spam finisca pubblicato.
- Holding per autori non riconosciuti: in alternativa, attiva “L’autore del commento deve aver già un commento approvato”. Approvi una volta l’autore legittimo, da quel momento in poi i suoi commenti passano senza moderazione.
- Soglia link: imposta il numero massimo di link prima della moderazione a 1 (default WordPress è 2). I commenti spam contengono quasi sempre più di un link.
- Chiusura automatica: chiudi i commenti su articoli più vecchi di 60-90 giorni. Gli articoli vecchi raccolgono solo spam (l’analisi dei log lo conferma in modo schiacciante), mentre la discussione legittima si concentra nelle prime settimane dalla pubblicazione.
Ridurre la superficie d’attacco
Ogni campo del form e ogni endpoint pubblico è una porta che un bot può attraversare. Eliminare ciò che non usi è la prima ottimizzazione di sicurezza.
- Campo URL nel form commenti: è l’esca principale per i bot di link building. Rimuoverlo riduce drasticamente l’incentivo dei bot a colpire il tuo form. La procedura completa è in come rimuovere il campo URL dai commenti WordPress.
- HTML e link automatici nel testo: WordPress di default converte URL in tag
<a>e accetta una whitelist di tag HTML. Disabilitare entrambi rende i commenti meno appetibili per lo spammer e meno pericolosi quando uno passa la moderazione. La guida è disabilitare tag HTML e link automatici nei commenti. - Pingback e trackback: erano utili nel 2008, oggi sono solo un altro vettore di spam. Disattivali da Impostazioni → Discussione (uncheck “Permetti notifiche di link da altri blog”) e considera di disabilitarli anche a livello server (vedi sezione XML-RPC).
Plugin antispam: Akismet, Antispam Bee, CleanTalk
Anche con i layer edge e server attivi, un plugin antispam come ultima rete di sicurezza ha senso. Sono tre le opzioni serie sul mercato; ognuna ha un modello di funzionamento diverso e un trade-off specifico.
| Plugin | Modello | Privacy | Costo | Quando sceglierlo |
|---|---|---|---|---|
| Akismet | Classificazione cloud Automattic | Invia commento, IP e User-Agent ai server Akismet | Gratuito uso personale, a pagamento per siti commerciali | Blog medio-grandi, vuoi delegare la decisione a un classificatore maturo |
| Antispam Bee | Filtri locali (no cloud) | 100% on-premise, GDPR-friendly | Gratuito | Siti soggetti a GDPR rigoroso, blog europei che non vogliono trasferire dati extra-UE |
| CleanTalk | Classificazione cloud + blacklist IP | Invia dati ai server CleanTalk | Subscription annuale low-cost | Hai bisogno di proteggere anche form di registrazione, contatto e checkout oltre ai commenti |
Nei progetti che gestisco da consulente, la combinazione che vedo funzionare meglio è Antispam Bee + Cloudflare Turnstile per i blog europei (zero invio dati a terzi, gratuito, efficace) oppure Akismet + Cloudflare Bot Fight Mode per blog grandi non vincolati da policy privacy stringenti.
Honeypot fatto in casa (snippet PHP)
Un honeypot è un campo nascosto al CSS che gli utenti reali non compilano mai, ma che la maggior parte dei bot riempie automaticamente. È la tecnica più semplice, economica e sorprendentemente efficace contro i bot “dumb”. Aggiungi il seguente codice nel file functions.php del tuo tema child (mai nel tema principale).
<?php
/**
* Honeypot per commenti WordPress
* Aggiunge un campo nascosto al form; se viene compilato, il commento è spam.
*/
// 1. Inserisci il campo honeypot nel form commenti
add_action( 'comment_form_after_fields', function() {
echo '<p style="position:absolute;left:-9999px;" aria-hidden="true">
<label for="website_url">Website URL (non compilare)</label>
<input type="text" name="website_url" id="website_url" tabindex="-1" autocomplete="off" />
</p>';
}, 5 );
// 2. Intercetta i commenti prima del salvataggio
add_filter( 'preprocess_comment', function( $commentdata ) {
if ( ! empty( $_POST['website_url'] ) ) {
// Honeypot compilato: blocca con 403
wp_die(
'Spam rilevato.',
'Commento bloccato',
array( 'response' => 403 )
);
}
return $commentdata;
} );
Tre dettagli implementativi non banali. Primo, il nome del campo (website_url) deve sembrare plausibile: i bot moderni evitano i campi chiamati esplicitamente honeypot o do_not_fill. Secondo, nascondi il campo con CSS inline (position:absolute;left:-9999px), non con display:none: alcuni bot ignorano i campi con display:none proprio perché è un pattern noto di honeypot. Terzo, l’attributo tabindex="-1" impedisce che un utente che naviga con la tastiera finisca per sbaglio sul campo.
Disabilitare REST API dei commenti e XML-RPC
Il form HTML non è l’unico modo per inviare un commento. WordPress espone due API alternative che i bot moderni sfruttano sistematicamente: wp-json/wp/v2/comments (REST API) e xmlrpc.php. Se non hai integrazioni che le richiedono, disabilitarle è un guadagno netto.
<?php
/**
* Blocco endpoint REST commenti e XML-RPC
* Inserire in functions.php del tema child
*/
// Blocca POST sull'endpoint REST dei commenti per utenti non autenticati
add_filter( 'rest_pre_dispatch', function( $result, $server, $request ) {
if ( $request->get_method() === 'POST'
&& strpos( $request->get_route(), '/wp/v2/comments' ) === 0
&& ! is_user_logged_in() ) {
return new WP_Error(
'rest_forbidden',
'Endpoint disabilitato.',
array( 'status' => 403 )
);
}
return $result;
}, 10, 3 );
// Disabilita completamente XML-RPC
add_filter( 'xmlrpc_enabled', '__return_false' );
// Rimuovi header HTTP che annuncia XML-RPC
add_filter( 'wp_headers', function( $headers ) {
unset( $headers['X-Pingback'] );
return $headers;
} );
// Rimuovi pingback dal link discovery
remove_action( 'wp_head', 'rsd_link' );
remove_action( 'wp_head', 'wlwmanifest_link' );
Attenzione: se usi l’app mobile WordPress o servizi tipo Jetpack che si appoggiano a XML-RPC, dovrai mantenerlo abilitato e proteggerlo a livello edge (vedi Layer 2). La REST API serve a moltissime cose oltre ai commenti; il filtro sopra blocca solo l’endpoint specifico, non l’intera API.
Layer 2 — Edge: fermare lo spam prima che tocchi WordPress
Il modo più economico per bloccare un bot è non lasciarlo arrivare al tuo server. Una CDN con capacità WAF (Web Application Firewall) intercetta le richieste sul proprio edge e scarta quelle ostili senza che il tuo PHP venga mai eseguito. Cloudflare è la scelta di riferimento per costo (free plan generoso), copertura geografica e qualità delle regole.
Se non hai ancora Cloudflare attivo, parti dalla guida come installare Cloudflare in 5 minuti. Il resto di questa sezione assume che il tuo sito stia proxytizzando il traffico attraverso Cloudflare (nuvoletta arancione attiva).
Bot Fight Mode e Super Bot Fight Mode
Cloudflare include un modulo di bot mitigation con due livelli. Bot Fight Mode è gratuito su tutti i piani e blocca automaticamente i bot identificati con alta confidenza dal classificatore Cloudflare. Super Bot Fight Mode (Pro plan e superiori) aggiunge granularità: puoi distinguere bot “verificati” (Googlebot, Bingbot), bot “likely automated” e bot “definitely automated”, applicando azioni diverse a ciascuna categoria.
Configurazione consigliata per un blog: Definitely Automated → Block, Likely Automated → Managed Challenge, Verified Bots → Allow. Attivi tutto da Security → Bots nella dashboard del dominio.
Custom Rules su /wp-comments-post.php
Le Custom Rules ti permettono di scrivere regole arbitrarie basate su qualunque attributo della richiesta. La regola di base che applico in ogni progetto WordPress blocca POST verso wp-comments-post.php con caratteristiche sospette.
Vai in Security → WAF → Custom rules e crea una nuova regola con questa expression:
(http.request.uri.path eq "/wp-comments-post.php" and http.request.method eq "POST") and (
http.user_agent eq ""
or http.referer eq ""
or not http.referer contains "tuodominio.com"
or ip.geoip.country in {"RU" "CN" "VN" "IN"}
)
Action: Block (o Managed Challenge se temi falsi positivi). Sostituisci tuodominio.com con il tuo dominio reale e adatta la lista paesi alle tue esigenze: la lista mostrata non è uno stigma sui paesi ma una semplificazione operativa basata sul fatto che, in un blog italofono che riceve solo lettori italiani, traffico POST da quei paesi è quasi certamente automatizzato. Verifica nei log Cloudflare quali paesi generano effettivamente spam sul tuo sito prima di blocchi geografici.
Rate Limiting Rules
Un utente legittimo lascia un commento ogni tanto. Un bot lascia 50 commenti in 60 secondi. Il rate limiting sfrutta questa asimmetria per bloccare gli abusi senza falsi positivi.
In Cloudflare vai in Security → WAF → Rate limiting rules. Configurazione consigliata:
- Match:
http.request.uri.path eq "/wp-comments-post.php" and http.request.method eq "POST" - Caratteristiche per definire un cliente: IP address
- Soglia: 5 richieste in 60 secondi (alza/abbassa in base al volume di commenti legittimi del tuo blog)
- Azione quando superata: Block per 1 ora
Il free plan di Cloudflare include un rate limiting rule gratuito; piani superiori ne abilitano molti di più. Per un blog questo single slot è quasi sempre sufficiente.
Cloudflare Turnstile come challenge invisibile
Turnstile è la risposta di Cloudflare a reCAPTCHA: una challenge che nella maggior parte dei casi è completamente invisibile all’utente (il widget verifica passivamente fingerprint del browser, telemetria comportamentale, reputazione IP) ma che impedisce il bypass automatizzato. È gratuito, privacy-friendly e funziona anche con Cloudflare non attivo come proxy.
La procedura ha due step: aggiungere il widget al form commenti e validare la risposta server-side prima di salvare il commento.
<?php
/**
* Integrazione Cloudflare Turnstile per WordPress
* Inserire in functions.php del tema child
*/
define( 'TURNSTILE_SITE_KEY', 'INSERISCI_LA_TUA_SITE_KEY' );
define( 'TURNSTILE_SECRET_KEY', 'INSERISCI_LA_TUA_SECRET_KEY' );
// 1. Carica lo script Turnstile sulle pagine con commenti
add_action( 'wp_enqueue_scripts', function() {
if ( is_singular() && comments_open() ) {
wp_enqueue_script(
'cf-turnstile',
'https://challenges.cloudflare.com/turnstile/v0/api.js',
array(),
null,
true
);
}
} );
// 2. Inserisci il widget nel form
add_action( 'comment_form_after_fields', function() {
echo '<div class="cf-turnstile" data-sitekey="' . esc_attr( TURNSTILE_SITE_KEY ) . '"></div>';
} );
// 3. Valida la risposta server-side
add_filter( 'preprocess_comment', function( $commentdata ) {
$token = $_POST['cf-turnstile-response'] ?? '';
if ( empty( $token ) ) {
wp_die( 'Verifica anti-bot mancante.', 'Commento bloccato', array( 'response' => 403 ) );
}
$response = wp_remote_post(
'https://challenges.cloudflare.com/turnstile/v0/siteverify',
array(
'body' => array(
'secret' => TURNSTILE_SECRET_KEY,
'response' => $token,
'remoteip' => $_SERVER['REMOTE_ADDR'] ?? '',
),
'timeout' => 5,
)
);
if ( is_wp_error( $response ) ) {
// In caso di errore di rete, fail-open o fail-closed in base alla tua policy
return $commentdata;
}
$body = json_decode( wp_remote_retrieve_body( $response ), true );
if ( empty( $body['success'] ) ) {
wp_die( 'Verifica anti-bot fallita.', 'Commento bloccato', array( 'response' => 403 ) );
}
return $commentdata;
} );
Crea Site Key e Secret Key da dash.cloudflare.com → Turnstile. La policy fail-open nel codice (in caso di errore di rete il commento passa) è quella di default in produzione: meglio un raro commento spam che bloccare commenti legittimi quando l’API di Cloudflare è momentaneamente lenta. Se gestisci un sito ad alta sensibilità, sostituisci il return $commentdata dopo is_wp_error con un wp_die.
Blocco per ASN e reputation IP
Una porzione significativa dello spam comment proviene da ASN noti per ospitare botnet o servizi di proxy abusati (DigitalOcean droplet bruciati, OVH residenziali, hosting “bulletproof” dell’est europeo). Cloudflare permette di filtrare per ip.geoip.asnum, e le liste pubbliche di ASN spammosi (Spamhaus DROP, Stop Forum Spam) sono aggiornate frequentemente.
Una regola pragmatica che funziona bene in molti contesti consiste nel forzare un Managed Challenge su tutto il traffico POST che proviene da ASN classificati come “hosting” (cioè data center) anziché “ISP” (cioè connessioni residenziali). Gli utenti reali commentano da casa o dall’ufficio, non da un VPS. Cloudflare espone questa distinzione tramite la enterprise feature IP Lists, ma anche le custom rule sui singoli ASN più abusati (AS14061 DigitalOcean, AS16276 OVH, AS24940 Hetzner, AS200373 Aeza) coprono la quasi totalità dei casi di un blog medio.
Layer 3 — Server: barriere a livello di web server
Il layer server è l’ultima linea prima di WordPress. Anche se a questo punto la quasi totalità dello spam è stata filtrata, le difese a livello di web server hanno tre vantaggi: sono sempre attive (anche se Cloudflare viene bypassato puntando l’IP origin), sono economiche in termini di risorse (l’evaluation è in C, non in PHP) e proteggono anche dagli attacchi che arrivano direttamente all’origin (es. scanner che ti hanno trovato via certificate transparency).
Regola .htaccess modernizzata (referrer + User-Agent vuoto)
La regola classica del 2013 controllava solo il referrer. Funzionava all’epoca; oggi i bot più scadenti la bypassano semplicemente impostando un referrer falso. La versione moderna combina tre controlli: metodo POST, referrer non vuoto e proveniente dal tuo dominio, User-Agent non vuoto. Inseriscila in cima al tuo .htaccess, prima delle regole standard di WordPress.
# Blocca POST su wp-comments-post.php senza referrer valido o senza User-Agent
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_METHOD} =POST
RewriteCond %{REQUEST_URI} ^/wp-comments-post\.php$
RewriteCond %{HTTP_REFERER} !^https?://(www\.)?tuodominio\.com [NC]
RewriteRule .* - [F,L]
RewriteCond %{REQUEST_METHOD} =POST
RewriteCond %{REQUEST_URI} ^/wp-comments-post\.php$
RewriteCond %{HTTP_USER_AGENT} ^$
RewriteRule .* - [F,L]
</IfModule>
Sostituisci tuodominio.com con il tuo dominio. La flag [F,L] restituisce un 403 Forbidden e ferma la valutazione delle regole successive. Questa regola da sola filtra l’80-90% dei bot “dumb” senza alcun overhead percepibile: ogni richiesta viene valutata in pochi microsecondi prima che Apache invochi PHP.
Equivalente Nginx
Nginx non legge .htaccess (per scelta architetturale: ogni request che dovesse rileggerlo sarebbe un I/O sprecato). Le regole vanno scritte nel file di configurazione del server e ricaricate con nginx -s reload. La traduzione dello snippet precedente è la seguente, da inserire dentro il blocco server { ... } del tuo sito.
# Blocca POST su wp-comments-post.php senza referrer valido o senza User-Agent
location = /wp-comments-post.php {
if ($request_method = POST) {
set $block_spam "";
if ($http_referer !~* "^https?://(www\.)?tuodominio\.com") {
set $block_spam "${block_spam}R";
}
if ($http_user_agent = "") {
set $block_spam "${block_spam}U";
}
if ($block_spam != "") {
return 403;
}
}
# Passa a PHP-FPM se non bloccato
include fastcgi_params;
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
La concatenazione su $block_spam è una tecnica idiomatica per combinare più condizioni dentro Nginx, che non supporta l’AND logico nelle direttive if. Adatta il path di PHP-FPM (php8.2-fpm.sock) alla tua installazione.
Rate limit nativo del web server
Se non usi Cloudflare o vuoi una difesa ridondante all’origin, sia Apache che Nginx supportano rate limiting nativo. Su Nginx la sintassi è particolarmente compatta.
# In nginx.conf (contesto http {}):
limit_req_zone $binary_remote_addr zone=comments_limit:10m rate=5r/m;
# Nel server block del sito, dentro location = /wp-comments-post.php:
location = /wp-comments-post.php {
limit_req zone=comments_limit burst=3 nodelay;
# ... resto della configurazione
}
La direttiva rate=5r/m consente 5 richieste al minuto per IP; burst=3 ammette un burst di 3 richieste extra accodate; nodelay serve le richieste in burst immediatamente, non in coda. Oltre la soglia Nginx restituisce 503 Service Unavailable. La zona di memoria 10m tiene traccia di circa 160.000 IP unici.
fail2ban: ban automatico per POST abusivi
Le regole del web server bloccano la singola richiesta; fail2ban va un passo oltre e banna l’IP a livello di firewall (iptables/nftables) dopo N tentativi abusivi in una finestra temporale. Un IP bannato non riesce nemmeno a stabilire la connessione TCP: zero costo CPU per il tuo server, zero possibilità di bypass.
Servono due file: un filter che descrive come riconoscere il pattern abusivo nei log, e una jail che lega il filter al log file e definisce ban time e soglie.
# /etc/fail2ban/filter.d/wordpress-comments.conf
[Definition]
failregex = ^<HOST> .* "POST /wp-comments-post\.php HTTP/.*" (403|404|429) .*$
ignoreregex =
# /etc/fail2ban/jail.d/wordpress-comments.conf
[wordpress-comments]
enabled = true
filter = wordpress-comments
logpath = /var/log/nginx/access.log
/var/log/apache2/access.log
maxretry = 5
findtime = 600
bantime = 86400
action = iptables-multiport[name=wp-comments, port="http,https"]
La regex matcha le righe di access log dove un client ha ricevuto 403, 404 o 429 su wp-comments-post.php: vuol dire che è già stato bloccato dalle regole precedenti del web server. Cinque tentativi falliti in 10 minuti (maxretry=5, findtime=600) producono un ban di 24 ore (bantime=86400). Ricarica con fail2ban-client reload e verifica con fail2ban-client status wordpress-comments.
ModSecurity e OWASP CRS: quando ha senso
ModSecurity è un WAF open source che si integra in Apache, Nginx e IIS, ed è tipicamente accoppiato all’OWASP Core Rule Set per intercettare pattern di attacco noti (SQLi, XSS, RCE, ma anche spam comment con regole anti-spambot). È un’arma potente con un trade-off importante: i falsi positivi non sono rari e la configurazione richiede tuning attivo.
Senso pratico: ModSecurity vale lo sforzo se hosti più siti su un singolo VPS senza Cloudflare. In quel caso fornisce una baseline di sicurezza paragonabile a un WAF in cloud. Se il tuo unico sito è già dietro Cloudflare, la sovrapposizione di funzionalità è notevole e l’overhead manutentivo raramente è giustificato. Approfondisco il tema in modo più ampio nella mia guida alla sicurezza di WordPress.
Strategia per dimensione del blog
Implementare tutti i layer ha senso per un blog enterprise; per un blog personale è overkill. La matrice qui sotto sintetizza il setup raccomandato in funzione del volume di traffico e della severità del problema spam.
| Profilo | Layer 1 (App) | Layer 2 (Edge) | Layer 3 (Server) | Effort iniziale |
|---|---|---|---|---|
| Blog piccolo (<5k visite/mese) | Akismet o Antispam Bee + moderazione preventiva + chiusura commenti dopo 60gg | Cloudflare free + Bot Fight Mode | — | 30 minuti |
| Blog medio (5k-50k visite/mese) | Antispam Bee + honeypot + disabilitazione REST/XML-RPC + rimozione campo URL | Cloudflare + Bot Fight Mode + Custom Rule su wp-comments-post.php + Rate limiting | Regola .htaccess/Nginx modernizzata | 2-3 ore |
| Blog grande (>50k visite/mese) | Tutte le difese del blog medio + Turnstile + plugin antispam (Akismet o CleanTalk) | Cloudflare Pro + Super Bot Fight Mode + Custom Rules su ASN abusati + Rate limiting aggressivo | .htaccess/Nginx + rate limit nativo + fail2ban | 1 giornata |
Le righe non sono cumulative: ognuna rappresenta un setup completo coerente con il profilo. Salire di profilo significa aggiungere difese, mai sostituirle.
Monitoraggio e tuning continuo
Una difesa antispam non è “fire and forget”. I bot evolvono, le tue regole invecchiano, e senza misurazioni è impossibile sapere se il setup sta funzionando o se stai bloccando commenti legittimi.
Misurare l’efficacia: KPI e log analysis
I tre KPI che monitoro in ogni progetto antispam sono i seguenti.
- Commenti spam in moderazione / settimana: il target operativo è meno di 5. Sopra i 20 alla settimana, qualcosa non funziona nel tuo setup.
- Rapporto blocchi edge / blocchi application: vuoi che la stragrande maggioranza dei bot venga fermata da Cloudflare (numerose blocchi nel dashboard Cloudflare) e una minoranza da Akismet o dai filtri PHP. Se Akismet processa più commenti spam di quelli che Cloudflare blocca, il layer edge è configurato male.
- Falsi positivi segnalati: utenti che ti scrivono dicendo “ho provato a commentare ma il sito mi ha respinto”. Tieni traccia: oltre 1 falso positivo segnalato al mese significa che le regole sono troppo aggressive.
Per l’analisi dei log access, una one-liner utile su un server Nginx è la seguente:
# Top 20 IP che hanno tentato POST su wp-comments-post.php nelle ultime 24h
awk -v d="$(date -d '24 hours ago' '+%d/%b/%Y:%H')" \
'$4 > "["d && $6 ~ /POST/ && $7 ~ /wp-comments-post/ {print $1}' \
/var/log/nginx/access.log | sort | uniq -c | sort -rn | head -20
Il risultato è una classifica dei top abuser delle ultime 24 ore: utile per identificare pattern (un singolo IP con migliaia di tentativi, oppure migliaia di IP con un tentativo a testa — botnet distribuita).
Gestire i falsi positivi
Il falso positivo più comune è un utente reale dietro una VPN o un network aziendale con reputazione IP compromessa. Il sintomo è una segnalazione via email o sui social (“ho provato a commentare e mi dà 403”). La diagnosi è veloce.
- Chiedi all’utente l’IP da cui ha provato (oppure deducilo dall’orario del tentativo nei log).
- Cerca quell’IP nei log del web server e nel dashboard Cloudflare (sezione Security Events).
- Identifica quale layer ha generato il blocco (il messaggio di errore restituito è diverso: Cloudflare mostra il proprio errore branded; .htaccess restituisce un 403 generico Apache; il filtro PHP restituisce
wp_diecon il testo che hai impostato). - Decidi se whitelistare l’IP, allargare la regola che ha causato il falso positivo, o entrambi.
Una revisione trimestrale delle regole è sufficiente per la maggior parte dei blog. Programmala in agenda come si fa con qualsiasi altra manutenzione tecnica.
Troubleshooting: errori comuni
Akismet blocca commenti legittimi
Capita soprattutto su commenti tecnici contenenti più URL (snippet con link a documentazione, riferimenti incrociati). Vai in Commenti → Spam, recupera il commento, clicca “Non spam”. Akismet impara dai tuoi feedback: ogni commento marcato come “non spam” allena il classificatore per il tuo specifico contesto. Dopo 4-6 settimane di training attivo i falsi positivi calano in modo netto.
Plugin antispam in conflitto con il caching
WP Rocket, W3 Total Cache, LiteSpeed Cache e altri plugin di cache servono pagine statiche pre-renderizzate. Se il tuo honeypot o il widget Turnstile inseriscono un token CSRF/nonce nel form (cosa che fanno per definizione), questo token resta congelato nella cache HTML e fallirà la validazione server-side. Soluzioni in ordine di preferenza:
- Genera il token via JavaScript al rendering della pagina (non come PHP server-side). Turnstile fa già questo nativamente; per honeypot custom, valuta una refresh AJAX del token.
- Escludi le pagine con commenti aperti dalla cache (configurabile in tutti i plugin di caching). Costo: hit ratio della cache più basso sulle pagine articolo.
- Usa “edge caching” Cloudflare con bypass su query parameter: la pagina è cached ma il form è dinamico via fragment caching.
fail2ban banna IP legittimi
Il caso classico: un utente legittimo dietro un NAT carrier-grade (rete mobile, Wi-Fi pubblico) viene bannato perché qualcun altro dietro lo stesso IP ha tentato spam. La soluzione non è disabilitare fail2ban ma alzare la soglia: maxretry=10 e findtime=300 rendono il ban più tollerante. In alternativa, sbianca via fail2ban-client set wordpress-comments unbanip <IP> on demand quando ti segnalano il problema, e considera di aggiungere gli IP “amici” alla ignoreip nel file /etc/fail2ban/jail.local.
Conclusioni
Bloccare i commenti spam su WordPress nel 2026 è un problema risolto, ma non da un solo strumento. La strategia che produce risultati misurabili è la difesa a strati: Cloudflare e regole edge filtrano il grosso del traffico ostile, il web server intercetta ciò che bypassa l’edge, WordPress fa da ultima rete con Akismet (o equivalente) e honeypot. Ogni layer costa poco e blocca una porzione diversa dell’attacco; insieme abbattono lo spam praticamente a zero.
Il punto chiave è l’ordine: la regola da mille euro è “blocca presto, blocca a basso costo”. Akismet è uno strumento eccellente come ultimo filtro, ma usarlo come unico filtro è la ragione per cui la maggior parte dei blog WordPress si lamenta del problema spam. Sposta la difesa all’edge, libera il tuo PHP, e Akismet ringrazia.
Se vuoi un approccio più ampio alla sicurezza WordPress (utenti, file, database, sessioni), la mia guida alla protezione totale di WordPress tratta il tema in modo organico. Per chi non ha ancora Cloudflare attivo, la guida pratica è installare Cloudflare in 5 minuti.
Articoli correlati
Autore
Mi chiamo Giovanni Sacheli e dal 2009 aiuto le aziende a farsi trovare online. Sono specializzato in SEO tecnica e PPC, competenze che applico quotidianamente nella mia agenzia, Searcus Swiss Sagl. Mi piace sviluppare strumenti a supporto del mio lavoro, ho creato SEOdata.app e cluster.army e co-scritto il libro SEO Audit Avanzato. Curo maniacalmente questo blog per colleghi e appassionati, dove mi "appunto" quello che imparo. Sono un NERD anni '80, motociclista e orgoglioso papà di due bambini.
Link:
Giovanni Sacheli
SEO Audit Avanzato
Searcus Swiss Sagl
SEOdata.app
cluster.army
Commenti |3
Lascia un commentoCiao. Ho provato a modificare il file .htaccess con le stringhe che hai postato sopra, sostituendo “evemilano.com” con l’indirizzo del mio blog, ma dopo l’aggiornamento del file sull’ftp, mi viene dato errore 404 ogni volta che apro gli articoli del mio blog. dove sbaglio? il mio file htaccess contiene questo
ErrorDocument 404 …nomesito.net/404.php
# BEGIN WordPress
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ – [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
# END WordPress
Ciao Ugo, se il tuo sito non usa plugin di cache ti consiglio di inserire le stringhe così come le ho scritte (cambiando il dominio ovviamente). Il tuo HTACCESS è diverso
ciao e complimenti per l’ articolo.
io per fermare l’invio di commenti spam, ho integrato il modulo di commenti di facebook.
questa cosa che ho fatto, mi ha oltre che limitato i commenti spam, aiutato ad interagire di più con gli utenti del social network.
se vuoi ti scrivo qui come ho fatto ( l’ ho trovato in rete)
sono andato a creare un applicazione facebook qui developers.facebook.com/apps
poi per creare la applicazione basta, una volta iscritti, cliccare sul pulsante “crea applicazione”, inserire un nome (ad esempio “commenti per evemilano.com”), e creare l’applicazione. In questo modo si otterrà un numero ID. Ora bisogna inserire questo numero nell’header.php, prima del e all’interno dell’ , in una stringa come la seguente, nella quale si dovrà sostituire “numero-app” con il numero ID fornito in precedenza da Facebook.
Successivamente, bisognerà modificare la pagina comments.php (sempre nell’editor). Ogni template WordPress ha le sue configurazioni ed il suo codice, ma modificare comments.php non dovrebbe essere difficile. Bisognerà aggiungere dunque nel proprio comments.php la seguente stringa di codice, facendo attenzione che venga inserita insieme (prima o dopo) altre stringhe che iniziano con <php if ( comments_open). La stringa infatti ha un inizio ed una fine a sé, ma va inserita all’interno del codice in modo da non modificarne le sue funzionalità.
<fb:comments href=”” width=”600″>
E’ possibile all’interno del codice modificare la lingua (in questo caso /it) e la lunghezza del campo di commento, in modo che si adatti al design del proprio sito (in questo caso width=”600″).
ciao alla prossima