Skip to content
EVE Milano Consulenza SEO

EveMilano Logo White EveMilano Logo White

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.

Architettura a tre layer per filtrare i commenti spam su WordPress: Edge Cloudflare WAF, Server Nginx Apache, Application WordPress
Architettura defense in depth a tre layer: edge, server, application

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).
Anatomia di un attacco spam ai commenti WordPress: bot invia HTTP POST diretto a wp-comments-post.php bypassando la pagina
Anatomia di un attacco spam: il bot bypassa la pagina e POSTa direttamente all’endpoint

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.php esegue il bootstrap completo di WordPress (caricamento wp-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.

  1. Moderazione preventiva: attiva “Il commento deve essere approvato manualmente”. Sì, aumenta il lavoro di moderazione, ma azzera il rischio che uno spam finisca pubblicato.
  2. 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.
  3. 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.
  4. 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.

PluginModelloPrivacyCostoQuando sceglierlo
AkismetClassificazione cloud AutomatticInvia commento, IP e User-Agent ai server AkismetGratuito uso personale, a pagamento per siti commercialiBlog medio-grandi, vuoi delegare la decisione a un classificatore maturo
Antispam BeeFiltri locali (no cloud)100% on-premise, GDPR-friendlyGratuitoSiti soggetti a GDPR rigoroso, blog europei che non vogliono trasferire dati extra-UE
CleanTalkClassificazione cloud + blacklist IPInvia dati ai server CleanTalkSubscription annuale low-costHai 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.

ProfiloLayer 1 (App)Layer 2 (Edge)Layer 3 (Server)Effort iniziale
Blog piccolo (<5k visite/mese)Akismet o Antispam Bee + moderazione preventiva + chiusura commenti dopo 60ggCloudflare free + Bot Fight Mode30 minuti
Blog medio (5k-50k visite/mese)Antispam Bee + honeypot + disabilitazione REST/XML-RPC + rimozione campo URLCloudflare + Bot Fight Mode + Custom Rule su wp-comments-post.php + Rate limitingRegola .htaccess/Nginx modernizzata2-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 + fail2ban1 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.

  1. Chiedi all’utente l’IP da cui ha provato (oppure deducilo dall’orario del tentativo nei log).
  2. Cerca quell’IP nei log del web server e nel dashboard Cloudflare (sezione Security Events).
  3. 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_die con il testo che hai impostato).
  4. 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

11 min lettura

I tool automatici degli hosting migrano solo file e database, tralasciando URL mapping e redirect. Procedura tecnica manuale per trasferire un sito WordPress su un altro dominio e server gestendo il database MySQL e preservando il traffico organico post-migrazione.
94 mi piace

Autore

Commenti |3

Lascia un commento Lascia un commento
  1. ugo 1 commento

    Ciao. 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

    1. Giovanni Sacheli 774 risposte

      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

  2. Roberto Varriale 1 commento

    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

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *

Ultimi articoli aggiornati

22 min lettura

Difendere WordPress dai commenti spam con una strategia defense in depth a tre layer: configurazioni applicative, regole edge su Cloudflare, barriere a livello web server. Honeypot PHP, regole .htaccess e Nginx modernizzate, Cloudflare Turnstile, fail2ban. Snippet completi pronti da incollare.
0 mi piace
22 min lettura

Analisi tecnica della persistenza dei dati nel protocollo HTTP tramite header Set-Cookie. Comprendere la meccanica dei cookie, attributi come Max-Age e i limiti di Googlebot come crawler stateless è essenziale per diagnosticare problemi di rendering e involuntary cloaking.
3 mi piace
19 min lettura

Analisi dell'architettura RAG nativa per WordPress sviluppata interamente in PHP e MySQL, senza dipendenze da database vettoriali esterni. Il sistema supera i limiti della ricerca lessicale integrando la ricerca semantica su VPS o hosting condivisi con meno di 1GB di RAM.
2 mi piace
7 min lettura

La gestione dei 404 durante le migrazioni richiede automazione per preservare la link equity. migTool è uno script Python progettato per automatizzare la mappatura dei redirect 301 intelligenti, ottimizzando il processo di reindirizzamento ed eliminando le inefficienze manuali.
5 mi piace

Richiedi un preventivo SEO e Google Ads

Porta il tuo sito web al livello successivo con l’esperienza di EVE Milano. La nostra agenzia di Search Marketing ha ricevuto oltre 1205 richieste di preventivo, un segnale chiaro della fiducia che imprenditori e manager, come te, ripongono nella nostra specializzazione tecnica e verticale nella SEO e PPC. Se la tua organizzazione cerca competenze specifiche per emergere nei risultati di Google, noi siamo pronti a fornire quel valore aggiunto. Richiedi un preventivo ora e scopri la differenza tra noi e gli altri.
Richiedi un preventivo

Vuoi ricevere un avviso al mese con le nuove guide pubblicate?

Iscriviti alla newsletter!