स्टेलोबोट का पता लगाने वाला इंजन ASP है।
**
github.com/scottgal/stylobot-goSDK,github.com/scottgal/caddy-stylobotप्लगइन, औरMostlylucid.BotDetection.Sidecarकन्टेनर शीघ्र प्रकाशित होगा** नीचे सब कुछ उन सतह का वर्णन करता है जो वे प्रदर्शित करेंगे
स्टिलियोबोट रिलेस शृंखला
- व्यवहार, पहचान नहीं: क्यों StyloBot ग्राहक व्यवहारिक रूप से मॉडल करता है
- व्यवहार-Aware ASP.NET UIसर्वर : NET अनुप्रयोगों के लिए प्रदान किया गया सतह
- लंबे समय तक चलाने वाले नेट सेवाओं में असीमित विकास का पता लगाना और स्थिर करना: विश्वसनीयता अनुशासन जो उत्पादन में इंजन को नीरस बनाए रखता है
- व्यवहार-Aware TypeScript UI: Express , Fastify, और ब्राउज़र घटक
- साइडकार वास्तुकला: इस लेख
- तेजी से सीखनाअनुकूलन सीखने की प्रणाली
- उस चीज़ का परीक्षण जो सफल नहीं हो रही है: सत्यापन अनुशासन
- स्टिलियोएक्सट्रैक्ट - एक स्थानीय सीखने के HTML को मार्कडाउन रूपांतरक में: एचटीएमएल\→\मार्कडाउन परत जो डिटेक्टर के साथ जोड़ता है,\walker bug lucidVIEW पकड़ा\M SK3\ और कुत्तेfood लूप कि यह ईमानदार बना
एक उल्टा प्रॉक्सी बॉट पता चलाने के लिए स्पष्ट स्थान है। अलग-अलग करना जो अनुरोध कर रहा है के आधार पर | . | एक गेटवे जो सीधे ब्लॉक करता है |; | अधिकांश अनुप्रयोगों को वास्तव में एक निर्णय की आवश्यकता होती है, जिस पर वे एक ही समय में कई तरह से कार्य कर सकते हैं
छेदगाड़ी पैटर्न दो चिंताओं को अलग करता है। तेजी से सीखनादो स्थानीय नेटवर्क पर संचार करते हैं. एक ही होस्ट या एक ही पोड.
यह नया नमूना नहीं है प्रेषक प्रॉक्सी सेवा के लिए यह ठीक करता है-मेश संबंधित M SK1mTLS, रिट्रीस दमर यह राज्य और pub के लिए करता है ओपन टेलीमीटरी कलेक्टर टेलीमीटरी के लिए यह करता है।
वैकल्पिक है गेटवे में सीधे पता लगाने को कम्पाइल करना।
इस जटिलता के एक इंजन के लिए भी यथार्थ नहीं है . स्टिलोबोट में चार निष्पादनों पर \49\सूचक संगठित हैं लहरें (अगामी तरंगों को तभी चलाया जाता है जब पहले से आने वाले संकेत इसे गारंटी देते हैं। मार्कोव श्रृंखला वेक्टर एक 129-आयामी अंतरिक्ष में\ .\ A Markov श्रृंखला केवल एक संभाव्यता मॉडल के ऊपर है & # 160; "\ given the last thing this session did\ M SK3\ what comes next\ ?",\ and 129\ dimensions captures enough page\ MSC6\ transition shape to tell humans and bots apart\ MST7\ It runs लीडन समुदाय पहचान उन सदिशों के ऊपर-:, एक ग्राफ, -, समूहबद्ध एल्गोरिथ्म जो सत्रों को समान रूप से व्यवहार करते हैं समूहित करता है,,, जो कि है StyloBot एक बॉट नेटवर्क को पता लगाता है जब व्यक्तिगत सत्र ठीक दिखते हैं तब भी।
एक पार्श्वगाड़ी प्रत्येक अवयव को ऐसा करने देता है जो यह अच्छी है
graph TD
classDef input fill:none,stroke:#3b82f6,stroke-width:2px
classDef async fill:none,stroke:#a855f7,stroke-width:2px
classDef good fill:none,stroke:#22c55e,stroke-width:2px
classDef store fill:none,stroke:#f59e0b,stroke-width:2px
GW["Gateway<br/>Caddy / YARP / nginx"]:::input
SD["StyloBot Sidecar · ASP.NET Core<br/>gRPC :5090 · REST :5091<br/>≤50ms per Detect RPC"]:::async
APP["Upstream Application<br/>Node / Go / ASP.NET<br/>reads req.stylobot.verdict"]:::good
DB[("SQLite<br/>sessions · signatures · reputation")]:::store
GW --> SD
SD <--> DB
GW --> APP
गेटवे छेदगाड़ी को कॉल करता है, परिणाम HTTP हेडर के रूप में इंजेक्शन करता है।
Mostlylucid.BotDetection.Sidecar एक न्यूनतम ASP है
/api/v1/* अंतबिन्दुजीआरपीसी Google में विकसित एक उच्च निष्पादन दूरस्थ प्रक्रिया कॉल फ्रेमवर्क है प्रोटोकॉल बफर अपने तार प्रारूप के रूप में (protobuf) एक संक्षिप्त द्विआधारी एनकोडिंग जो JSON की तुलना में तार पर क्रमबद्ध करने में तेजी से और छोटा होता है।
इंटरफेस एक में परिभाषित किया गया है .proto फ़ाइल. उस फ़ाइल से कूट जनरेटर किसी भी समर्थित भाषा में टाइप किए गए क्लाइंट और सर्वर स्टब्स को उत्पन्न करते हैं .proto कोई भी भाषा जो जीआरपीसी क्रियान्वयन के साथ है, साइडकार को बुला सकता है
सेवा में तीन आरपीसी हैं
service DetectionService {
rpc Detect(DetectRequest) returns (DetectResponse);
rpc DetectBatch(DetectBatchRequest) returns (DetectBatchResponse);
rpc RenderWidget(RenderWidgetRequest) returns (RenderWidgetResponse);
}
Detect per है। - request hot path; .; Pass it method; ,; path;,; headers; MSC4; remote IP; M SK5; and optional TLS fingerprint data; MRK6; It runs the wave pipeline; (; only the detectors that the request; MST8; signals warrant; M ST9; updates the session vector; Mst10; scores against the reputation store; M st11; and returns a verdict.
DetectBatch अनुक्रमिक रूप से बहुविध अनुरोध चलाता है. लॉग रिप्ले और ऑफ़लाइन विश्लेषण के लिए उपयोग किया जाता है
RenderWidget एक तरल टेम्प्लेट स्ट्रिंग को स्वीकार करता है।
चित्र से पहले एक त्वरित शब्दकोश, क्योंकि ये नाम प्रकट होंगे
request.ip.is_datacenter, detection.useragent.confidence). डिटेक्टर इसके लिए संकेत लिखते हैं, ; बाद में एक ही तरंग के डिटेक्टर उन्हें पढ़ते हैं।HttpContext जीआरपीसी सेवा प्रोटो अनुरोध क्षेत्रों से बनाता है HttpContextएक संश्लेषण करने से एक जीआरपीसी कॉल के अंदर एक ही इंजन बिना बदले चलाता हैsequenceDiagram
participant GW as Gateway (Caddy)
participant SD as gRPC Service
participant ORC as BlackboardOrchestrator
participant DET as Detectors (up to 49, 4 waves)
participant DB as SQLite
GW->>SD: Detect RPC { method, path, headers, remoteIp }
SD->>ORC: DetectAsync(syntheticHttpContext)
ORC->>DET: Wave 0 - Identity + ContentSequence
ORC->>DET: Wave 1 - Fast path <1ms: UA, Header, IP, Heuristic ...
ORC->>DET: Wave 2 - Session vectors, Behavioural waveform
ORC->>DET: Wave 3 - Slow path: DNS, advanced fingerprinting
DET-->>ORC: DetectionContributions (signals, confidence deltas)
ORC->>DB: update session vector and reputation score
DB-->>ORC: ok
ORC-->>SD: AggregatedEvidence { botProbability, riskBand, ... }
SD-->>GW: DetectResponse { isBot, riskBand, recommendedAction, ... }
पूरी पाइपलाइन एकल जीआरपीसी कॉल के अंदर चलती है
गो में गेटवे कोड ASP को आयात नहीं कर सकता हैgithub.com/scottgal/stylobot-goएक टाइप्ड इंटरफेस प्रदान करता है जो कलर से उत्पन्न प्रोटोबॉफ़ प्रकारों को पूरी तरह छुपाता है
प्रोटोबॉफ़-generated code is verbose and has an unusual APIRISK_BAND_HIGH, नहीं "High"). क्षेत्र नाम ऊंट हैं कुछ जेनेरेटरों में केस और सांप के साथ-साथ
SDK एक बार सीमा पर (प्रो एनम को कैनोनिक स्ट्रिंगों में अनुवाद करता है
// the only interface you depend on: no proto imports required
type Client interface {
Detect(ctx context.Context, req DetectRequest) (*Verdict, error)
DetectBatch(ctx context.Context, reqs []DetectRequest) ([]*Verdict, error)
RenderWidget(ctx context.Context, req RenderRequest) (*RenderResponse, error)
Close() error
}
DetectRequest और Verdict सादा Go स्ट्रक्चर हैं
type DetectRequest struct {
Method string
Path string
Headers map[string]string
RemoteIP string
Protocol string // "http" or "https"; defaults to "https" if empty
TLS *TLSInfo
}
type Verdict struct {
IsBot bool
BotProbability float32
Confidence float32
BotType string // "AiBot", "Scraper", "GoodBot", ...
BotName string
RiskBand string // "VeryLow", "Low", "Elevated", "Medium", "High", "VeryHigh"
RecommendedAction string // "Allow", "Throttle", "Challenge", "Block"
ThreatScore float32
ThreatBand string
ProcessingTimeMs float32
DetectorsRun int32
Reasons []Reason
}
एक क्लाइंट बनाना और पता चलाना
import (
stylobot "github.com/scottgal/stylobot-go"
"context"
"time"
)
client, err := stylobot.NewClient(
"localhost:5090",
stylobot.WithTimeout(50 * time.Millisecond),
stylobot.WithAPIKey(os.Getenv("SB_API_KEY")),
)
if err != nil {
log.Fatal(err)
}
defer client.Close()
verdict, err := client.Detect(ctx, stylobot.DetectRequest{
Method: r.Method,
Path: r.URL.RequestURI(),
RemoteIP: r.RemoteAddr,
Headers: extractHeaders(r),
Protocol: "https",
})
if err != nil {
// fail open: log and continue
log.Printf("stylobot detect failed: %v", err)
return next(w, r)
}
if verdict.RecommendedAction == "Block" {
http.Error(w, "Forbidden", http.StatusForbidden)
return
}
grpc.NewClient एक क्लाइंट चैनल बनाता है लेकिन तत्काल टीसीपी कनेक्शन स्थापित नहीं करता।
यह HTTP क्लाइंटों से भिन्न है, जहाँ आप आमतौर पर निर्माण पर जुड़ते हैं जीआरपीसी गो दस्तावेज़ीकरण जीवन चक्र को विस्तृत रूप से शामिल करता है
WithTimeout पर NewClient प्रत्येक के भीतर लागू एक डिफ़ॉल्ट per-call तारीख़ सेट करता है Detect कॉल. यदि आपका कॉल कोड |( |या Caddy प्लगइन जैसे मिडवेअर | ) |आगत अनुरोध से सीमाबद्ध संदर्भ | МSK3 |से पहले समाप्त होने वाले किसी भी समयावधि को लागू करता है WithTimeout से NewClient और प्लगइन को इसे नियंत्रित करने दें NewClient जैसा कि ऊपर दिखाया गया है
कैडीCity name (optional, probably does not need a translation) एक Go-आधारित वेब सर्वर और स्वचालित HTTPS के साथ उल्टे प्रॉक्सी है एक्सकैडी एक अनुकूल Caddy द्विआधारी बनाने के लिए जो आपके प्लगइनों को शामिल करता है.so रनटाइम पर लोड फ़ाइलें). स्टेलोबोट प्लगइनgithub.com/scottgal/caddy-stylobotप्रत्येक अनुरोध पर गो एसडीके को कॉल करने वाले मध्यवेयर हैंडलर को पंजीकृत करता है
Caddyfile विन्यास:
{
order stylobot before respond
}
:80 {
stylobot {
endpoint localhost:5090 # gRPC host:port of the sidecar
timeout 50ms # per-request deadline; fails open on expiry
# on_block 503 # optional: change the block status code (default: 403)
}
reverse_proxy upstream:3000
}
प्लगइन प्रत्येक अग्रेषित अनुरोध पर नौ निर्णायक हेडर डालता है
हेडर
|---|---|
| X-StyloBot-IsBot | isBot 0 bool
| X-StyloBot-Probability | botProbability (0.0-1.0) |
| X-StyloBot-Confidence | confidence (0.0-1.0) |
| X-StyloBot-BotType | AiBot, Scraper, GoodBot |
| X-StyloBot-BotName | GPTBot, Googlebot |
| X-StyloBot-RiskBand | VeryLow ... VeryHigh |
| X-StyloBot-Action | Allow / Throttle / Challenge / Block |
| X-StyloBot-ThreatScore संख्यात्मक
| X-StyloBot-ThreatBand | None ... Critical |
जहाँ अनुरोध करता है isBot=true और Action=Block एक 403 के साथ गेटवे पर रोके जाते हैं और कभी ऊपरी धारा तक नहीं पहुँचते हैं Throttle या Challenge सिफारिश) सभी नौ शीर्ष intact के साथ अग्रेषित किया जाता है
on_block जब गेटवे ब्लॉक करता है तब उपयोग की जाने वाली स्थिति कोड बदलता है on_block 503 scrapers में पुनः प्रयास तर्क को दबाने के लिए जो 403 को पुनः प्रयास योग्य के रूप में देखता है
flowchart TD
classDef input fill:none,stroke:#3b82f6,stroke-width:2px
classDef async fill:none,stroke:#a855f7,stroke-width:2px
classDef good fill:none,stroke:#22c55e,stroke-width:2px
A["1. Strip inbound X-StyloBot-* headers"]:::input
B["2. context.WithTimeout(r.Context(), 50ms)"]:::input
C["3. sbClient.Detect(ctx, DetectRequest)"]:::async
D{error?}
E["log warn - fail open<br/>forward unchanged"]:::good
F["4. injectHeaders<br/>X-StyloBot-IsBot, Probability, Confidence,<br/>BotType, BotName, RiskBand, Action,<br/>ThreatScore, ThreatBand"]:::input
I["next.ServeHTTP - forward to upstream<br/>with all verdict headers injected"]:::good
A --> B --> C --> D
D -->|yes| E --> I
D -->|no| F --> I
चरण 1, स्ट्रिप इनबाउंड हेडर एक ग्राहक जो जानता है कि X-StyloBot-* हेडर नाम स्वंयः---एक अनुकूल निर्णय दे सकता है और यह असफलता से बच सकता है।
चरण 2, संदर्भ समय-सीमा समय समाप्ति से व्युत्पन्न है r.Context() उपयोग context.WithTimeout (जो एक सापेक्ष अवधि लेता है context.WithDeadline एक पूर्ण समय लेता है r.Context() बजाय context.Background() कुंजी बिंदु है
चरण 3 और 4, पता लगाना और इंजेक्शन करें नौ निर्णायक क्षेत्र नौ हो जाते हैं X-StyloBot-* हेडर. हेडर ब्लॉक जाँच से पहले सेट किए जाते हैं styloBotMiddleware({ mode: 'headers' }) सभी non-blocked अनुरोधों के लिए isBot=true और recommendedAction=Block गेटवे पर 403 के रूप में लौटाया जाता है
क्रियान्वयन
// from sdk/caddy/stylobot.go
func (s *StyloBot) ServeHTTP(w http.ResponseWriter, r *http.Request, next caddyhttp.Handler) error {
for _, name := range stylobotHeaders {
r.Header.Del(name)
}
ctx, cancel := context.WithTimeout(r.Context(), s.timeout)
defer cancel()
verdict, err := s.sbClient.Detect(ctx, sb.DetectRequest{
Method: r.Method,
Path: r.URL.RequestURI(),
RemoteIP: ExtractIP(r),
Protocol: r.Proto,
Headers: ExtractHeaders(r),
})
if err != nil {
s.logger.Warn("stylobot detect failed, failing open", zap.Error(err))
return next.ServeHTTP(w, r)
}
injectHeaders(r, verdict)
if verdict.IsBot && s.OnBlock > 0 && verdict.RecommendedAction == "Block" {
http.Error(w, "Forbidden", s.OnBlock)
return nil
}
return next.ServeHTTP(w, r)
}
केडीई प्लगइन को द्विआधारी में कम्पाइल किया जाना चाहिए एक्सकैडीएकीकरण परीक्षणों में Dockerfile पैटर्न दिखाता है
# from tests/integration/caddy-sidecar/Dockerfile
FROM caddy:2-builder AS builder
WORKDIR /build
COPY sdk/caddy/ caddy-plugin/
COPY sdk/go/ go/
WORKDIR /build/caddy-plugin
RUN xcaddy build \
--with github.com/scottgal/caddy-stylobot=/build/caddy-plugin \
--with github.com/scottgal/stylobot-go=/build/go
FROM caddy:2
COPY --from=builder /build/caddy-plugin/caddy /usr/bin/caddy
COPY tests/integration/caddy-sidecar/Caddyfile /etc/caddy/Caddyfile
प्लगइन go.mod समाहित है:
replace github.com/scottgal/stylobot-go => ../go
यह कहता है कि जब आप देखते हैं Go औजार श्रृंखला " stylobot-goमॉड्यूल प्रॉक्सी से लाने के बजाय स्थानीय निर्देशिका का उपयोग करें go build और go test प्लगइन निर्देशिका में
xcaddy अपने निर्माण के लिए एक नया अस्थायी जा मॉड्यूल बनाता है replace प्लगइन से निर्देश go.mod. बिना दूसरे --with तर्क, xcaddy डाउनलोड करने की कोशिश करेगा stylobot-go से pkg.go.dev (जहां यह अभी प्रकाशित नहीं हुआ है
--with module=path तर्क xcaddy's एक का मूल समकक्ष है replace निर्देशिका: यह निर्माण समय पर स्थानीय निर्देशिका में एक मॉड्यूल पथ का नक्शा बनाता है
RenderWidget एक जीआरपीसी आरपीसी है जो एक तरल टेम्प्लेट स्ट्रिंग को स्वीकार करता है।
तरल Shopify द्वारा बनाया गया एक टेम्पलेटिंग भाषा है। तरल, एक उच्च
पार्श्वगाड़ी कार्यान्वयन
// from src/Mostlylucid.BotDetection.Sidecar/Services/DetectionGrpcService.cs
private static readonly FluidParser Parser = new(); // static, shared, compiled templates cached
public override async Task<Proto.RenderWidgetResponse> RenderWidget(
Proto.RenderWidgetRequest request, ServerCallContext context)
{
if (!Parser.TryParse(request.Template, out var template, out var error))
return new Proto.RenderWidgetResponse { Success = false, Error = error };
var ctx = new TemplateContext();
if (request.Verdict is { } v)
{
ctx.SetValue("isBot", v.IsBot);
ctx.SetValue("botProbability", (double)v.BotProbability);
ctx.SetValue("botType", v.BotType);
ctx.SetValue("botName", v.BotName);
ctx.SetValue("riskBand", v.RiskBand.ToString());
ctx.SetValue("recommendedAction", v.RecommendedAction.ToString());
ctx.SetValue("threatScore", (double)v.ThreatScore);
ctx.SetValue("threatBand", v.ThreatBand.ToString());
}
foreach (var kv in request.Vars)
ctx.SetValue(kv.Key, kv.Value);
var html = await template.RenderAsync(ctx);
return new Proto.RenderWidgetResponse { Html = html, Success = true };
}
तरल.Core एक आंतरिक कम्पाइलित टेम्प्लेट कैश रखता है FluidParser स्थिर है और सभी जीआरपीसी कॉलों में साझा है
नोड StyloBotGrpcClient.renderWidget() उदाहरण और पूरा टेम्प्लेट चल संदर्भ में हैं टाइपस्क्रिप्ट एसडीके अनुच्छेद.
इसे Go से बुला रहे हैं
rendered, err := client.RenderWidget(ctx, stylobot.RenderRequest{
Template: `{% if isBot %}<p class="warning">Bot: {{ botType }}</p>{% endif %}`,
Verdict: verdict,
Vars: map[string]string{"locale": "en-GB"},
})
if err == nil && rendered.Success {
fmt.Fprint(w, rendered.HTML)
}
टेम्प्लेट वाक्य संरचना समान है चाहे आप कॉल करें RenderWidget से Go, Node, या उपयोग <sb-widget> ब्राउज़र में
graph LR
classDef input fill:none,stroke:#3b82f6,stroke-width:2px
classDef async fill:none,stroke:#a855f7,stroke-width:2px
classDef good fill:none,stroke:#22c55e,stroke-width:2px
classDef store fill:none,stroke:#f59e0b,stroke-width:2px
INT([Internet])
CF["Cloudflare<br/>Tunnel / CDN"]
CA["Caddy<br/>+ caddy-stylobot"]:::input
SD["StyloBot Sidecar<br/>:5090 gRPC · :5091 REST"]:::async
WEB["Upstream App<br/>Node / Go / ASP.NET"]:::good
DB[("SQLite<br/>sessions · reputation")]:::store
INT --> CF --> CA
CA -->|"gRPC Detect<br/>≤50ms"| SD
SD <-->|"persist"| DB
CA -->|"X-StyloBot-* headers"| WEB
WEB -->|"/_stylobot/partials/render<br/>(widget rendering)"| SD
उपप्रणाली अनुप्रयोग छेदकार को सीधे विजेट रेंडरिंग के लिए बुलाता है, गेटवे को पार करने के लिए
Caddy प्लगइन, नोड मिडिल्डवेयर, और Go SDK सभी खोलने में विफल होते हैं।
व्यापार से यह एनकोड करता है। legitimate traffic blocking because detection is unavailable worse than missing bot traffic during a sidecar outage
जारी जारी जारी है
कार्यान्वयन के लिए स्रोत github.comM SK1scottgal/stylobot. लाइव इंजन stylobot.net.
© 2026 Scott Galloway — Unlicense — All content and source code on this site is free to use, copy, modify, and sell.