Skip to content

aupv9/auto-block

Repository files navigation

AutoBlock

Adaptive multi-layer rate limiting & auto-remediation — in a single, cloud-portable package.

AutoBlock fills the gap between returning a 429 and pushing to your WAF + notifying your team + writing an audit trail. It works as a drop-in middleware for Express, FastAPI, Spring Boot, and Go's net/http, backed by Redis.

Current version: 0.1.0 (2026-01-15)


Why AutoBlock?

Without AutoBlock With AutoBlock
Return 429 and hope WARN → SLOW → BLOCK → BLACKLIST (FSM)
Manual WAF rule updates Auto-push to AWS WAF / Cloudflare / Nginx
No visibility into who is abusing your API Audit stream + Slack/PagerDuty alerts
Burst and sustained abuse treated the same Hybrid sliding-window + token-bucket algorithm
Per-service silos Multi-tenant, shared Redis, one engine

How It Works

Each request is evaluated against configurable rules across multiple dimensions (IP, user ID, endpoint). A penalty score accumulates on violations and drives a state machine:

CLEAN ──→ WARN ──→ SLOW ──→ BLOCK ──→ BLACKLIST
  │         │        │        │
  └─────────┴────────┴────────┘ (score decays over time)

When an IP reaches BLACKLIST, the AutoBlock engine automatically:

  1. Pushes the IP to your WAF (AWS WAF, Cloudflare, or Nginx)
  2. Fires a Slack / PagerDuty alert
  3. Writes an audit event to a Redis Stream

Packages

Package Language Install
@autoblock/core TypeScript npm install @autoblock/core
@autoblock/express TypeScript npm install @autoblock/express
autoblock Python 3.11+ pip install autoblock
autoblock-spring-boot-starter Java 21 Maven: io.autoblock
Go SDK Go 1.22+ go get github.com/autoblock/autoblock/packages/go

Quick Start

Express (TypeScript)

import express from 'express'
import { createAutoBlockMiddleware } from '@autoblock/express'
import Redis from 'ioredis'

const app = express()
const redis = new Redis({ host: 'localhost', port: 6379 })

app.use(createAutoBlockMiddleware(redis, {
  tenant: 'my-app',
  rules: [
    {
      id: 'login-limit',
      enabled: true,
      dimensions: ['ip'],
      endpointPattern: '^/api/auth/login$',
      methods: ['POST'],
      algorithm: 'hybrid',
      limits: { requests: 10, windowSeconds: 60, burst: 15 },
      penalties: {
        warn:      { scoreThreshold: 3 },
        slow:      { scoreThreshold: 6,  delayMs: 2000 },
        block:     { scoreThreshold: 10, durationSeconds: 300 },
        blacklist: { scoreThreshold: 15 },
      },
    },
  ],
}))

app.listen(3000)

FastAPI (Python)

from fastapi import FastAPI
from autoblock.middleware import AutoBlockMiddleware
from autoblock.config import AutoBlockConfig, RuleConfig

app = FastAPI()

app.add_middleware(
    AutoBlockMiddleware,
    tenant="my-app",
    fail_open=True,
    rules=[
        RuleConfig(
            id="login-limit",
            path="/api/auth/login",
            methods=["POST"],
            limit=10,
            window_seconds=60,
            algorithm="hybrid",
        )
    ],
)

Spring Boot (Java)

# application.yml
autoblock:
  tenant: my-app
  fail-open: true
  trust-proxy: true
  rules:
    - path: /api/auth/login
      limit: 10
      window-seconds: 60
      algorithm: HYBRID
      per-user: true
    - path: /api/**
      limit: 200
      window-seconds: 60
      algorithm: SLIDING_WINDOW

Go (net/http)

import "github.com/autoblock/autoblock/packages/go/autoblock"

mw := autoblock.NewMiddleware(redisClient, autoblock.Config{
    Tenant: "my-app",
    Rules: []autoblock.Rule{
        {
            ID:              "login-limit",
            EndpointPattern: "^/api/auth/login$",
            Methods:         []string{"POST"},
            Algorithm:       autoblock.Hybrid,
            Limits:          autoblock.Limits{Requests: 10, WindowSeconds: 60, Burst: 15},
        },
    },
})

http.Handle("/", mw(yourHandler))

Algorithm

AutoBlock's hybrid algorithm runs both checks on every request — either violation increments the penalty score:

Algorithm Catches Trade-off
sliding_window Sustained rate abuse Can allow short bursts
token_bucket Burst abuse Doesn't catch slow, sustained abuse
hybrid Both Recommended for auth/critical endpoints

All counter operations use Lua scripts for atomicity — no WATCH/MULTI needed.


Penalty State Machine

Thresholds are configurable. Defaults:

State Score Effect
CLEAN 0–2 Allow
WARN 3–5 Allow, headers set
SLOW 6–9 Allow with artificial delay (default 2 s)
BLOCK 10–14 429 Too Many Requests + Retry-After
BLACKLIST ≥ 15 403 Forbidden + WAF push + alert

Scores decay over time via the DecayWorker (configurable half-life).


Auto-Remediation Engine

The engine runs as a sidecar or standalone service. On BLACKLIST events it:

  • WAF push — AWS WAF IP Sets, Cloudflare IP Lists, or Nginx geo-module ban files
  • Notifications — Slack webhook, PagerDuty incident (auto-resolves on unblock)
  • Audit stream — every action appended to a Redis Stream

Configure via autoblock.yaml (see autoblock.example.yaml):

tenant: my-app
redis:
  url: redis://localhost:6379

remediation:
  enabled: true
  decay:
    enabled: true
    half_life_minutes: 30

waf:
  providers:
    - name: aws_waf
      enabled: true
      type: aws_waf
      config:
        region: us-east-1
        ip_set_id: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
        scope: REGIONAL

notifications:
  slack:
    enabled: true
    webhook_url: ""   # or env AUTOBLOCK_NOTIFICATIONS_SLACK_WEBHOOK_URL
    channel: "#security-alerts"

Management API

The engine exposes a REST API on :8080. All endpoints require Bearer auth except /healthz.

GET    /healthz
GET    /api/v1/status/ip/{ip}       Penalty state + score
GET    /api/v1/blacklist/ip         List blacklisted IPs
POST   /api/v1/blacklist/ip         Add IP/CIDR  {"ip":"1.2.3.4","ttl":3600}
DELETE /api/v1/blacklist/ip/{ip}    Remove from blacklist
GET    /api/v1/whitelist/ip         List whitelisted IPs
POST   /api/v1/whitelist/ip         Add IP/CIDR to whitelist
DELETE /api/v1/whitelist/ip/{ip}    Remove from whitelist
GET    /api/v1/rules                List dynamic rules
POST   /api/v1/rules                Create rule
PUT    /api/v1/rules/{id}           Replace rule
DELETE /api/v1/rules/{id}           Delete rule

Full spec: api/openapi.yaml


Response Headers

Every request receives standard headers:

Header Description
RateLimit-Limit Configured limit (IETF draft)
RateLimit-Remaining Remaining requests
RateLimit-Reset Seconds until window resets
X-RateLimit-* Legacy equivalents
Retry-After Seconds to wait (on 429 responses)

Local Development

# Start full stack: Redis, engine, API, Prometheus, Grafana
docker compose -f docker/docker-compose.yml up -d

# Services:
#   Redis            → localhost:6379
#   Management API   → localhost:8080
#   Prometheus       → localhost:9091
#   Grafana          → localhost:3000  (admin / admin)

TypeScript:

pnpm install
pnpm --filter @autoblock/core test
pnpm --filter @autoblock/express test

Python:

cd packages/fastapi
pip install -e ".[dev]"
pytest

Java:

cd packages/spring
mvn test --enable-preview

Go:

go test ./... -race

Monorepo Structure

autoblock/
├── packages/core/          TypeScript — algorithms, FSM, Redis client
├── packages/express/       TypeScript — Express.js middleware
├── packages/fastapi/       Python — Starlette/FastAPI middleware
├── packages/spring/        Java — Spring Boot starter
├── packages/go/            Go — net/http + chi middleware
├── engine/                 Go — auto-remediation service
├── api/                    OpenAPI spec + Go handlers
├── deploy/helm/autoblock/  Helm 3 chart
├── docker/                 docker-compose for local dev
├── dashboards/             Grafana + Prometheus alert rules
├── tests/e2e/k6/           k6 load test scripts
└── autoblock.example.yaml  Full configuration reference

Observability

Prometheus metrics exposed on :9090/metrics:

  • autoblock_waf_actions_total{provider,action,success}
  • autoblock_waf_action_latency_seconds{provider,action} (p50/p95/p99)
  • autoblock_blacklist_total{tenant}
  • autoblock_events_processed_total{tenant,state}
  • autoblock_api_requests_total{method,path,status}

Pre-built Grafana dashboards are in dashboards/.

OpenTelemetry tracing is supported in all SDKs (autoblock.evaluate span). It is a no-op when the OTel SDK is not configured.


Configuration Reference

See autoblock.example.yaml for the full annotated configuration file. Sensitive values can be supplied via environment variables with the AUTOBLOCK_ prefix (dots become underscores):

AUTOBLOCK_WAF_PROVIDERS_0_CONFIG_API_TOKEN=secret
AUTOBLOCK_NOTIFICATIONS_SLACK_WEBHOOK_URL=https://hooks.slack.com/...
AUTOBLOCK_API_AUTH_KEYS_0_KEY=my-api-key

CI/CD

Workflow Trigger Publishes
ts.yml packages/core/**, packages/express/** npm
python.yml packages/fastapi/** PyPI
java.yml packages/spring/** Maven Central
engine.yml engine/** ghcr.io images
go-sdk.yml packages/go/**
release.yml Tag push (v*) All packages

License

Apache 2.0

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors