最新资讯
dev.to 为 CI/CD 构建 AI 质量门禁 dev.to Kakao 发布面向 AI Agent 的决策模型 Kanana-2-v-decide computerworld.com Microsoft 对 Copilot Chat 企业用户扩大未公开的使用限制 pub.towardsai.net Google 发布 Gemini 4 Carbon:主打网络安全能力的前沿模型 gradientflow.com METR 研究:AI 正在加速构建 AI 的团队本身 www.infoq.com GitLab 19.5 将 Agentic 开发纳入 DevOps 平台的治理体系 aiacceleratorinstitute.com 研究:AI Agent 的复杂流程编排可能反而是问题所在 pub.towardsai.net MongoDB 推出 Vercel AI SDK 集成:为 AI 应用提供持久记忆 thenewstack.io Google 捐出被 Anthropic 和 OpenAI 使用的代码沙箱 gVisor,押注 AI Agent 基础设施开源 dev.to 在信任 AI 生成的测试用例前,如何逐条复核 unite.ai Franklin Templeton 构建 AI 研究工作流以揭示风险 techxplore.com AI 助力寻找更优的钛合金 3D 打印工艺参数
多元动态
登录 注册
智能体 dev.to · @Shiyam

基数炸弹:不依赖外部缓存在边缘防护 API

原文 我的收藏

文章介绍边缘反向代理如何用固定内存 sketch 应对无限基数攻击、凭证滥用和失控 agent 循环,并回顾前两篇关于读取时衰减计算与 CAS 状态转换、亚 35ns 多核扩展的实现,对比 Stripe、GitHub、Figma 常用的集中式 Redis 限流模式。

AI推荐理由 DEV 技术长文,讲边缘反向代理用固定内存 sketch 抵御无限基数攻击、凭证滥用和失控 agent 循环,并对比集中式 Redis 限流方案;涉及 agent 场景下的基础设施防护,技术细节具体,但属个人博客系列,非官方基准。

70

正文

How an edge reverse proxy uses fixed-memory sketches to survive infinite-cardinality attacks, credential abuse, and runaway agent loops. In Part 1, we explored Interpreted Decay — calculating recency-weighted frequency on-the-fly at read time (count >> age) in a single 64-bit word. In Part 2, we looked under the hood at atomic Compare-And-Swap (CAS) state transitions, bit-chipping eviction lotteries, and sub-35ns multi-core scaling. Data structures prove their real value when applied to infrastructure problems. Consider a common scenario in backend systems: A public API sits behind an edge reverse proxy or ingress gateway. Suddenly, an automated scraper or credential-stuffing bot begins rotating through hundreds of thousands of residential IP addresses, randomized query paths, or spoofed tokens. The standard industry pattern for distributed rate limiting (widely documented by teams like Stripe, GitHub, and Figma) is well-established: Deploy a centralized Redis or Memcached cluster. Track client frequency via sliding-window keys (e.g., rate:limit:). Query the cache cluster on every incoming HTTP request. Under normal traffic, this architecture works reliably. But under an intentional high-cardinality flood, distributed counter clusters face distinct operational trade-offs: Memory & Eviction Collisions: A sliding window allocates a key per client. If an attack fires 500,000 ephemeral IPs across a few minutes, Redis memory surges. Once it reaches maxmemory, it either begins evicting critical application cache data (under LRU policies) or rejects writes (OOM command not allowed), forcing the limiter to fail open. Network Round-Trip Tax: Querying a remote cache cluster on every single HTTP request adds 2–10ms round-trip latency to the 99th percentile (p99). Connection Saturation: Under heavy concurrency, connection pool exhaustion and single-threaded Redis event loops often become the bottleneck before the backend itself gets saturated. The "Cardinality Bomb" Problem When an attacker distributes requests across a vast botnet (hundreds of thousands of rotating residential IPs), two painful realities emerge: 1. No Per-Key Rate Limiter Blocks a 100% Rotating Key A key seen for the very first time has an observed frequency of 1. Whether using Redis, a local hash map, or a token bucket, that request falls below any sensible rate limit threshold. Blocking never-before-seen keys is impossible—doing so would block every legitimate new user visiting the site. Under a pure IP-rotation attack, every rate limiter forwards the traffic. 2. The Rate Limiter Becomes the Attack Vector What differs is what the attack does to the rate limiter itself: In-Memory Hash Maps (map[string]*counter): Every new IP allocates a new map entry. Within minutes, heap allocation explodes, triggering aggressive GC thrashing followed by an Out-Of-Memory (OOM) crash. Redis Clusters: Millions of ephemeral keys bloat the cache until Redis either evicts business-critical cache entries or crashes under memory exhaustion. The attacker doesn't need to take down the application; they turn the rate limiter against itself. Incoming Attack: 1,000,000 Distinct IPs │ ▼ ┌─────────────────────────────────────────┐ │ Traditional Sharded Map / Redis Limiter │ │ ├── Stored Keys: 1,000,000 │ │ ├── Memory: 250 MB ──► 1 GB ──► 2 GB... │──► [ Process OOM-Killed! ] └─────────────────────────────────────────┘ Enter fullscreen mode Exit fullscreen mode The engineering goal is not claiming to magically block a never-before-seen IP on request #1. The goal is surviving the rotation in strictly fixed memory while enforcing limits on every non-rotating client, without relying on external databases. This is the exact purpose of SketchProxy. Enter SketchProxy: Fixed-Memory Edge Defense SketchProxy is an edge reverse proxy built on Go's standard library (net/http, httputil.ReverseProxy). Instead of synchronizing state with an external cache cluster, each proxy instance maintains dedicated in-memory epochsketch tables. Because an EpochSketch bucket table is allocated once at startup (e.g., 65,536 buckets) and never resizes, its memory consumption is flat and immutable. Whether the proxy processes 100 requests or 10 million distinct IP addresses, its memory footprint remains unchanged. The Multi-Layer Request Pipeline Every incoming request passes through an outermost-first defense pipeline. Any stage that makes an early decision short-circuits the pipeline and never touches the upstream backend: Each stage is powered by its own dedicated, isolated sketch: 1. Rate Limiting + The Tarpit Slow Lane Traditional limiters force a binary choice: either 200 OK or an immediate 429 drop. SketchProxy introduces a two-tier volume band: RateLimit.Threshold: The drop line. Requests with estimate >= Threshold receive an immediate 429. Tarpit.Threshold: A lower threshold defining a "suspicious volume" band. Matching requests are delayed with a configurable time.Sleep before forwarding. Tarpitting forces brute-force scrapers to consume their own connection pools and slow down without breaking borderline legitimate users. Defending Against Self-Inflicted DoS: Sleeping goroutines hold open connections. If an attacker floods the tarpit band, a naive proxy would exhaust OS file descriptors. SketchProxy prevents this via Tarpit.MaxConcurrent: once in-flight sleeps hit capacity, further tarpit-eligible requests skip the delay and forward immediately. Defensive delays never sacrifice proxy availability. 2. Wallet Defense: Neutralizing Proxy-Hopping Bots Real-world attacks are rarely 100% rotating across every dimension. A scraper might rotate residential IPs, but it often reuses the same API token or session credential. Wallet Defense tracks frequency keyed on the HTTP Authorization header rather than IP address: $$\text{Key} = \text{sha256}(\text{Authorization Header})$$ Extracting this key takes just ~22 ns with 0 heap allocations. Even if a bot rotates across 50,000 IPs, all requests sharing that credential collide in the same token slot and get throttled. 3. First-Sightings as an Anomaly Detection Signal A flood of brand-new, rotating keys is itself an attack signature. Because EpochSketch indicates whether an observation was a first-sighting (first == true), SketchProxy gets anomaly detection for free: When rate limiting observes a new key, it can trigger an asynchronous JSON webhook (first_sighting). Zero extra lookups: Reuses the rate-limiting Observe call directly. Zero blocking: Webhook dispatches are capped by Anomaly.MaxConcurrent. If the queue is full, notifications drop silently rather than delaying the HTTP request. 4. Agentic Loop Breakers: Outcome-Based Defense With the rise of autonomous AI agents, backend services frequently encounter Runaway Agentic Retry Loops. When an upstream backend returns a transient error (500 or 503), a poorly configured AI agent often retries in a tight loop, firing hundreds of requests per minute and preventing the backend from recovering. The Agentic Loop Breaker gates on response outcomes, not request volume: A dedicated sketch observes only 5xx responses per caller+path. If a caller crosses the 5xx threshold within an epoch window, subsequent requests from that specific caller+path are blocked with an immediate 503, shielding the backend. The block automatically expires after one TickDuration once errors cease. Proving Fixed Memory: The "Cardinality Bomb" Demo To verify that SketchProxy's fixed-memory guarantee holds under real attack conditions, the repository includes cardinalitybomb — a reproducible benchmark stack: cd ecosystem/cardinalitybomb docker compose up --build open http://localhost:9200 Enter fullscreen mode Exit fullscreen mode This stack launches five containers: An origin backend stub. SketchProxy (backed by EpochSketch). A Naive Baseline rate limiter (a competent 256-shard mutex-protected map). An attack generator firing escalating-cardinality requests at both proxies identically. A live dashboard charting real-time memory and latency. The Result: SketchProxy's memory remains completely flat — holding steady at a few tens of megabytes regardless of how many millions of unique keys are generated. The baseline map climbs continuously as each new IP adds a map entry. Within 60 seconds, the baseline container is OOM-killed by the Docker runtime, while SketchProxy continues answering traffic without interruption. Operational Simplicity & Performance SketchProxy is designed for minimal operational footprint: 1. Instant Startup Protect a backend running on port 5000: go run ./cmd/sketchproxy -listen :8080 -target http://localhost:5000 Enter fullscreen mode Exit fullscreen mode 2. Microsecond Key Extraction Benchmarked on an Apple M4 Pro: Request IP+Path extraction: ~14 ns / 0 allocs. Authorization key extraction: ~22 ns / 0 allocs. 3. Zero-Dependency Prometheus Metrics Exposes hand-rolled Prometheus metrics at /metrics without pulling in large external telemetry dependencies: Eviction rates (CASRetriesExhausted, Chips, Evictions) Tarpit concurrency gauges (sketchproxy_tarpit_active) Loop breaker trip states What About Cloudflare or Akamai? (Where Does This Fit?) An obvious architectural question is: “Why not simply put Cloudflare WAF or Akamai in front of the API?” Cloudflare and Akamai operate at the public Anycast edge, providing indispensable L3/L4 volumetric DDoS mitigation, bot challenges (Turnstile), and global CDN caching. SketchProxy does not replace edge CDNs; it solves problems they cannot address: Internal Microservices & East-West Traffic: Cloudflare only protects public North-South ingress. It cannot protect internal service-to-service communication, private VPC endpoints, or Kubernetes ingress where internal client bugs or cascading retries threaten downstream databases. Application-Aware Logic (Wallet Defense & Loop Breakers): Throttling by hashing Authorization headers across rotating IPs or tripping circuit breakers on 5xx error outcomes requires deep application context. Doing this on enterprise CDN tiers requires costly custom edge worker scripting or enterprise plans ($1,000s/mo). Data Privacy & Air-Gapped Environments: Regulated industries (healthcare, finance, defense) often cannot route sensitive customer payloads or authentication tokens through third-party CDN decryption. Prompt Caching for LLM Gateways: SketchProxy embeds semantic prompt caching with TinyLFU admission filtering directly adjacent to local model inference runtimes (like vLLM or Ollama), serving hits in microseconds. In production, combining Cloudflare at the outer perimeter for volumetric protection with SketchProxy at origin or ingress for fixed-memory, application-aware defense provides defense-in-depth. Summary Moving frequency tracking directly to the proxy edge with fixed-memory sketches fundamentally shifts defensive architecture: Zero External Storage: Eliminates external cache clusters, network hops, and connection pools for rate limiting. Immune to Cardinality Attacks: Memory is strictly bounded at startup; scrapers cannot trigger OOM crashes. Multi-Vector Protection: Combines Rate Limiting, Tarpitting, Wallet Defense, and Agentic Loop Breaking in a single nanosecond pipeline. 📦 Inspect the Code & Run the Demo: SketchProxy: ecosystem/sketchproxy Live Cardinality Bomb Demo: ecosystem/cardinalitybomb

来源报道 · 1 篇 · 以下链接均前往原始媒体

← 返回精选动态 原文

更多内容