# **StyloBot: Найпростіше і найпростішим M SK1 Частка МSK2**

*Розпізнавання роботів у компанії не повинно потребувати докторських наук в галузі інфраструктури. МСК1 або тисячі на місяць за використання. МSK2 Дві лінії коду, МСК3 - нуль зовнішніх послуг. , - ви, МSK5 - запускаєте детектори від ( до МSK7 МSK8 - в милісекунді від кожного запиту до кожного кінцевого пункту.*

**[Розумійте деталь 1: StyloBot: Борьба проти Scrapers](https://www.mostlylucid.net/blog/botdetection-introduction)**

**[Читайте частину 2: Як Bots стали розумнішими](https://www.mostlylucid.net/blog/botdetection-part2-signature-pipeline-and-stylobot-architecture)**

**[👉 Подивіться на це в прямому ефірі](https://stylobot.net)** - Реальна система виробництва працює на ранніх стадіях - розпізнавання виходу в лінії на шлюзі

<!--category-- ASP.NET, Bot Detection, Security, Architecture -->
<datetime class="hidden">2026-02-16T10:30</datetime>

[![NuGet](https://img.shields.io/nuget/v/mostlylucid.botdetection.svg)](https://www.nuget.org/packages/mostlylucid.botdetection/)
[![GitHub](https://img.shields.io/github/stars/scottgal/stylobot?style=social)](https://github.com/scottgal/stylobot)
[![Докер](https://img.shields.io/docker/pulls/scottgal/stylobot-gateway)](https://hub.docker.com/r/scottgal/stylobot-gateway)

---


[TOC]

---


## Ідея

Ейнштейн, як здавалося, сказав: "" МСК0 "", """. "" Все має бути зроблене якомога простішим "". МСК2 "", але не простіше. МСК3 "". Це - принцип дизайну "" StyloBot "".

Покритими деталями 1 та МSK1 *чому* питання розпізнавання робота і *як працює детектор*. Цей пост *наскільки малий код ви насправді потребуєте* - і те, як одна і та сама система масштабується від одногоM SK1файлу до повної виробничої шлюги за допомогою TimescaleDB , Квантова векторна пошука МSK3 і ЦП МСК4 тільки класифікація LLM М СК5

Найголовніша думка: **кожен рівень використовує ту ж саму трубку для виявлення**. Ви ' не змінюєте фреймворки, як ви ростете M SK2 Ви ' додаємо зберігання та забагачення навколо одного ядра МSK4

---


## Дві лінії коду

Це абсолютне minimum. Ніяких файлів конфігурації

```csharp
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddBotDetection();       // ← that's line 1

var app = builder.Build();
app.UseBotDetection();                    // ← that's line 2
app.Run();
```

Що ж сталося?

- **21 детектори** зареєстровані: співпадіння шаблонів з користувачамиM SK1 концентрація заголовків , виявлення IP центрів обробки даних МSK3 аналіз поведінки M SK4 відбитки пальців з TLS ( JAMSC6JA4), TCPMska8 відбиток пальця з IP МSK9 HTTPMST10 відбування пальцеві пальціMSL11 аналіз поведінки в буфері CacheMNK12 зворотній зв 'язок щодо поведінки реагуванняMRK13 мультиплексніMEK14 кореляція шарівMSKI15 і більшеMسک16
- **Трубопровод на основі Wave-**: детектори запускаються в хвильях залежності
- **Сховування SQLite**: А `botdetection.db` файл автоматичний- створює для вчиних шаблонів та вагахМSK1 Без налаштуванняM SK2
- **В- пошук подібних процесів**: Індекс HNSW для пошуку схожих Bot-signatur
- **Геуристичний відлік**: МSK1 характеристики, виделені за запитом МSK2 відліковані легким числом вМСК3модельі обробки МСК4

Все це відбувається **під 1 мілісекунд** на попит на товарну апаратність. лише CPU , без GPUM SK2

Кожен запит тепер має результати виявлення, доступні через `HttpContext` rozszerzenia:

```csharp
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()
}));
```

Детекція працює, але нічого не блокує. Ви вирішуєте, що робити з результатамиM SK1

---


## Blokувати всі Bots, Цілковита програма

Якщо ви просто хочете блокувати роботів з вашої усієї програми, - не на один - консоль кінцевого пункту configM SK2 не має атрибутів МSK3 це МSK4 один рядок JSON:

```json
{
  "BotDetection": {
    "BlockDetectedBots": true
  }
}
```

Те, що "'" - це МSK1 Помітні боти над вашим блоком "-" досягають рівня довіри`MinConfidenceToBlock` поганий до `0.8`). пошукові машини МSK1GooglebotM SK2 Bingbot ), передбачування соціальних медіа МSK4FacebookMST5 TwitterM ST6XM st7 і моніторні Botи MST8UptimeRobotМST9 PingdomMst10 дозволяються по замовчуванню мST11 тому що ви майже безперечно хочете такихМ ST12

Або те ж саме в коді, жодного файлу конфігурації не потрібно

```csharp
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
});
```

Це "" МСК0 "". Я не хочу "'", я не хочу думати про це. МСК2 "", режим "" Миск3 "", запуск детектора, робота блокується, МСК5 "", хороші клайлери проходять через "" миск6 "", рухається до "" включного "", "" укінченного "" управління, коли вам це потрібно

---


## Minimal API: Це повний приклад

Тут ' це повний , робочий інтерфейс з пер МSK2 захистом закінчуючих ботів МSK3 Це все `Program.cs`:

```csharp
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();
```

Кожного `.BlockBots()` блоки дзвінків **всі** по замовчуванню типи роботів. Ви обираєте певні типи *всередині* з `Allow*` параметри. ідея - заперечитиM SK1направдуМSK2по замовчуванню

### Типи Bot, які ви можете дозволити

| Параметр МSK1 Що він дозволяє МSK2 Чому ви його використовуєте '
|-----------|---------------|-----------------|
| `allowSearchEngines` | GooglebotM SK1 BingbotМSK2 Yandex | SEO МSK4 ви хочете, щоб вас indeksували
| `allowSocialMediaBots` | Facebook , Twitter/XM SK3 LinkedIn МSK4 Link previewsMSC5 Open Graph cards МSK6
| `allowMonitoringBots` | Робот з підтримкою часу МSK1 Pingdom МSK2 StatusCake | Схвалення здоров 'я
| `allowAiBots` МSK0 GPTBot, ClaudeBotM SK2 Google-Extended MSC4 OptMST5in to AI training |
| `allowGoodBots` | Читачі មតិнокM SK1 перевірювачі зв 'язків | Автоматизація Benign МSK3
| `allowVerifiedBots` | DNSM SK1 перевірені клайлери | Упевнена автоматизація МSK3
| `allowScrapers` | AhrefsBot, SemrushBot | Медоносні горщикиM SK3 Дослідження SEO МSK4
| `allowMaliciousBots` | Знані погані актори МSK1 Медоносні горщики МSK2 дослідження безпеки |
| `minConfidence` | *(тривалістьM SK1* | Заблокувати тільки тоді, коли система дуже надійна |

---


## Контролери MVC: Attributes

Те ж саме розпізнавання трубопроводу, захист через атрибутиM SK1

```csharp
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddBotDetection();
builder.Services.AddControllersWithViews();

var app = builder.Build();
app.UseBotDetection();
app.MapControllers();
app.Run();
```

### Ідентичності

```csharp
[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%" });
}
```

### Географічне блокування мережі &

Вони працюють як з атрибутами MVC, так і з Minimal API-фільтрами. Вони потребують GeoDetection-допомічника для даних сигналу.

```csharp
// 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();
```

---


## За межами блоку

Бінарний блок/дозволяти простий, але обмеженийM SK1 Політики поведінки окремо *те, що ви виявляєте* від *як ви реагуєте*. Визначати стратегії реагування в конфігурації , підпорядковувати їх кінцевим точкам МSK2

### appsettings.json

```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
      }
    }
  }
}
```

### Додавати політику в кінцеві точки

```csharp
// 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();
```

П 'ять типів політики: `Block` МSK0HTTP 403), `Throttle` (запізнення в тайніM SK1 `Challenge` МSK0CAPTCHA/проникновість МSK2за МSK3працездатність ), `Redirect` ( `LogOnly` ( режим затінкуM SK1 Погляньте на [документи про політику дій](https://github.com/scottgal/LLMApi/blob/main/Mostlylucid.BotDetection/docs/action-policies.md) для повного опису.

Схожий на режим стінків - це zalecaний starting point. Розгортання розпізнаванняM SK1 перегляд результатів , шкали відхилення звуку *тоді* почати блокування.

---


## Що ви отримуєте безкоштовно

Кожен запит після `UseBotDetection()` мають ці розширення доступні на `HttpContext`:

```csharp
// 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();
```

Два незалежні показники тут важливі: **ймовірність роботи** ( наскільки імовірно, що це робот ?) і **впевненість в розпізнанні** (скільки впевнена система *людина* (ниска вірогідністьM SK1 високий рівень довіри). Або ви бачите підозрюваний запит, але маєте низький рівень доверості, тому що лише один детектор запустився

---


## Сигнал-Фітрування на основі

За межами типів роботів, StyloBot відображає задруковані сигнали з детекторів M SK1 . Ви можете відфільтрувати кінцеві точки на основі конкретних показників сигналу МSK3 як для Minimal API, так і для MVC

### Minimalний інтерфейс

```csharp
// 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");
```

### МVC

```csharp
[BlockIfSignal(SignalKeys.GeoIsVpn, SignalOperator.Equals, "True")]
public IActionResult Payment() => Ok();

[RequireSignal(SignalKeys.GeoCountryCode, SignalOperator.Equals, "US")]
public IActionResult DomesticOnly() => Ok();
```

### Читання сигналів в лінії

```csharp
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 });
});
```

Справка про повний сигнал: [сигнали та особисті фильтры](https://github.com/scottgal/LLMApi/blob/main/Mostlylucid.BotDetection/docs/signals-and-custom-filters.md).

---


## Випробовування

```bash
# 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
```

І `/bot-detection/check` кінцевий пункт є вашим другом для розвитку. Він повертає кожен сигнал з кожного детектораMSC1 дані про таймінгM SK2 і за вклади детекторів в- так, що ви можете побачити, що відбувається

---


## Як це масштабувати: від файла до повного резервуару

Це найважливіший принцип дизайну. **кожен рівень використовує ту ж саму трубку для виявлення**. Ви ' ніколи не перезаписуєте код захисту

### Тир 1: Самотній МSK1Захищений МSK2Де ви починаєте )

```
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
```

Усі детектори 21 запускаються в хвильі - базуються на трубці МSK2 швидкі \ - \ детекторі маршруту \( \ UserAgent \ МSK5 \ Header \МSK6 \ IP | , \ Peripheral \ TLS \ Fingerprint \ LLS \ ) \ запускають паралельно в Wave \ \ Wave \ Heuristic scoring extracts \ MiSK11 \ features and runs a lightweight scoring model \ MISK12 \ Набуті шаблони продовжують працювати над SQLite крізь рестарти \ miSK13 \ Якщо ви хочете інтерфейсів \ миSK14 \ Część \ МиSK15 \ охоплює архітектуру та потік сигналів у деталях \MISK16 \

**Добре для:** Одинакова програма, <100K запитів /деньM SK3 запускуMSC4

### Зона 2: Dodaj геодетектор

Додайте гео маршрутизацію плюс геодопонувача:

```csharp
builder.Services.AddBotDetection();
builder.Services.AddGeoRoutingWithDataHub(); // free local GeoIP DB (no account)
builder.Services.AddGeoDetectionContributor(options =>
{
    options.FlagVpnIps = true;
    options.FlagHostingIps = true;
});
```

Якщо геолокація IP нова: [Геоіп фон](https://en.wikipedia.org/wiki/Geolocation_software#IP_address) і [Набір даних GeoIP DataHub](https://datahub.io/core/geoip2-ipv4) це хороші точки старту. DataHubCsv завантажує безкоштовну ~27MB IP базу даних на перший запуск і зберігає її на bieżąco щотижняM SK2 Всі пошуки локальні - ні за один МSK4 запроси HTTP дзвінків M SK5 Для міста MSC6 рівень точності , використання [MaxMind GeoLite2](https://dev.maxmind.com/geoip/geolite2-free-geolocation-data/).

Тепер ви отримуєте 20+ гео-сигнал МSK1 країна МSK2 VPN , прокси \ , \ Tor \, \ Detection of datacenter \ МSK6 \ and bot origin verification \ ( \ Googlebot from a Chinese datacenter `BlockCountries`, `BlockVpn`, `BlockDatacenter`, `BlockTor` параметри активують.

### Уровни 3: PostgreSQL + TimescaleDB

Замінити SQLite з PostgreSQL для багатого-сервера спільного навчання і додавати [TimescaleDB](https://docs.timescale.com/) (а ПостгреSQL - розширення для часу -серійні дані МSK2 для аналізу

```csharp
builder.Services.AddBotDetection();
builder.Services.AddStyloBotDashboard();
builder.Services.AddStyloBotPostgreSQL(connectionString, options =>
{
    options.EnableTimescaleDB = true;
    options.RetentionDays = 90;
    options.CompressionAfter = TimeSpan.FromDays(7);
});
```

```yaml
# 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 дає вам гіперстабільне відокремлення, автоматичне стиснення M SK1 скорочення зберігання після МSK2 днів ), безперервні агрегати для суб- мілісекундні пошуки на панелі доти МSK5 та політики збереженняMSC6

**Добре для:** >100K запитів/деньM SK2 багатосерверів , потребна панель з аналізом МSK4

### Уровни 4: Полна партія МSK1 Перехідник МSK2 Квартира + ЛЛМ

```
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)
```

Вхід - автономний контейнер Docker (`scottgal/stylobot-gateway`), що запускає розпізнавання на всіх потоках і передає результати як HTTP заголовки . Ваша програма читає заголовок МSK2 **не потрібні SDK, будь-яка мова**МSK0 Якщо "похідник МSK2 незнайомий , подумайте[зворотній прокси](https://en.wikipedia.org/wiki/Reverse_proxy) що сидить перед вашим приложением і додає безпеки

```yaml
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
```

Ваша програма довіряє воротам

```csharp
// ASP.NET Core
builder.Services.Configure<BotDetectionOptions>(o => o.TrustUpstreamDetection = true);
```

Або читати заголовки безпосередньо на будь-якому мові:

```python
# 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')
```

```javascript
// 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' });
});
```

**Заголовки, які відправляє порт:**

| Заголовок МSK1 До прикладу
|--------|---------|---------|
| `X-Bot-Detected` | `true` | BotM SK1 людська класифікація |
| `X-Bot-Confidence` | `0.91` | Упевненість в розпізнанні МSK1
| `X-Bot-Detection-Probability` | `0.87` | Ймовірність Bot
| `X-Bot-Type` | `Scraper` | Категорія Bot
| `X-Bot-Name` | `AhrefsBot` | Визначений робот МSK1
| `X-Bot-Detection-RiskBand` | `High` | класифікація ризику МSK1

### Що додає кожне з компонентів

| Komponenт МSK1 Що він робить МSK2 Потрібно ? мSK4
|-----------|-------------|-----------|
| **TimescaleDB** МСК0 ЧасМSK1серійні аналізи, стиснутий складM SK3 послідовні агрегатиМСК4 правила збереження МСК5 Рекомендується для виробництва МСК6
| **Кдрант** | Поиск векторної подібності - знаходить роботів навіть, коли вони обертаються
| **Лалам-Шарп** | Процесор - Лише LLM для набору кластерів і синтезу класифікації роботів | |
| **Caddy/Nginx** | Завершення TLSM SK1 статичні файли | Ваший існуючий зворотній прокси МSK3
| **Перехідник** | Центризована розпізнавання для мультиплекснихM SK1app або не--.NET засадників | Для мультиплітиннихМSK4сервисних архітектур МSK5

### Вибір вашого Tier

```
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)
```

Переміщення між рівнощами - це зміна rejestracji DI. Ваш кінцевий код захисту M SK1 `[BlockBots]` атрибути, `.BlockBots()` Filtrи, `context.IsBot()` перевіряє - залишається точно таким же

---


## Enterprise Hooks

Два "-" лінійні налаштування є початковою точкою МSK1 . Тут, МSK2 , видно, що ще вбудовано для використання для виробництва.

### Response Headers for Debugging

Ввімкніть заголовки розпізнавання глобально, щоб ви могли перевірити поведінку, не натискаючи на кінцеві точки діагностики:

```json
{
  "BotDetection": {
    "ResponseHeaders": {
      "Enabled": true,
      "HeaderPrefix": "X-Bot-",
      "IncludeConfidence": true,
      "IncludeDetectors": true,
      "IncludeProcessingTime": true,
      "SkipPaths": ["/health"]
    }
  }
}
```

Кожна реакція отримує `X-Bot-Detected`, `X-Bot-Confidence`, `X-Bot-Processing-Ms`, і т.д. . корисне для прийняття рішень щодо маршрутізації в CaddyM SK2Nginx, та для відладів у devMSC4 Виключити виробництво або обмежувати до довірливих мережМSK5

### Політики виклику (Різниця перед блоком МSK1

Don' не блокує невпевненості M SK1 завдання замість . StyloBot має п 'ять моделей випробувань

```json
{
  "BotDetection": {
    "ActionPolicies": {
      "challenge-on-uncertain": {
        "Type": "Challenge",
        "ChallengeType": "JavaScript"
      },
      "captcha-gate": {
        "Type": "Challenge",
        "ChallengeType": "Captcha",
        "RedirectUrl": "/captcha"
      },
      "proof-of-work": {
        "Type": "Challenge",
        "ChallengeType": "ProofOfWork"
      }
    }
  }
}
```

Типи викликів: `Redirect` (отправити на сторінку виклику `Inline` (HTML інтерститал МSK1 `JavaScript` (ДС доказM SK1в МSK2праця), `Captcha`, `ProofOfWork` ( обчислювальний викликM SK1 Додавати до кінцевих точок за допомогою `[BotPolicy]`:

```csharp
[BotPolicy("default", ActionPolicy = "challenge-on-uncertain")]
public IActionResult Submit() => Ok();
```

### Дозволяти IP/Заперечувати листи

Глобальна lista дозволу та відмови від відомих IP і [Інформаційний ресурс](https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing) діапазони:

```json
{
  "BotDetection": {
    "WhitelistedIps": ["203.0.113.10/32", "198.51.100.0/24"],
    "BlacklistedIps": ["1.2.3.4", "5.6.7.0/24"]
  }
}
```

Уявлення про IP, що знаходяться на білому списку, повністю перестає виявлятися. Вявлення, що IP, які знаходяться на чорному списку, миттєво блокуютьсяM SK1 Обидві системи підтримують нотацію CIDR.

### Метріка OpenTelemetry

StyloBot виявляє метрики за допомогою `System.Diagnostics.Metrics`, здатний [Відкрита телеметрія](https://opentelemetry.io/docs/), [Прометеус](https://prometheus.io/docs/introduction/overview/), [Графана](https://grafana.com/docs/), та будь-які МSK1NET метрики споживачаM SK2

```csharp
builder.Services.AddOpenTelemetry()
    .WithMetrics(metrics => metrics.AddMeter("Mostlylucid.BotDetection"));
```

**Доступні метрики:**

МSK0 Метрічний | Тип МSK2 Як він вимірює |
|--------|------|-----------------|
| `botdetection.requests.total` | Переводник МSK1 Общее оброблене число запитів МSK2
| `botdetection.bots.detected` | Перерахунок МSK1 Запити, класифіковані як Bots |
| `botdetection.humans.detected` | Переводник МSK1 Запити, класифіковані як людські МSK2
| `botdetection.errors.total` | Перерахунок МSK1 Виявление помилок в трубопроводі МSK2
| `botdetection.detection.duration` | Хістограма МSK1 Затримка виявлення МSK2msM SK3 |
| `botdetection.confidence.average` | Гаудж МSK1 Середня впевненість в рухі |
| `botdetection.cache.patterns.count` | Gauge МSK1 Число зашифрованих шаблонів |

Це ті цифри, які вам потрібні для панелі приладів, попередженняM SK1 та планування пропускної спроможності

### Погані маршрути для груп

Застосувати захист для роботів на всіх маршрутних групах, замість того, щоб повторювати в один раз

```csharp
// 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()` бере ті ж самі гео/мережіМSK1параметри впевненості, що й `.BlockBots()`, але навмисно завжди блокує скрукерів та злонадійних роботів на груповому рівні `allowScrapers` / `allowMaliciousBots` на групи). `WithHumanOnly()` є еквівалентом групи `.RequireHuman()`.

### Наименовані правила на Minimal API

Використовувати `.BotPolicy()` надати названі правила дій кінцевим точкам Minimal API - те ж саме. `[BotPolicy]` робить для MVC:

```csharp
// 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 зворотнього зв 'язку

Сповісти про хибні позитиви і негативи до системи через `POST /bot-detection/feedback`:

```bash
# 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"}'
```

Даний кінцевий пункт показує, чи зворотній зв 'язок є хибним позитивним або хибnym негативним відносно результату bieżąceго виявлення.

### Перехідна межа довіри з підписом HMAC

Коли ви використовуєте YARP-шлюзник, ваш зворотній бік довіряє заголовкам, що відповідають за попереднє виявлення . Це конфіденційне налаштування МSK2чуттєве налаштування M SK3 ви повинні впевнитись, що лише шлюзень може налаштувати ці заголовки .

**Базова довіра (мережаM SK1виключення лише на рівні МSK2**

```json
{
  "BotDetection": {
    "TrustUpstreamDetection": true
  }
}
```

**HMAC-подписана довіра МSK1шифрографічна перевіркаM SK2**

```json
{
  "BotDetection": {
    "TrustUpstreamDetection": true,
    "UpstreamSignatureHeader": "X-Bot-Signature",
    "UpstreamSignatureSecret": "base64-encoded-shared-secret"
  }
}
```

Коли `UpstreamSignatureHeader` і `UpstreamSignatureSecret` встановлено, посередник перевіряє [HMAC-SHAM SK1](https://datatracker.ietf.org/doc/html/rfc2104) підпис перед тим, як повірити в зворотньі заголовки.

Використовуйте це зараз для **custom gateway/proxy integrations** що додають заголовки для підпису. збудованийM SK1 в порті Stylobot передувається до Botа - заголовок для відбору МSK3 але ще не видає заголовків для підписів HMAC

Потрібні підписані заголовки:

- `X-Bot-Signature` ( база МSK1 ГМСК МSK2
- `X-Bot-Detection-Timestamp` (Сі секунди епохи ЮніксМSK1 UTCM SK2

Подписання контракту:

- `payload = X-Bot-Detected + ":" + X-Bot-Confidence + ":" + X-Bot-Detection-Timestamp`
- `signature = Base64(HMACSHA256(payload, base64Decoded(UpstreamSignatureSecret)))`

Signatures outside a 5-minute replay window are rejected

**Важливо:** Увімкніть довіру тільки тоді, коли ваша заставка стоїть за довіреним зворотним проксим. Якщо атакующий може дістатися до вашої заставки безпосередньо, вони можуть обманювати `X-Bot-Detected: false` і обходяють всі розпізнавання. В процесі виробництваM SK1

- Упевниться, що зворотній бік не доступний для публічного доступу. (Докерна внутрішня мережаM SK1 Kubernetes ClusterIP)
- Стріп `X-Bot-*` заголовки у вашому прокси на краю перед тим, як вони досягнуть ворота
- Використовуйте HMAC для захисту

---


## Що таке StyloBot?

Досить чіткого:

- **Не WAF.** StyloBot не перевіряє навантаження для введення SQL або XSS, *хто* робить запит, не *що* вони' надсилаютьM SK1 Використовуйте його поряд з WAF , не замість одного
- **Не ферма CAPTCHA.** Політики виклику існують, але філософія дизайну полягає в виявленні. Це означає, що ви маєте справу з *до цього* вирішувати, чи кидати виклик
- **Не периферійний- тількиM SK1** Виявление запускається за допомогою policies per-endpoint з за допомогою per -end point `/products` дозволити пошуковим машинам `/api/checkout` вимагає людей. Це концепційна семантика , не правила брандмауэра .
- **Не хмари-независиміM SK1** Все працює самостійно-вміщується. QdrantM SK2 TimescaleDB , LLM МSK4 все опціональноMSC5 Корінь - дві лінії коду і файл SQLiteMسک6
- **Невизначеність-свідомістьM SK1** Два невід 'ємні оцінки (можливість + впевненість МSK2 означає, що ви можете відокремити МSK3 ймовірно бота \, ми \ ' впевнені \ МSK6 \ від мSK7 веројатно ботан \МSK8 \, але ми | ' \ догадуємо \ мSK10 \ Більшість систем дають вам один номер і сподіваються на найкращу \ . \

---


## Що Next

Частка 1 описувала, чому важливо розпізнавати роботів . Część МSK2 описує інтерфейси розпізнавання трубопроводу МSK3 Цей пост охопив мінімальну життєздатну інтеграцію та шлях масштабування M SK4 від двох ліній коду до повної виробничої шлюпки .

**Почнемо:**

- NuGet: `dotnet add package Mostlylucid.BotDetection`
- Gateway Docker: `docker pull scottgal/stylobot-gateway`
- [Повні доки](https://github.com/scottgal/LLMApi/tree/main/Mostlylucid.BotDetection/docs)
- [Жива демонстрація: StyloBot.net](https://stylobot.net)