This is a viewer only at the moment see the article on how this works.
To update the preview hit Ctrl-Alt-R (or ⌘-Alt-R on Mac) or Enter to refresh. The Save icon lets you save the markdown file to disk
This is a preview from the server running through my markdig pipeline
Monday, 16 February 2026
La detezione dei robot per l'impresa non dovrebbe'dure un dottorato in infrastrutture (o migliaia al mese di spese per usarlo !). Due linee di codiceM SK3 zero servizi esterniMNK4 e voiMMK5lavorate SSK6~) \21\detttori in millisecondi su ogni richiesta a ogni punto di fineMRK9
Leggere la parte 1: StyloBot: Combattersi di nuovo contro i Combattenti
Leggere la parte 2: Come i bot sono diventati più intelligenti
👉 See It Live: StyloBotM SK2net - Il sistema di produzione reale in funzione presto-Detezione dell'exit inline alla portaM SK2
Einstein diceva:,, ", "Tutto deve essere fatto il più semplice possibile, ,, ma niente di più semplice,."", "Questo è il principio di design del StyloBot, il modello di integrazione del ', il .".
Parte 1 e 2 coperte Perché? i problemi di rilevamento dei robot e Come funziona il tubo di rilevamento?. Questo post copre Quanti piccoli codici ci servono? - e come lo stesso sistema scala da una sola app di file - ad un'intera porta di produzione con TimescaleDB, La ricerca dei vectori QdrantM SK3 e il processore CPUMSC4 Solo classificazione LLMMスク5
Il punto di vista chiave: Ogni livello usa la stessa catena di rilevamento.. Voi' non cambiate i schemi mentre cresceteM SK2 Vogliamo aggiungere l'archiviazione e l'enrichimento intorno allo stesso nucleo .
Questo è il minimo assoluto. Nessun file di configurazione, nessuna configurazione della base di datiM SK2 nessuna chiave API , nessun contenitore DockerMSC4
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddBotDetection(); // ← that's line 1
var app = builder.Build();
app.UseBotDetection(); // ← that's line 2
app.Run();
Cos'è successo?
botdetection.db file auto- crea modelli e pesci imparati. Niente configurazioneM SK2Tutto questo va avanti. sotto 1 millisecondi per ogni richiesta di hardware di merce. solo CPU, nessun GPUM SK2
Ogni richiesta ora ha risultati di rilevamento disponibili tramite HttpContext Prolungamenti:
app.MapGet("/", (HttpContext ctx) => Results.Ok(new
{
isBot = ctx.IsBot(),
probability = ctx.GetBotProbability(), // 0.0-1.0: how likely it's a bot
confidence = ctx.GetDetectionConfidence(), // 0.0-1.0: how certain the system is
type = ctx.GetBotType()?.ToString(),
name = ctx.GetBotName()
}));
La rilevazione funziona ma niente blocca. Decidete cosa fare con i risultati.
Se volete solo bloccare i bot dall'intera vostra applicazione - nessun perM SK1config punto di fine, nessun attributo - èMSC4 una linea di JSONMST5
{
"BotDetection": {
"BlockDetectedBots": true
}
}
Che 's itM SK1 I robot rilevati sopra il tuo blocco - soglia di fiducia ottengono unMinConfidenceToBlock defaults to 0.8). I motori di ricerca (Googlebot, Bing botM SK3 le preview dei social media ♫(FacebookMST5 TwitterMSC6XMSST7 e i robot di monitoraggio |(UptimeRobot | MST9 | Pingdom | SST10 | sono accessibili da default |SST11 | perché quasi certamente li volete |
O la stessa cosa nel codice, non c'è bisogno di file di configurazione:
builder.Services.Configure<BotDetectionOptions>(o =>
{
o.BlockDetectedBots = true;
o.MinConfidenceToBlock = 0.8; // only block when confident
o.AllowVerifiedSearchEngines = true; // Googlebot, Bingbot through
o.AllowSocialMediaBots = true; // Facebook, Twitter previews through
o.AllowMonitoringBots = true; // UptimeRobot, Pingdom through
});
Questo è il "Io non lo voglio 'non voglio pensarci"modoM SK3Funzionano le rilevazioniMSC4 i robot vengono bloccatiMST5 bravi crawler passano attraversoMst6 Si muovo a perMSt7controllo finale quando ti serveM st8
Qui ' è un intero , API di lavoro con per- protezione dei bot terminaliM SK3 Questo è l'intero Program.cs:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddBotDetection();
var app = builder.Build();
app.UseBotDetection();
// Detection results available, no blocking
app.MapGet("/", (HttpContext ctx) => Results.Ok(new
{
isBot = ctx.IsBot(),
probability = ctx.GetBotProbability(),
confidence = ctx.GetDetectionConfidence(),
type = ctx.GetBotType()?.ToString(),
name = ctx.GetBotName()
}));
// Block all bots
app.MapGet("/api/data", () => Results.Ok(new { data = "sensitive" }))
.BlockBots();
// Allow search engines (Googlebot, Bingbot, Yandex)
app.MapGet("/products", () => Results.Ok(new { catalog = "public" }))
.BlockBots(allowSearchEngines: true);
// Allow search engines + social media previews (Facebook, Twitter/X)
app.MapGet("/blog/{slug}", (string slug) => Results.Ok(new { post = slug }))
.BlockBots(allowSearchEngines: true, allowSocialMediaBots: true);
// Health check: monitoring bots allowed (UptimeRobot, Pingdom)
app.MapGet("/health", () => Results.Ok("healthy"))
.BlockBots(allowMonitoringBots: true);
// Humans only - blocks ALL bots including verified crawlers
app.MapPost("/api/submit", () => Results.Ok(new { submitted = true }))
.RequireHuman();
// High-confidence blocking only (reduces false positives)
app.MapGet("/api/lenient", () => Results.Ok("data"))
.BlockBots(minConfidence: 0.9);
// Geo + network blocking (needs GeoDetection contributor)
app.MapPost("/api/payment", () => Results.Ok("ok"))
.BlockBots(blockCountries: "CN,RU", blockVpn: true, blockDatacenter: true);
// Honeypot: deliberately allow scrapers in
app.MapGet("/honeypot", () => Results.Ok("welcome"))
.BlockBots(allowScrapers: true, allowMaliciousBots: true);
// Dev diagnostics
app.MapBotDetectionEndpoints();
app.Run();
Ogni anno. .BlockBots() blocchi di chiamata Tutti. I tipi di bot per default. Si possono scegliere tipi specifici. Si tratta di un sistema basato su una classificazione basata sulla classificazione. con l'uso di Allow* Parameteri. L'idea è negare-dall'altra parteM SK2defaultMSC3 lista bianca le buone .
| Parametro | Cosa lo consente | Perché lo usate' |
|---|---|---|
allowSearchEngines |
Googlebot, Bingbot , Yandex | SEO SSK4 volete essere inseriti in un'indexazione S |
allowSocialMediaBots |
FacebookM SK1 Twitter/XMSC3 LinkedIn | Previews di linkMST5 Open Graph cards |
allowMonitoringBots |
UptimeRobotM SK1 Pingdom, StatusCake | Controlli di saluteMSC4 Monitoring dell'approvvigionamento. |
allowAiBots |
GPTBotM SK1 ClaudeBot, GoogleMSC3Extended | Opt-in to AI training |
allowGoodBots |
Reader per il feedM SK1 Checker per i link | Automatizzazione dei Benign |
allowVerifiedBots |
DNS | |
allowScrapers |
AhrefsBot, SemrushBot | Honeypots |
allowMaliciousBots |
I cattivi attori conosciuti | Honeypots |
minConfidence |
(intervalloM SK1 | Bloccare solo quando il sistema è molto sicuro |
La stessa catena di rilevamento, protezione tramite attributi.
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddBotDetection();
builder.Services.AddControllersWithViews();
var app = builder.Build();
app.UseBotDetection();
app.MapControllers();
app.Run();
[ApiController]
[Route("[controller]")]
public class ProductsController : ControllerBase
{
// No protection - detection runs but nothing blocks
[HttpGet]
public IActionResult List() => Ok(new { products = "all" });
// Block all bots, allow search engines
[HttpGet("catalog")]
[BlockBots(AllowSearchEngines = true)]
public IActionResult Catalog() => Ok(new { catalog = "indexed" });
// Block all bots, allow search engines + social previews
[HttpGet("{id:int}")]
[BlockBots(AllowSearchEngines = true, AllowSocialMediaBots = true)]
public IActionResult Detail(int id) => Ok(new { id });
}
// Entire controller: humans only
[ApiController]
[Route("[controller]")]
[RequireHuman]
public class CheckoutController : ControllerBase
{
[HttpPost("cart")]
public IActionResult AddToCart() => Ok();
[HttpPost("pay")]
public IActionResult Pay() => Ok();
}
// Infrastructure endpoints
[ApiController]
[Route("[controller]")]
public class InfraController : ControllerBase
{
// Skip detection entirely
[HttpGet("health")]
[SkipBotDetection]
public IActionResult Health() => Ok("ok");
// Monitoring bots allowed
[HttpGet("status")]
[BlockBots(AllowMonitoringBots = true)]
public IActionResult Status() => Ok(new { uptime = "99.9%" });
}
Questi lavorino sia su attributi MVC che su filtri API Minimal. Richiedono il contribuente GeoDetection per i dati del segnale.
// Block countries
[BlockBots(BlockCountries = "CN,RU,KP")]
public IActionResult SensitiveApi() => Ok();
// Country whitelist - only these allowed
[BlockBots(AllowCountries = "US,GB,DE,FR")]
public IActionResult DomesticOnly() => Ok();
// Block VPNs + proxies (anti-fraud)
[BlockBots(BlockVpn = true, BlockProxy = true)]
public IActionResult Payment() => Ok();
// Block datacenter IPs + Tor
[BlockBots(BlockDatacenter = true, BlockTor = true)]
public IActionResult FormSubmission() => Ok();
// Combine: SEO-friendly + geo block + VPN block
[BlockBots(AllowSearchEngines = true, BlockCountries = "CN,RU", BlockVpn = true)]
public IActionResult ProtectedContent() => Ok();
Blocco binario/autorizzare è semplice ma limitato. Politiche di azione separate Quello che si rileva a partire da Come reagi?. Definire le strategie di risposta nella configurazione, assegnarle ai punti finaliM SK2
{
"BotDetection": {
"BotThreshold": 0.7,
"ActionPolicies": {
"api-block": {
"Type": "Block",
"StatusCode": 403,
"Message": "Bot traffic is not allowed."
},
"api-throttle": {
"Type": "Throttle",
"BaseDelayMs": 500,
"MaxDelayMs": 5000,
"ScaleByRisk": true,
"JitterPercent": 0.3
},
"shadow-mode": {
"Type": "LogOnly",
"AddResponseHeaders": true,
"LogFullEvidence": true
}
}
}
}
// Bots get progressively slower responses (they don't know they're being throttled)
[BotPolicy("default", ActionPolicy = "api-throttle")]
public IActionResult Browse() => Ok();
// Hard block
[BotPolicy("default", ActionPolicy = "api-block")]
public IActionResult Confirm() => Ok();
// Shadow mode: log everything, block nothing (deploy first, tune later)
[BotPolicy("default", ActionPolicy = "shadow-mode")]
public IActionResult PublicApi() => Ok();
Cinque tipi di politica: Block (HTTP 403), Throttle (delitti di privacyM SK1 Challenge (CAPTCHA Redirect ( LogOnly (modo diombra). Vedete il Doc delle politiche di azione. per la descrizione completa.
Il modo "shadow" è il punto di partenza preferito. Detezione di deploiamento, Osservare i risultatiM SK2 soglia di tonalità e poi. iniziare a bloccare.
Ogni richiesta dopo. UseBotDetection() queste estensioni sono disponibili su HttpContext:
// Am I talking to a bot?
context.IsBot() // true if probability >= threshold
context.IsHuman() // inverse
context.IsSearchEngineBot() // Googlebot, Bingbot, etc.
context.IsVerifiedBot() // DNS-verified bots
context.IsMaliciousBot() // known bad actors
// How bad is it?
context.GetBotProbability() // 0.0-1.0: likelihood of being a bot
context.GetDetectionConfidence() // 0.0-1.0: how certain the system is
context.GetRiskBand() // Low, Elevated, Medium, High
context.GetRecommendedAction() // Allow, Challenge, Throttle, Block
// What is it?
context.GetBotType() // BotType enum
context.GetBotName() // "Googlebot", "Scrapy", etc.
// Full breakdown
var result = context.GetBotDetectionResult();
Due punteggi indipendenti sono importanti qui: Probabilità di bot (come è probabile che questo sia un robot?) e La fiducia nella rilevazione. (come si è certi del sistema?). Potete essere 95% sicuri che qualcosa sia. l'uomo. (poche probabilitàM SK1alta fiducia). Oppure potete vedere una richiesta sospetta ma con poca fiducia perché c'è solo un rilevatore in funzioneMSC3
Oltre i tipi di bot, StyloBot espone segnali tipizzati 100+ dai suoi rilevatoriM SK2 Si possono filtrare punti finali basati su valori specifici del segnale - sia per la Minimal API che per il MVC
// Block VPN traffic
app.MapPost("/api/payment", () => Results.Ok())
.BlockIfSignal(SignalKeys.GeoIsVpn, SignalOperator.Equals, "True");
// Block datacenter IPs
app.MapPost("/api/submit", () => Results.Ok())
.BlockIfSignal(SignalKeys.IpIsDatacenter, SignalOperator.Equals, "True");
// Only allow US traffic
app.MapGet("/api/domestic", () => Results.Ok())
.RequireSignal(SignalKeys.GeoCountryCode, SignalOperator.Equals, "US");
// Block high-confidence bots by heuristic score
app.MapGet("/api/premium", () => Results.Ok())
.BlockIfSignal(SignalKeys.HeuristicConfidence, SignalOperator.GreaterThan, "0.9");
[BlockIfSignal(SignalKeys.GeoIsVpn, SignalOperator.Equals, "True")]
public IActionResult Payment() => Ok();
[RequireSignal(SignalKeys.GeoCountryCode, SignalOperator.Equals, "US")]
public IActionResult DomesticOnly() => Ok();
app.MapGet("/debug", (HttpContext ctx) =>
{
var country = ctx.GetSignal<string>(SignalKeys.GeoCountryCode);
var isVpn = ctx.GetSignal<bool>(SignalKeys.GeoIsVpn);
var isDc = ctx.IsDatacenter();
var heuristic = ctx.GetSignal<double>(SignalKeys.HeuristicConfidence);
return Results.Ok(new { country, isVpn, isDc, heuristic });
});
Referenza completa al segnale: segnali e filtri personalizzati..
# Normal browser request → low bot score
curl -H "Accept: text/html" -H "Accept-Language: en-US" \
-A "Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/120.0.0.0" \
http://localhost:5090/
# Googlebot → allowed where AllowSearchEngines=true
curl -A "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)" \
http://localhost:5090/products
# Scraper → blocked by .BlockBots()
curl -A "Scrapy/2.7" http://localhost:5090/api/data
# Full detection breakdown → shows all signals and per-detector contributions
curl http://localhost:5090/bot-detection/check
# Simulate bot types via test mode header
curl -H "ml-bot-test-mode: malicious" http://localhost:5090/bot-detection/check
curl -H "ml-bot-test-mode: scraper" http://localhost:5090/api/data
L'informazione figura nella parte dispositiva. /bot-detection/check il punto finale è il vostro amico di sviluppo. Rende ogni segnale da ogni rilevatore, dati di timingM SK2 e per i contributi dei rilevatori, così che possiate vedere esattamente cosa sta succedendo.
Questo è il principio di progettazione più importante: Ogni livello usa la stessa catena di rilevamento.. Voi' non riscrivete mai il codice di protezioneM SK2 Voi' aggiungete l'infrastruttura intorno allo stesso nocciolo .
Your App + AddBotDetection()
└── SQLite (auto-created botdetection.db)
└── In-process [HNSW](https://en.wikipedia.org/wiki/Hierarchical_navigable_small_world_graphs) similarity search
└── 21 detectors, <1ms per request
└── No external services
Tutti i rilevatori 21 funzionano in una onda-in un tubo basatoM SK2FastMSC3dettatori di percorso (UserAgentMska5HeaderMske6IPMsek7ConduttiviMске8Taglio digitale TLSM Ske9Si eseguiscono in parallelo nella Wave CMS10Estrazioni heuristice di punteggio DMS11Feature e conduce un modello di punteggi leggeriMS.Patterni imparati persistono su SQLite attraverso i ristartsMSSK13Se volete degli interniM,Parte |2 copre l'architettura e il flusso dei segnali in dettaglioMSSK16
Benissimo per: App unica, M SK1K richieste/ giornoMSC3 inizioMST4
Add geo routing plus the geo contributor:
builder.Services.AddBotDetection();
builder.Services.AddGeoRoutingWithDataHub(); // free local GeoIP DB (no account)
builder.Services.AddGeoDetectionContributor(options =>
{
options.FlagVpnIps = true;
options.FlagHostingIps = true;
});
Se la geolocalizzazione IP è nuova: Il background di GeoIP e DataHub GeoIP dataset sono buoni punti di partenza. DataHubCsv scarica una free ~27MB IP database al primo lancio e la mantiene aggiornata settimanalmenteM SK2 Tutte le visite sono locali - nessun perMSC4 richiede chiamate HTTPMST5 Per la cittàMSP6 precisione di livelloMSV7 uso MaxMind GeoLite2.
Ora si ottengono 20+ segnali geo ( paese, VPNM SK3 proxyMST4 TorMSC5 rilevamento del centro di datiMSSK6 e verifica dell'origine dei bot ♫( Googlebot da un centro di informazioni cinese ♫ = sospetto ♫ BlockCountries, BlockVpn, BlockDatacenter, BlockTor i parametri si attivano.
Sostituire SQLite con PostgreSQL per l'apprendimento condiviso multi-server e aggiungere TimescaleDB (a estensione PostgreSQL per il tempo-dati di serieM SK2 per l'analisi
builder.Services.AddBotDetection();
builder.Services.AddStyloBotDashboard();
builder.Services.AddStyloBotPostgreSQL(connectionString, options =>
{
options.EnableTimescaleDB = true;
options.RetentionDays = 90;
options.CompressionAfter = TimeSpan.FromDays(7);
});
# docker-compose.yml
services:
timescaledb:
image: timescale/timescaledb:latest-pg16
environment:
POSTGRES_DB: stylobot
POSTGRES_USER: stylobot
POSTGRES_PASSWORD: ${DB_PASSWORD}
volumes:
- timescale-data:/var/lib/postgresql/data
app:
build: .
environment:
ConnectionStrings__BotDetection: "Host=timescaledb;Database=stylobot;Username=stylobot;Password=${DB_PASSWORD}"
depends_on:
timescaledb:
condition: service_healthy
TimescaleDB vi dà la partizione ipertabile, compressione automatica M SK1 riduzione di memoria dopo 7 giorni), aggregi continui per il sotto--questioni da scatola millisecondiMST5 e politiche di conservazioneMSC6
Benissimo per: >100K richiesteM SK1 giorno, server multipleMSC3 dashboard di analisi necessarie .
Internet → Caddy (TLS) → Stylobot Gateway ([YARP](https://microsoft.github.io/reverse-proxy/)) → Your App
│
├── TimescaleDB (analytics, learning)
├── [Qdrant](https://qdrant.tech/documentation/) (vector similarity search)
└── LLamaSharp CPU [LLM](https://en.wikipedia.org/wiki/Large_language_model) (bot classification)
La porta è un contenitore Docker autonomo (scottgal/stylobot-gateway) che fa la rilevazione su tutti i traffici e trasmette i risultati come titoli HTTP. La vostra app legge i titoli - non c'è bisogno di SDK, nessuna lingua. Se "gateway" è sconosciutoM SK3 pensate "Proxy inversa che si trova davanti alla vostra app e aggiunge sicurezza/Logica del traffico."
services:
gateway:
image: scottgal/stylobot-gateway:latest
environment:
DEFAULT_UPSTREAM: "http://app:8080"
StyloBotDashboard__PostgreSQL__ConnectionString: "Host=timescaledb;..."
StyloBotDashboard__PostgreSQL__EnableTimescaleDB: true
BotDetection__Qdrant__Enabled: true
BotDetection__Qdrant__Endpoint: http://qdrant:6334
BotDetection__Qdrant__EnableEmbeddings: true
BotDetection__AiDetection__Provider: LlamaSharp
BotDetection__AiDetection__LlamaSharp__ModelPath: "Qwen/Qwen2.5-0.5B-Instruct-GGUF/qwen2.5-0.5b-instruct-q4_k_m.gguf"
app:
build: .
environment:
BOTDETECTION_TRUST_UPSTREAM: true
qdrant:
image: qdrant/qdrant:latest
timescaledb:
image: timescale/timescaledb:latest-pg16
caddy:
image: caddy:latest
La vostra app crede al gateway's headers:
// ASP.NET Core
builder.Services.Configure<BotDetectionOptions>(o => o.TrustUpstreamDetection = true);
O leggere i titoli direttamente in qualsiasi lingua:
# Python/Flask
@app.route('/api/data')
def api_data():
if request.headers.get('X-Bot-Detected') == 'true':
return jsonify(error='blocked'), 403
return jsonify(data='sensitive')
// Node.js/Express
app.get('/api/data', (req, res) => {
if (req.headers['x-bot-detected'] === 'true') {
return res.status(403).json({ error: 'blocked' });
}
res.json({ data: 'sensitive' });
});
Header che il gateway manda:
| Insieme | Esempio | Obiettivo S |
|---|---|---|
X-Bot-Detected |
true |
BotM SK1 classificazione umana |
X-Bot-Confidence |
0.91 |
Confidenza di rilevamento |
X-Bot-Detection-Probability |
0.87 |
Probabilità del bot |
X-Bot-Type |
Scraper |
Categoria dei bot |
X-Bot-Name |
AhrefsBot |
Bot identificato |
X-Bot-Detection-RiskBand |
High |
Classificazione dei rischi |
| Componente | ||
|---|---|---|
| TimescaleDB | TempoM SK1analisi di serie, immagazzinamento compressoMNK3 aggregati continuiMMK4 politiche di conservazione | Suggerito per la produzione SNK6 |
| Qdrant | La ricerca di somiglianza con i vettori - trova dei robot anche quando ruotano Usatore-Agenti ♫ | Opzionale ♫ |
| LLamaSharp | CPU-solo LLM per la classificazione e l'innomenazione dei gruppi di bot. | |
| Caddy/Nginx | Terminazione del TLS, file statici | il vostro proxy inversa |
| Portatile | Detezione centralizzata per multiapp o non--.NET backends. |
Starting out?
├── Single ASP.NET app → Tier 1 (two lines of code)
│ └── Need geo blocking? → Tier 2 (one more line)
│ └── Need analytics? → Tier 3 (add PostgreSQL)
└── Multiple apps or non-.NET? → Tier 4 (Gateway)
Il spostamento tra i livelli è un cambiamento di registro DI. Il codice di protezione del vostro punto di fine - il [BlockBots] attributes, il .BlockBots() filtri, il context.IsBot() Controlli - rimane esattamente ugualeM SK1
Il setup delle due linee è il punto di partenza.
Spegnere globalmente i titoli di rilevamento così da poter verificare il comportamento senza colpire i punti di fine diagnostici:
{
"BotDetection": {
"ResponseHeaders": {
"Enabled": true,
"HeaderPrefix": "X-Bot-",
"IncludeConfidence": true,
"IncludeDetectors": true,
"IncludeProcessingTime": true,
"SkipPaths": ["/health"]
}
}
}
Ogni risposta arriva. X-Bot-Detected, X-Bot-Confidence, X-Bot-Processing-Ms, etc. Utilizzabile per le decisioni di routing delle aree in Caddy /NginxM SK3 e per il debugging nel devMSC4 Disable nella produzione o restringersi a reti affidabiliMスク5
Don' non blocca l'incertezza M SK1 sfida invece . StyloBot ha cinque tipi di sfida
{
"BotDetection": {
"ActionPolicies": {
"challenge-on-uncertain": {
"Type": "Challenge",
"ChallengeType": "JavaScript"
},
"captcha-gate": {
"Type": "Challenge",
"ChallengeType": "Captcha",
"RedirectUrl": "/captcha"
},
"proof-of-work": {
"Type": "Challenge",
"ChallengeType": "ProofOfWork"
}
}
}
}
Tipi di sfida: Redirect ( mandare alla pagina di sfidaM SK1 Inline (HTML interstitiale), JavaScript (Protocolo JSM SK1di-operaMSC3 Captcha, ProofOfWork (questo di calcolo). Assignare ai punti finali attraverso [BotPolicy]:
[BotPolicy("default", ActionPolicy = "challenge-on-uncertain")]
public IActionResult Submit() => Ok();
Liste globali per consentire e negare i dati IP conosciuti. CIDR ranges:
{
"BotDetection": {
"WhitelistedIps": ["203.0.113.10/32", "198.51.100.0/24"],
"BlacklistedIps": ["1.2.3.4", "5.6.7.0/24"]
}
}
IP in lista bianca scorrono completamente la rilevazione. IP in Lista nera vengono bloccate immediatamente. Entrambi supportano la notazione CIDRM SK2
StyloBot espone le misurazioni attraverso System.Diagnostics.Metrics, compatibile con OpenTelemetry, Prometheus, Grafana, e qualsiasi .NET metrico consumatoreM SK2
builder.Services.AddOpenTelemetry()
.WithMetrics(metrics => metrics.AddMeter("Mostlylucid.BotDetection"));
Metriki disponibili:
| Metrica | Tipo | Cosa misura S |
|---|---|---|
botdetection.requests.total |
Contatore | Il totale delle richieste processate |
botdetection.bots.detected |
Contatore | Requiste classificate come robot |
botdetection.humans.detected |
Contriuttore | Requiste classificate come umani |
botdetection.errors.total |
Contatore | Errori del tubo di detezione PSK2 |
botdetection.detection.duration |
Histogramma | La latenza di detezione SSK2ms) MSC4 |
botdetection.confidence.average |
Gauge | Confidenza media di giro MSC2 |
botdetection.cache.patterns.count |
Gauge | Numero di schemi codificati PSK2 |
Questi sono i numeri di cui avete bisogno per il pannello di controllo, l'allarmeM SK1 e la pianificazione della capacità. L'histogramma della latenza di rilevamento vi permette di stabilire gli SLO . il bot*/ i contatori umani vi danno la composizione del traffico nel tempoMSC5
Applicate la protezione dei robot su interi gruppi di corsie invece che ripetere per -endpoint:
// All /api routes: block bots, allow search engines
var api = app.MapGroup("/api").WithBotProtection(allowSearchEngines: true);
api.MapGet("/products", () => "data");
api.MapGet("/categories", () => "cats");
// Secured routes: humans only
var secure = app.MapGroup("/secure").WithHumanOnly();
secure.MapPost("/submit", () => "ok");
secure.MapPost("/checkout", () => "done");
// Individual endpoints can still override
api.MapGet("/special", () => "overridden")
.BlockBots(allowSearchEngines: true, allowSocialMediaBots: true);
WithBotProtection() prende gli stessi parametri geo/network/confidence come .BlockBots(), ma intenzionalmente blocca sempre gli smascheratori e i bot maliziosi a livello di gruppo (no allowScrapers / allowMaliciousBots su gruppi). WithHumanOnly() è l'equivalente di un gruppo. .RequireHuman().
Usare .BotPolicy() per assegnare le politiche di azione chiamate ai punti di fine del Minimal API - la stessa cosa. [BotPolicy] Fa per MVC:
// Throttle bots on this endpoint
app.MapGet("/api/data", () => "sensitive")
.BotPolicy("default", actionPolicy: "api-throttle");
// Block with high-confidence threshold
app.MapPost("/api/submit", () => "ok")
.BotPolicy("strict", actionPolicy: "block", blockThreshold: 0.8);
Racconta false positivi e negativi al sistema tramite POST /bot-detection/feedback:
# Mark a detection as a false positive (bot detected but was actually human)
curl -X POST http://localhost:5090/bot-detection/feedback \
-H "Content-Type: application/json" \
-d '{"outcome": "Human", "notes": "Known partner integration"}'
# Mark a missed bot (human detected but was actually a bot)
curl -X POST http://localhost:5090/bot-detection/feedback \
-H "Content-Type: application/json" \
-d '{"outcome": "Bot", "notes": "Automated scraper spotted in logs"}'
Il punto finale restituisce se il feedback rappresenta un falso positivo o un falso negativo rispetto al risultato di rilevamento attuale. Questa è la base per l'apprendimento a circuito chiuso-loop2
Quando usate il gateway YARP, la vostra backend si affida ai header di rilevamento in arrivo. Questa è una configurazione sensibile per la sicurezzaM SK2 - dovete assicurarvi che solo il gateways può stabilire quei headersMSC4
Confidenza di base ( reteM SK1 isolamento a livello solo):
{
"BotDetection": {
"TrustUpstreamDetection": true
}
}
HMAC-confidenza firmata M SK1verificazione criptografica):
{
"BotDetection": {
"TrustUpstreamDetection": true,
"UpstreamSignatureHeader": "X-Bot-Signature",
"UpstreamSignatureSecret": "base64-encoded-shared-secret"
}
}
Quando? UpstreamSignatureHeader e UpstreamSignatureSecret sono stati stabiliti, il middleware verifica un HMAC-SHA256 firma prima di fidarsi dei titoli in arrivo.
Usate questo per ora. Gateway personalizzato/integrazioni proxy che aggiungono i titoli di firma. L'interfaccia di Stylobot costruita-in avanti porta il botM SK2header di rilevamentoMSC3 ma non emette ancora i titoli della firma HMAC .
Cose da scrivere firmate:
X-Bot-Signature (base64HMACM SK2X-Bot-Detection-Timestamp (Sekunden dell'Epoche UnitaM SK1 UTC)Firma del contratto:
payload = X-Bot-Detected + ":" + X-Bot-Confidence + ":" + X-Bot-Detection-Timestampsignature = Base64(HMACSHA256(payload, base64Decoded(UpstreamSignatureSecret)))Signature fuori da un 5-window di riproduzione di un minuto vengono rifiutate. Se la firma mancaM SK2invalidaMSC3 o che è finita , i header in arrivo sono rifiutati e la rilevazione locale completa viene attivata inveceMSL5
Importante: Spegnere la fiducia solo quando il vostro backend è dietro un proxy inversa affidabile. Se un attaccatore riesce a raggiungere il vostro Backend direttamente, può imitare. X-Bot-Detected: false e bypassare tutte le rilevazioni. In produzione:
X-Bot-* i titoli al vostro proxy di bordo prima che raggiungano la porta.Worth being explicit:
/products permettere ai motori di ricerca mentre /api/checkout Ha bisogno di umani. Questa è la semantica del punto finale, non le regole del firewallM SK2La parte 1 riguardava il perché la rilevazione dei robot è importante. La parte 2 riguardava l'interfaccia interna del tubo di rilevamentoM SK3 Questo posto ha riguardato l'integrazione minimamente sostenibile e il percorso di scalatura - da due linee di codice a una porta di produzione completaMSC5
Cominciamo:
dotnet add package Mostlylucid.BotDetectiondocker pull scottgal/stylobot-gateway© 2026 Scott Galloway — Unlicense — All content and source code on this site is free to use, copy, modify, and sell.