StyloBot: As Simple as Possible And No Simpler (Part 3)
La détection de robots d’entreprise ne devrait pas nécessiter un doctorat en infrastructure (ou des milliers par mois dans les dépenses pour l’utilisation !). Deux lignes de code
Lire la partie 1: StyloBot: Lutte contre les Scrappers
Lire la partie 2: Comment les bottes sont devenues plus intelligentes
👉 Voir en directM SK1 StyloBot.net - Le système de production réel qui fonctionne tôt - Détection d'exit en ligne à la passerelle
L'idée
Einstein aurait dit : « Tout doit être fait aussi simple que possible ». « ,, mais pas plus simple ».
Pièces 1 et 2 couvertes pourquoi les questions de détection des robots et Comment fonctionne le pipeline de détection?. Ce poste couvre comment peu de code vous avez vraiment besoin - et comment le même système peut passer d’une seule application de fichiers - à une passerelle de production complète avec TimescaleDB, Recherche par vecteur QdrantM SK3 et CPUMST4classification LLM seulementMSC5
Le point de vue clé: chaque niveau utilise la même conduite de détection. Vous ' ne changez pas de cadres au fur et à mesure que vous croîtez . Vous+' ajoutez l’entreposage et l’enrichissement autour du même noyau
Deux lignes de code
Il s’agit du minimum absolu. Aucun fichier de configuration , aucune mise en place de base de données
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddBotDetection(); // ← that's line 1
var app = builder.Build();
app.UseBotDetection(); // ← that's line 2
app.Run();
Ce qui vient d’arriver:
- Détecteurs 21 enregistrés: Matchage des patrons de l'agent d'utilisateur, cohérence du headerM SK2 détection du centre de données IP , analyse comportementale , empreintes digitales TLS MSC5 JAMST6JAMst7 TCPM st8 empreints électroniques IPM ST9 HTTPM St10 empreintures digitales MST11 analyse du comportement en cache M st12 rétroaction sur le comportement de réponse M t13 multiM t14 corrélation entre les niveaux M s t15 et plus M m t16
- Voie de pipeline basée sur la vapeur: Les détecteurs fonctionnent dans des ondes de dépendanceM SK1 La vague 0 SSK3aucune dépendance) exécute en parallèle. Des ondes plus tardives ne déclenchent que lorsque les signaux antérieurs justifient une analyse plus approfondie.
- Stockage SQLite: A
botdetection.dbfichier automatique-crée des patrons et des pondérations apprisesM SK1 Aucune configuration. - En- recherche de similitude des processus: Indice de l'HNSW pour trouver des signatures bot similairesM SK1 Aucune base de données externe sur les vecteurs.
- Notation héuristique: ~50 fonctions extraites par demandeM SK2 cotées par un poids léger dans le modèle de traitement-
Tout cela se déroule dans sous 1 milliseconde per request on commodity hardware. CPU only, no GPUM SK2
Chaque demande a maintenant des résultats de détection disponibles par HttpContext extensions:
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 détection fonctionne, mais rien ne bloque. Vous décidez ce que faire avec les résultatsM SK1
Blocker tous les Bots, Appuelle entière
Si vous voulez simplement bloquer les bots de votre application entière - pas parM SK1config point final, pas d'attributs - ilMSC4 une ligne de JSON
{
"BotDetection": {
"BlockDetectedBots": true
}
}
Que les robots détectés au-dessus de votre bloc, le seuil de confiance, obtiennent un 403MinConfidenceToBlock par défaut à 0.8). Les moteurs de recherche (Googlebot, Bing botM SK3 les préviews des médias sociaux (FacebookMSC5 TwitterMST6XMSP7 et les robots de surveillance M(UptimeRobot MST9 PingdomMst10 sont autorisés par défaut AMST11 parce que vous voulez presque certainement ces PMST12
Ou la même chose dans le code, aucun fichier de configuration n'est requis:
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
});
Il s’agit du mode "Je ne veux pas 'je ne veux rien penser à ce sujet" modeM SK3 La détection se faitMSC4 les bots sont bloquésMST5 de bons crawleurs passent par la passerelleMst6 Passez vers le commandement de point final lorsque vous en avez besoinM st8
API minimal: Exemple complet
Voici ' est un API de travail complet , avec protection par point d’accès pour les bots 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();
Tous les .BlockBots() blocs d'appel tous Types de bot par défaut. Vous choisissez des types spécifiques dans avec le Allow* Paramètres. L'idée est de ne pas accepter
Types de bottes que vous pouvez autoriser
| Paramètre | Ce qu'il permet | Pourquoi vous l'utilisez ? |
|---|---|---|
allowSearchEngines |
GooglebotM SK1 Bingbot , Yandex | SEO SSK4 vous voulez être indexé S |
allowSocialMediaBots |
FacebookM SK1 Twitter/XMSC3 LinkedIn | Préviews des liensMST5 Cartes graphiques ouvertes SST6 |
allowMonitoringBots |
UptimeRobot, PingdomM SK2 StatusCake | Checks de santéMSC4 surveillance du temps d'ouverture |
allowAiBots |
GPTBotM SK1 ClaudeBot, GoogleMSC3Extendue | OptMST5in to AI training MSC6 |
allowGoodBots |
Lecteurs de feedsM SK1 Contrôleurs de liens | Automatisation des benignes |
allowVerifiedBots |
DNSM SK1 crawleurs vérifiés | Automatisation fiable |
allowScrapers |
AhrefsBotM SK1 SemrushBot | Honeypots, Recherche SEO |
allowMaliciousBots |
Faibles acteurs connus | |
minConfidence |
(trême seuilM SK1 | Seulement bloquer lorsque le système est très sûr |
Contrôles MVC: Attributes
La même conduite de détection, protection par les attributs.
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddBotDetection();
builder.Services.AddControllersWithViews();
var app = builder.Build();
app.UseBotDetection();
app.MapControllers();
app.Run();
Les attributs
[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%" });
}
Géographique & blocage du réseau
Ces fonctions s’appliquent à la fois aux attributs de MVC et aux filtres API minimales. Elles nécessitent le cotisant GeoDetection pour les données de signaux.
// 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();
Au-delà du bloc/Allow: Politiques d’action
Bloc binaire/allow est simple mais limité. Politiques d'action séparées ce que vous détectez de comment vous réagissez. Définir les stratégies de réponse dans la configuration , assigner celles-ci aux points finals .
appsettings.json
{
"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
}
}
}
}
Assigner des politiques aux points finals
// 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();
Cinq types de politiques: Block (HTTP 403), Throttle (délays de confidentialitéM SK1 Challenge (CAPTCHAM SK1proof -ofMSC3work), Redirect ( LogOnly (mode de l'ombre). Voir le Documents de politique d'action pour la référence complète.
Le mode « ombre » est le point de départ recommandé. Détection de déploiement , Voir les résultats puis commencer à bloquer.
Ce que vous obtiez gratuitement
Chaque demande après UseBotDetection() a ces extensions disponibles sur 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();
Deux points indépendants sont importants ici: probabilité d'un robot (comme probable est-ce qu'il s'agisse d'un robot? la confiance en matière de détection (de quelle façon le système est-il certain? utilisation des ressources humaines ( faible probabilitéM SK1 confiance élevée ). Vous pouvez voir une demande douteuse mais avoir peu de confiance parce qu’un seul détecteur a été utilisé.
Filtration basée sur le signal-
Au-delà des types de bots, StyloBot expose les signaux typés 100+ à partir de ses détecteursM SK2 Vous pouvez filtrer les points finals en fonction de valeurs spécifiques du signal - pour l'API minimal et le MVCMSC4
API minimal
// 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");
MVC
[BlockIfSignal(SignalKeys.GeoIsVpn, SignalOperator.Equals, "True")]
public IActionResult Payment() => Ok();
[RequireSignal(SignalKeys.GeoCountryCode, SignalOperator.Equals, "US")]
public IActionResult DomesticOnly() => Ok();
Lire les signaux en ligne
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 });
});
Référence complète des signaux: signales et filtres personnalisés.
Évaluation
# 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'article 5 de la Loi sur l'immigration et le statut des réfugiés /bot-detection/check endpoint est votre ami de développement. Il retourne tous les signaux provenant de chaque détecteur , données d’échéancier
Comment il est calculé: de fichier à stockage complet
C’est le principe de conception qui est le plus important: chaque niveau utilise la même conduite de détection. Vous ' ne rédigez jamais de nouveau le code de protection . vous M SK3 ajoutez des infrastructures autour du même noyau
Niveau 1: Automne -Contrôlé MSC2À partir de quoi vous débutez MSC3
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
Tous les détecteurs 21 fonctionnent dans une onde - basé sur un pipeline
Bon pour: App unique, M SK1 Demandes de K / jour, démarrageMSC4
Niveau 2: Ajouter Géodétection
Ajouter la routage géo plus le cotisant géo:
builder.Services.AddBotDetection();
builder.Services.AddGeoRoutingWithDataHub(); // free local GeoIP DB (no account)
builder.Services.AddGeoDetectionContributor(options =>
{
options.FlagVpnIps = true;
options.FlagHostingIps = true;
});
Si la géolocalisation IP est nouvelle: Contexte de GeoIP et Système de données GeoIP du DataHub sont bons points de départ. DataHubCsv télécharge une base de données IP gratuite ~27MB au premier démarrage et la tient à jour hebdomadairementM SK2 Tous les lookups sont locaux - pas parMSC4 demande d'appels HTTP MaxMind GeoLite2.
Maintenant, vous obtiendrez 20+ des signaux géographiques ( le pays BlockCountries, BlockVpn, BlockDatacenter, BlockTor Paramètres activés.
Niveau 3: PostgreSQL + TimescaleDB
Remplacer SQLite avec PostgreSQL pour l’apprentissage partagé multi-server et ajouter TimescaleDB (une extension PostgreSQL pour le temps-données de sérieM SK2pour l'analyseMSC3
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 vous permet d'effectuer des partitions hypertables, compression automatique (90-95% réduction de stockage après 7 joursM SK3 regroupements continus pour les sous-groupesMSC4 demandes millisecondaires sur le tableaux de bordMNK5 et politiques de conservationMRK6
Bon pour: >100Requêtes de K/jourM SK2 serveurs multiples , tableau de bord d'analyse requis
Niveau 4: Établissement complet - Porte d'entrée ≥+ Qdrant MSC3 LLM
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 passerelle est un conteneur Docker autonome (scottgal/stylobot-gateway) qui assure la détection de tout le trafic et transmet les résultats sous forme d’en-têtes HTTP. Aucun SDK requis, n'importe quelle langue. Si :Proxy inverse qui se trouve à l’avant de votre app et ajoute la sécurité/logice du trafic."
Suivre une demande par l’intermédiaire de la passerelle. Suivre une demande de navigateur ordinaire, puis passer à un client inconnu. Surveiller d’où provient la réponse au défi et savoir si l’origine reçoit la demandeM SK2 Il s’agit d’un jeu éducatif avec des preuves synthétiques , plutôt que de Stylo en directMSC4Télémétrie du BotMST5
Ouvrir l'explorateur de proxy. TLS se termine à l’extrémité de cet exemple ; la passerelle reçoit un HTTP lisible à partir de cette étendue de confianceservices:
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
Votre application compte sur la passerelle'les titres de l’application:
// ASP.NET Core
builder.Services.Configure<BotDetectionOptions>(o => o.TrustUpstreamDetection = true);
Ou lire les titres directement dans n'importe quelle langue:
# 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' });
});
Intitulés envoyés par la passerelle:
| Intitulé | Exemple MSC2 But MSC3 | |
|---|---|---|
X-Bot-Detected |
true Classification humaine |
|
X-Bot-Confidence |
0.91 |
Confiance de détection |
X-Bot-Detection-Probability |
0.87 |
Probabilité de bottes |
X-Bot-Type |
Scraper |
Catégorie de bottes |
X-Bot-Name |
AhrefsBot |
Bot identifié |
X-Bot-Detection-RiskBand |
High |
Classification des risques |
Ce que chaque composant ajoute
| Composante | Ce qu'elle fait | Exigé |
|---|---|---|
| TimescaleDB | TempsM SK1Analyses de série , Entreposage comprimé, Agrégats continusSSK4 Politiques de conservation SNK5 Suivant pour la production | |
| Qdrant | Recherche de la similitude des vecteurs - trouve les bots même lorsqu'ils tournent UtilisateurM SK2Agents MSC3 Optionnel SMC4 | |
| LLamaSharp | CPUM SK1seulement LLM pour la synthèse du nom et de la classification des grappes bots | Optionnel |
| Caddy/Nginx | Termination de TLS, fichiers statiques | votre proxy inverse existant |
| Porte d'entrée | Détection centralisée pour les applications multiples -app ou non |
Choix de votre niveau
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)
Moving between tiers is a DI registration change. Your endpoint protection code - the [BlockBots] attributs, la .BlockBots() Filters, le context.IsBot() vérifie - demeure exactement le même
Enterprise Hooks (en anglais seulement)
La mise en place des deux lignes est le point de départ.
Headers de réponse pour le débugging
Activer les titres de détection à l'échelle mondiale afin que vous puissiez vérifier le comportement sans toucher des points finals diagnostiques:
{
"BotDetection": {
"ResponseHeaders": {
"Enabled": true,
"HeaderPrefix": "X-Bot-",
"IncludeConfidence": true,
"IncludeDetectors": true,
"IncludeProcessingTime": true,
"SkipPaths": ["/health"]
}
}
}
Chaque réponse reçoit X-Bot-Detected, X-Bot-Confidence, X-Bot-Processing-Ms, etc . Utilisable pour les décisions de routage à bord dans Caddy/NginxM SK3 et pour le débugging dans devMSC4 Débloquer la production ou restreindre les réseaux confiésMスク5
Politiques de contestation (Friction avant blocageM SK1
Don't bloque sur l’incertitude - défi plutôtM SK2 StyloBot a cinq types de défis - dans :
{
"BotDetection": {
"ActionPolicies": {
"challenge-on-uncertain": {
"Type": "Challenge",
"ChallengeType": "JavaScript"
},
"captcha-gate": {
"Type": "Challenge",
"ChallengeType": "Captcha",
"RedirectUrl": "/captcha"
},
"proof-of-work": {
"Type": "Challenge",
"ChallengeType": "ProofOfWork"
}
}
}
}
Types de défi: Redirect (envoyer à la page de contestationM SK1 Inline (HTML interstitielM SK1 JavaScript (Proof de J.S. Captcha, ProofOfWork (chaud de calculM SK1 Assigner aux points finals via [BotPolicy]:
[BotPolicy("default", ActionPolicy = "challenge-on-uncertain")]
public IActionResult Submit() => Ok();
IP Allow/Deny Lists
Listes globales d'autorisation et de refus pour les IP connues CIDR ranges:
{
"BotDetection": {
"WhitelistedIps": ["203.0.113.10/32", "198.51.100.0/24"],
"BlacklistedIps": ["1.2.3.4", "5.6.7.0/24"]
}
}
Les IP inscrits sur la liste blanche échappent complètement à la détection. Les IP classés en noir sont immédiatement bloqués. Les deux supportent la notation CIDRM SK2
Métrique de télémétrie ouverte
StyloBot expose les métriques par System.Diagnostics.Metrics, compatible avec OpenTelemetry, Prometheus, Grafana, et tout autre .Consommateur de métriques NET
builder.Services.AddOpenTelemetry()
.WithMetrics(metrics => metrics.AddMeter("Mostlylucid.BotDetection"));
Mesures disponibles:
| Mesure métrique | Type MSC2 Ce qu'il mesure MSC3 | |
|---|---|---|
botdetection.requests.total |
Contrôleur | Total des demandes traitées |
botdetection.bots.detected |
Contrôleur | Demandes classées en tant que robots |
botdetection.humans.detected |
Contrôleur | Demandes classées comme des demandes humaines |
botdetection.errors.total |
Contrôleur | Irrégularités de détection des pipelines |
botdetection.detection.duration |
Histogramme | La latence de détection |
botdetection.confidence.average |
Gauge | Confiance moyenne de roulement MSC2 |
botdetection.cache.patterns.count |
Gauge | Cote des patrons cachés |
Ce sont les numéros dont vous avez besoin pour les tableaux de bord, alerting , and capacity planningM SK2 Detection latency histogram allows you set SLOs. BotMNK4human counters give you traffic composition over timeMRK5
Groupe de route par défaut
Appliquer la protection bot à l’ensemble des groupes de route au lieu de répéter par -endpointM SK1
// 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() prend les mêmes paramètres geo/network/confidence que .BlockBots(), mais bloque intentionnellement toujours les scrapers et les bots malicieux au niveau de groupe (non allowScrapers / allowMaliciousBots sur les groupes). WithHumanOnly() est l'équivalent du groupe de .RequireHuman().
Politiques désignées sur l'API minimal
Utilisation .BotPolicy() pour attribuer des politiques d'action désignées aux points finals de l'API minimal - la même chose [BotPolicy] Fait pour 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);
API de rétroaction
Report false positives and negatives back to the system via 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"}'
Le point final indique si la rétroaction représente un mauvais positif ou un mauvais négatif par rapport au résultat de détection actuel.
Portée de confiance avec la signature du HMAC
Lorsque vous utilisez la passerelle YARP, votre backend compte sur les titres de détection en amont. Il s'agit d'une configuration sécuritaireM SK2sensible - vous devez veiller à ce que seulement la passerelles puissent régler ces titres.
Fiducie de base (network-isolement à niveau seulementM SK2
{
"BotDetection": {
"TrustUpstreamDetection": true
}
}
HMAC-fiducie signée M SK1vérification cryptographique):
{
"BotDetection": {
"TrustUpstreamDetection": true,
"UpstreamSignatureHeader": "X-Bot-Signature",
"UpstreamSignatureSecret": "base64-encoded-shared-secret"
}
}
Quand UpstreamSignatureHeader et UpstreamSignatureSecret sont établis, le middleware vérifie un HMAC-SHAM SK1 signature avant de confier les titres en amont.
Utilisez ce dernier pour passerelle personnalisée/intégrations de proxy qui ajoutent des en-têtes de signature. Le robot construit dans la passerelle Stylobot envoie vers l’avant les en-headers de détectionM SK2 , mais n’émet pas encore d’en-tête de signature HMAC.
Headers signés requis:
X-Bot-Signature(base64 HMACM SK2X-Bot-Detection-Timestamp(secondes de l'époque uniqueM SK1 UTC)
Signature du contrat:
payload = X-Bot-Detected + ":" + X-Bot-Confidence + ":" + X-Bot-Detection-Timestampsignature = Base64(HMACSHA256(payload, base64Decoded(UpstreamSignatureSecret)))
Les signatures à l’extérieur d’un 5- fenêtre de replay de minute sont rejetées. Si la signature est manquanteM SK2 invalide , ou expiréeMSC4 les en-têtes en amont sont rejetés et la détection locale complète est effectuée au lieu de celle-ci
Important: Activer la confiance seulement lorsque votre backend est derrière un proxy inverse de confiance. Si l'attaquant peut atteindre directement votre backende, ils peuvent faire des fausses déclarations X-Bot-Detected: false et parpasser toutes les détections. En productionM SK1
- Assurez-vous que le backend n'est pas accessible au public (Network interne de Docker, Kubernetes ClusterIPM SK2
- Écart
X-Bot-*les titres à votre proxy de bord avant qu'ils aient atteint la passerelle - Utiliser la signature HMAC pour la défense-in-de profondeur même avec l'isolement du réseau
Ce qui n'est pas StyloBot
Worth being explicit:
- Ce n’est pas un WAF. StyloBot n’inspecte pas les charges de paye pour l’injection SQL ou XSS. Il identifie qui fait la demande, non Ce qui suit : ils'sentM SK1 Utilisez-le parallèlement à un WAF , non au lieu d’un
- Aucune ferme CAPTCHA. Les politiques de contestation existent, mais la philosophie du design est la détection. précédemment Décision de contester
- Non périmètre-seulementM SK1 La détection est effectuée par -point final avec les politiques de -point terminal. Vous pouvez avoir
/productsautoriser les moteurs de recherche pendant/api/checkoutrequiert des humains. C'est la sémantique du point final, non les règles de pare-feu - Non nuageux-dépendantM SK1 Tout fonctionne lui-même-contained . QdrantM SK2 TimescaleDB, LLM MSC4 tous facultatifsMNK5 Le noyau est composé de deux lignes de code et d'un fichier SQLiteMRK6
- Incertitude-aware Deux cotes indépendantes (probabilité + confianceM SK2 signifie que vous pouvez distinguer "probablement un robot, nousMska5nous sommes sûrsM Ska6de MMska7probably un botM ska8mais nous Mska9nous croyons M Ska10 La plupart des systèmes vous donnent un nombre et nous espérons le meilleur
Quoi' Suivant
La partie 1 a porté sur les raisons pour lesquelles la détection des robots est importante . la partie ♫2 a parlé de l’interface interne du pipeline de détection . Ce poste a couvert l’intégration minimale viable et le chemin d’escalade ♫ - à partir de deux lignes de code jusqu’à une passerelle de production complète ♫
Démarrer:
- NuGet:
dotnet add package Mostlylucid.BotDetection - Gateway Docker:
docker pull scottgal/stylobot-gateway - Documents complets
- Démonstration en direct: StyloBot.net