BotDetect v2 — Libreria di Rilevamento Bot per Produzione
Libreria client-side per il rilevamento di bot e automazione con punteggio ponderato, analisi comportamentale, fingerprinting del browser e soglie configurabili. Rileva browser headless, Selenium, Puppeteer, Playwright, strumenti basati su CDP e framework di automazione stealth.
v2.1.0 — honeypot anti-rilevamento, fingerprinting canvas stabile su GPU, analisi comportamentale migliorata, inizializzazione lazy, rilevamento lato server di manomissioni, binding dell'impronta della richiesta e limitazione della frequenza.
Indice
Funzionalità
- 28 moduli di rilevamento che coprono framework di automazione, browser headless, fingerprinting, analisi comportamentale, honeypot e trappole per stack trace
- Sistema di punteggio ponderato — ogni segnale ha un peso configurabile; il punteggio finale viene calcolato lato server
- Tre livelli di verdetto:
human, suspicious, bot con corrispondenti azioni di contrasto (monitor, challenge, block)
- Verifica lato server — protetta da nonce, replay, proof-of-work firmato
- Trappole per stack trace — monkey-patching delle API DOM per catturare gli stack delle chiamate degli strumenti di automazione
- Analisi comportamentale — curvatura del mouse, varianza temporale della digitazione, accelerazione dello scorrimento, dinamiche tattili
- Honeypot anti-rilevamento — mascheramento CSS randomizzato, campi esca, nomi di campo realistici
- Rilevamento lato server di manomissioni — verifica l'integrità dei segnali, rileva tentativi di manipolazione
- Binding dell'impronta della richiesta — token PoW legati agli attributi della richiesta HTTP
- Limitazione della frequenza — limitazione per sessione su tutti gli endpoint di verifica
- Rilevamento no-script — identifica i client che non inviano mai payload di rilevamento
- Whitelist di crawler noti — oltre 20 bot legittimi esclusi dal calcolo del punteggio
Architettura
Browser Il tuo Server
┌──────────────────────────┐ ┌──────────────────────┐
│ Collector (singleton) │ POST │ Express Middleware │
│ ├─ 28 moduli rilevam. │ segnali │ ├─ NonceManager │
│ ├─ BehaviorTracker │ + nonce │ ├─ RateLimiter │
│ ├─ HoneypotTraps │───────────▶│ ├─ TamperDetector │
│ ├─ Trappole stack trace │ │ ├─ computeVerdict() │
│ └─ IframeContext │ │ └─ Proof-of-Work │
│ │ verdetto │ │
│ ↓ collect() → │ + proof │ Restituisce: │
│ DetectionResult[] │◀───────────│ { verdict, score, │
└──────────────────────────┘ │ confidence, proof, │
│ tamperScore } │
└──────────────────────┘
│
▼
Endpoint protetto da sessione
(login, checkout, etc.)
valida il proof prima di
concedere l'accesso
Principio chiave: Il browser raccoglie solo i segnali DetectionResult[] grezzi. Il server calcola il verdetto finale utilizzando una tabella di pesi segreta. I verdetti calcolati dal client non sono mai attendibili.
Avvio Rapido
1. Build
npm install
npm run build
Output in dist/:
botdetect.min.js (con polyfill, ~151 KB)
botdetect-clean.min.js (solo browser moderni, ~74 KB)
2. Includere nella pagina
<script src="/path/to/botdetect.min.js"></script>
<script>
BotDetect.collector.enableTraps();
BotDetect.collector.enableBehavioralTracking();
BotDetect.collector.enableHoneypots();
</script>
3. Configurare la verifica lato server
cd server
npm install express cors express-session
node example-integration.js
4. Inviare i segnali in occasione di un'azione sensibile
async function onLogin() {
const { nonce } = await (await fetch('/api/botdetect/nonce')).json();
BotDetect.collector.setNonce(nonce);
const signals = await BotDetect.collector.collect();
const resp = await fetch('/api/botdetect/verify', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ signals, nonce })
});
const { verdict, score, proof, friction } = await resp.json();
document.getElementById('botdetect-proof').value = proof;
document.getElementById('login-form').submit();
}
5. Validare lato server
app.post('/api/login', (req, res) => {
const bd = req.session.botdetect;
if (!bd) return res.status(403).json({ error: 'no_verification' });
if (bd.verdict === 'bot') return res.status(403).json({ error: 'access_denied' });
if (bd.verdict === 'suspicious') return challengeCaptcha(req, res);
res.json({ success: true });
});
API Lato Client
Collector (singleton)
import Collector from './collector/Collector';
// oppure via globale: BotDetect.collector
Detector (solo debug)
import Detector from './detector/Detector';
Attenzione: analyze() viene eseguito interamente nel browser. Non utilizzare mai il suo output per decisioni in produzione.
Tipi
interface DetectionResult {
name: string; // Nome del modulo
score: number; // 0.0 – 1.0
weight: number; // 1 – 10 (importanza)
detail?: string; // Descrizione leggibile dall'uomo
}
interface DetectionVerdict {
verdict: 'bot' | 'suspicious' | 'human';
score: number; // 0.0 – 1.0
confidence: number; // 0.0 – 1.0
signals: DetectionResult[];
threshold: number;
friction: 'monitor' | 'challenge' | 'block';
}
interface CollectorConfig {
detectionTimeoutMs: number; // timeout per modulo (default: 3000)
enableTraps: boolean;
enableBehavioralTracking: boolean;
enableHoneypots: boolean;
thresholds: { strict: number; balanced: number; relaxed: number };
}
Integrazione Lato Server
Express Middleware
const { createBotDetectEndpoint } = require('./server');
const { router, generateProofOfWork, cleanup } = createBotDetectEndpoint({
secretSalt: process.env.BOTDETECT_SALT,
scoring: {
threshold: 'balanced', // 'strict' | 'balanced' | 'relaxed' | number
minSignals: 2,
signalBoostThreshold: 0.8,
frictionThresholds: { monitor: 0.2, challenge: 0.5, block: 0.8 }
},
nonce: { ttl: 300000 }, // scadenza nonce di 5 minuti
noScript: { timeout: 10000 }, // finestra no-script di 10s
rateLimit: { maxRequests: 10, windowMs: 60000 },
noScriptPaths: ['/api/login', '/api/checkout', '/api/register']
});
app.use('/api', router);
Endpoint
| Endpoint | Metodo | Scopo |
|---|
/api/botdetect/nonce | GET |
Formato della risposta del server
{
"verdict": "human",
"score": 0.125,
"confidence": 0.85,
"tamperScore": 0,
"friction": "monitor",
"threshold": 0.5,
"proof": "a1b2c3d4e5f6..."
}
Calcolo del punteggio lato server (Node.js)
const { computeVerdict, RateLimiter, NonceManager } = require('./scoring');
const verdict = computeVerdict(signals, {
threshold: 'balanced',
minSignals: 2,
signalBoostThreshold: 0.8,
frictionThresholds: { monitor: 0.2, challenge: 0.5, block: 0.8 }
});
// verdict.tamperScore > 0 se vengono rilevate manomissioni dei segnali
Moduli di Rilevamento
Framework di automazione (pesi 5–7)
Specifici per Playwright (pesi 3–4)
| Modulo | Rileva | Peso |
|---|
playwrightWebKit | Artefatti di automazione WebKit | 4 |
playwrightOrientation | Incoerenza tra orientamento e chrome.runtime | 3 |
Analisi comportamentale (peso 7)
| Modulo | Segnali Analizzati | Peso |
|---|
behavioralAnalysis | Curvatura del mouse + rapporto linee rette, CV della digitazione + pattern di raffica + KPM, accelerazione dello scorrimento + cambi di direzione, varianza della forza tattile + raggio | 7 |
Fingerprinting del browser (pesi 3–4)
Proprietà Navigator e OS (peso 5)
| Modulo | Controlli | Peso |
|---|
navigatorInconsistencies | 11 controlli: languages, plugins, mimeTypes, platform, UA, cookies, DNT, touch, hardwareConcurrency, deviceMemory, connection | 5 |
Trappole attive e Honeypot (pesi 8–9)
| Modulo | Rileva | Peso |
|---|
honeypotTraps | Campi nascosti randomizzati + esche + endpoint canarino | 9 |
Di rete e contestuali (pesi 1–2)
Whitelist (peso 0)
| Modulo | Rileva | Peso |
|---|
verifiedBots | Oltre 20 crawler noti (Googlebot, Bingbot, Yandex, Facebook, Twitter, ecc.) — restituisce -1, escluso dal punteggio | 0 |
Configurazione
Collector
const collector = Collector.getInstance({
detectionTimeoutMs: 1000, // Più basso per UX più veloce
enableTraps: true,
enableBehavioralTracking: true,
enableHoneypots: true,
thresholds: {
strict: 0.3, // Aggressivo (login, checkout)
balanced: 0.5, // Default
relaxed: 0.7 // Permissivo (navigazione contenuti)
}
});
Detector (solo debug)
const detector = Detector.getInstance({
threshold: 'balanced', // 'strict' | 'balanced' | 'relaxed' | number
minSignals: 2, // Segnali minimi prima del boost
signalBoostThreshold: 0.8, // Segnali sopra questa soglia ottengono peso extra
failPolicy: 'open', // 'open' = umano in caso di errore, 'closed' = bot in caso di errore
frictionThresholds: {
monitor: 0.2,
challenge: 0.5,
block: 0.8
}
});
Server
createBotDetectEndpoint({
secretSalt: process.env.BOTDETECT_SALT, // Mantieni segreto
scoring: { threshold: 'balanced' },
nonce: { ttl: 300000, cleanupInterval: 60000 },
noScript: { timeout: 10000 },
rateLimit: { maxRequests: 10, windowMs: 60000 },
requestFingerprint: true, // Lega PoW agli attributi della richiesta
noScriptPaths: ['/api/login', '/api/checkout']
});
Checklist per la Produzione
Sicurezza
Monitoraggio
Test
npm test # 74 Jest tests across 6 suites
npm run typecheck # TypeScript strict mode
npm run lint # ESLint
npm run build # Webpack production bundle
Licenza
Apache — Lahmeri Mohamed Amine