zentinelproxy/zentinel
zentinelproxy/zentinel has 122 GitHub stars and 23 forks. Star changes are not measured yet. Last checked 2026-11-12 08:07 UTC. Last push 2026-11-12.
A security-first reverse proxy built to guard the free web.
What you can do
- Service types - web, api, static, builtin and inference (LLM/AI) routes
- Load balancing - 14 algorithms, including round-robin, weighted, least connections, consistent hash, Maglev, Peak EWMA and least-tokens-queued
- Security - TLS and mTLS, per-SNI certificates, ACME, rate limiting, GeoIP filtering, decompression (zip bomb) limits
- Agentic protocols - MCP and A2A awareness: per-method and per-tool allow/deny, resolved from the JSON-RPC body
Crecimiento de estrellas medido
- in 24h
- Recopilando historial
- in 7 days
- Recopilando historial
- in 15 days
- Recopilando historial
- in 1 month
- Recopilando historial
Cambios netos en períodos que se solapan, no totales diarios. Los datos no disponibles se dejan en blanco. Las estrellas indican interés, no calidad.
README.md
OriginalA security-first reverse proxy built to guard the free web
A reverse proxy on Cloudflare Pingora with explicit limits, predictable failure modes and security logic in crash-isolated agents, for operators who want to sleep.
Website · Docs · Playground · All repositories
Zentinel is a reverse proxy built on Cloudflare Pingora. It ships bounded resources, deterministic timeouts and an explicit fail-open or fail-closed choice per route, and keeps parsing-heavy or risky security logic (WAF, auth, policy) out of the dataplane in external agents, so a buggy agent cannot take the proxy down with it.
In the benchmarks on zentinelproxy.io Zentinel had the lowest p99 of five proxies (Zentinel, Envoy, HAProxy, Nginx, Caddy) at 10,000 req/s, and a 1-hour, 1,000,000-request soak test finished with a 99.95% success rate and no memory leak detected.
The core (proxy, routing, TLS, caching, load balancing) is production-ready. Agents are versioned separately; each one's status is on its registry page.
Quick start
curl -fsSL https://get.zentinelproxy.io | sh
Save this as zentinel.kdl. It proxies localhost:8080 to a backend on port 8081:
system {
worker-threads 0 // auto-detect CPU cores
}
listeners {
listener "http" {
address "0.0.0.0:8080"
protocol "http"
}
}
routes {
route "default" {
matches {
path-prefix "/"
}
upstream "backend"
}
}
upstreams {
upstream "backend" {
target "127.0.0.1:8081"
}
}
zentinel test -c zentinel.kdl # validate the config and exit
zentinel -c zentinel.kdl # run
The system block is required. More examples in config/examples/
(API gateway, load balancing, WebSocket, caching, inference routing, ACME,
namespaces and more), or build a config interactively with the
config builder.
Install
# Install script (binary only)
curl -fsSL https://get.zentinelproxy.io | sh
# Install and start as a systemd service (Linux, root or sudo)
curl -fsSL https://get.zentinelproxy.io | sh -s -- --enable-service
# From crates.io (the crate is zentinel-proxy, the binary is zentinel).
# --locked builds with the tested dependency versions; without it a fresh
# resolve can pick tokio 1.54, which the current Pingora fork cannot run on (#624).
cargo install --locked zentinel-proxy
# Docker
docker run -p 8080:8080 -v $(pwd)/zentinel.kdl:/etc/zentinel/zentinel.kdl \
ghcr.io/zentinelproxy/zentinel -c /etc/zentinel/zentinel.kdl
On systemd hosts the install script also writes /etc/systemd/system/zentinel.service,
a sysusers snippet and a starter config at /etc/zentinel/zentinel.kdl.
Enabling and starting the service is opt-in (--enable-service). See
crates/proxy/docs/deployment.md.
Configuration
Configuration is KDL. zentinel test -c <file> parses and validates it and
rejects unknown keys, so a typo fails loudly instead of being ignored.
Proxying to an HTTPS backend? Add a tls block to the upstream. Without it,
Zentinel connects with plaintext HTTP regardless of the port.
upstreams {
upstream "backend" {
target "api.example.com:443"
tls {
sni "api.example.com"
}
}
}
Full reference: docs.zentinelproxy.io.
Features
| Feature | What it does |
|---|---|
| Service types | web, api, static, builtin and inference (LLM/AI) routes |
| Load balancing | 14 algorithms, including round-robin, weighted, least connections, consistent hash, Maglev, Peak EWMA and least-tokens-queued |
| Security | TLS and mTLS, per-SNI certificates, ACME, rate limiting, GeoIP filtering, decompression (zip bomb) limits |
| Agentic protocols | MCP and A2A awareness: per-method and per-tool allow/deny, resolved from the JSON-RPC body |
| Agents | External processors for WAF, auth and custom logic over agent protocol v2 (UDS or gRPC), crash-isolated, any language |
| HTTP caching | Pingora-based response caching with stampede prevention and memory, disk or hybrid backends |
| WebSocket | RFC 6455 proxying with per-frame agent inspection |
| Observability | Prometheus metrics and structured logging; OpenTelemetry tracing when built with --features opentelemetry (the released binaries are built without it) |
| Hot reload | SIGHUP reloads routes, upstreams and agents after validation, with an atomic swap; listener changes need a restart |
Full breakdown: zentinelproxy.io/features.
Use cases
- Reverse proxy: TLS termination, static files, compression and security headers.
- API gateway: versioned routing, JWT or API-key auth (via agents), per-client rate limiting, JSON error responses.
- Load balancer: weighted distribution, health checks, circuit breakers, blue-green and canary rollouts.
- Inference gateway: token-based rate limiting, model routing with glob patterns (
gpt-4*,claude-*), and prompt-injection and PII filtering through agents. - Agent gateway (MCP / A2A): per-method and per-tool allowlists enforced against the JSON-RPC body.
- WebSocket gateway: persistent connection proxying with frame inspection and message rate limiting.
- Security gateway: WAF, GeoIP filtering, mTLS and composable agent pipelines.
Example configs for each: config/examples/.
Agentic protocols
Zentinel understands MCP (Model Context Protocol) and A2A (Agent2Agent). A route declares which methods and tools are permitted, and the proxy enforces that by reading the JSON-RPC envelope:
route "mcp" {
matches { path-prefix "/mcp" }
upstream "mcp-server"
mcp {
tools {
allow "get_weather" "search_docs"
deny "execute_sql"
}
}
}
Policy is resolved from the body, never from the mirrored headers. MCP's
Streamable HTTP transport copies the method and tool name into Mcp-Method and
Mcp-Name so intermediaries can route without parsing JSON. An allowlist built
on those headers allows everything:
Mcp-Name: read_file <- what a header-based allowlist checks
{"method":"tools/call","params":{"name":"delete_everything"}}
^ what the server actually executes
Zentinel reads the headers only to confirm they agree with the body, and
refuses a request that disagrees with itself. Requests claiming a protocol
revision older than 2026-07-28 are refused by default, because those
revisions never required the two to match; without that check, an attacker
opts out of validation by claiming an old version. A2A defines no mirrored
headers, so its policy reads the body directly.
This decides whether a call may be made. Whether its contents are safe (prompt injection in an argument, PII in a payload) stays agent work.
Reference: Agentic protocols.
How it works
┌────────┐ ┌──────────┐
│ Client │ │ Upstream │
└────┬───┘ └─────▲────┘
│ │
▼ │
╔═══════════ Zentinel (core, single binary) ══════════╤════╗
║ │ ║
║ Listener ─▶ Routing ─▶ Filter chain ─▶ Forward ────┘ ║
║ TLS, H2 priority rate-limit, LB, ║
║ + LRU cache, hooks retries ║
║ │ ║
╚══════════════════════════════╪═══════════════════════════╝
│ UDS / gRPC (agent protocol v2)
▼
╔═══════ External agents (separate processes) ═══════╗
║ WAF · Auth · Rate-limit · … ║
║ crash-isolated, any language ║
╚════════════════════════════════════════════════════╝
The response retraces the filter chain back to the client; access logs and
metrics are emitted at completion. The dataplane is a single binary. See
MANIFESTO.md for the reasoning and
crates/proxy/docs/architecture.md for the
per-phase details.
Why Zentinel
- Bounded resources: memory limits, queue depths, deterministic timeouts.
- Explicit failure modes: fail-open or fail-closed per route, never ambiguous.
- External extensibility: security logic lives in agents, not the core, so the dataplane stays small.
- Observable by default: decisions are logged and metered; features ship only when bounded, observed and tested.
Agents
Agents are external processes that hook into each request phase over agent
protocol v2. They are crash-isolated from the proxy, deployed independently,
and can be written in any language. Agents in the bundle install with
zentinel bundle install <name> (zentinel bundle list shows them).
SDKs: Rust · Go · Python · TypeScript · Elixir · Kotlin · Haskell
| Agent | What it does |
|---|---|
| WAF | Pure Rust WAF: detection rules, anomaly scoring, API schema validation, bot protection |
| ZentinelSec | Pure Rust ModSecurity-compatible WAF for SecLang rules and the OWASP CRS, no C dependencies |
| AI Gateway | Pattern-based prompt-injection, jailbreak and PII detection for LLM APIs |
| Auth | JWT, OIDC, API keys, Basic, SAML, mTLS, with Cedar-based authorization |
| Policy | Rego/OPA and Cedar policy evaluation, written in Haskell (beta) |
| Chaos | Latency, error and timeout injection with targeting and safety controls |
| Lua | Sandboxed Lua scripts for request and response processing |
| WebSocket Inspector | Content filtering, schema validation and attack detection for WebSocket frames |
| MQTT Gateway | Topic ACLs, client auth and payload inspection for MQTT |
All agents: registry.zentinelproxy.io.
Crates in this repository
Each crate has its own docs/ directory where there is more to say.
| Crate | Path | What it does |
|---|---|---|
zentinel-proxy |
crates/proxy/ |
The reverse proxy (binary zentinel) |
zentinel-config |
crates/config/ |
KDL configuration parsing and validation |
zentinel-agent-protocol |
crates/agent-protocol/ |
Agent protocol v2 and IPC |
zentinel-common |
crates/common/ |
Shared types, errors and utilities |
zentinel-gateway |
crates/gateway/ |
Kubernetes Gateway API controller (in progress, see conformance.md) |
zentinel-stack |
crates/stack/ |
All-in-one launcher for the proxy and agents |
zentinel-wasm-runtime |
crates/wasm-runtime/ |
WASM agent runtime on Wasmtime |
zentinel-sim |
crates/sim/ |
WASM-compatible configuration simulator |
zentinel-playground-wasm |
crates/playground-wasm/ |
Browser bindings for the playground |
zentinel-config-inspect |
crates/config-inspect/ |
Static config topology analysis and visualization |
sim, playground-wasm and config-inspect are excluded from the workspace
and built separately.
Development
The toolchain is pinned to Rust 1.99.1 in rust-toolchain.toml.
mise run build # cargo build --workspace
mise run test-unit # unit tests
mise run test # all tests
mise run pre-push # fmt-check, clippy -D warnings, docs (what CI requires)
See CONTRIBUTING.md. Using Claude Code? See
.claude/CLAUDE.md for project context and coding rules.
Related
- Documentation: guides, reference and examples
- Playground: try the routing engine in the browser (WASM)
- Benchmarks: latency, soak and chaos results
- Agent registry: every agent and its status
- zentinel-control-plane: fleet management for Zentinel proxies (Elixir/Phoenix)
- Discussions and issues
License
Apache-2.0, see LICENSE.
Part of Zentinel, the security-first reverse proxy. The shisa guards the gate.
Explorar proyectos relacionados
trimstray/the-book-of-secret-knowledge
Una colección de listas inspiradoras, manuales, chuletas, blogs, trucos, comandos de una línea, herramientas de CLI y web, y más.
257,837 estrellasHack-with-Github/Awesome-Hacking
Una colección de diversas listas awesome para hackers, pentesters e investigadores de seguridad.
125,254 estrellasswisskyrepo/PayloadsAllTheThings
Una lista de payloads y métodos de bypass útiles para la seguridad de aplicaciones web y para pentesting/CTF.
82,583 estrellascaddyserver/caddy
Servidor web HTTP/1-2-3 rápido, extensible y multiplataforma con HTTPS automático
78,959 estrellas