High-throughput, Redis-backed API protection for Go.
Atomic Lua critical path. Reputation pipeline. Behavioral entropy. Hot-reloadable signatures. Zero-allocation fast path.
English Β· Π ΡΡΡΠΊΠΈΠΉ Β· δΈζ
| β‘ ~12 ns clean-request fast path | Bloom filter short-circuits hot paths with zero allocations |
| π‘οΈ Atomic Redis Lua critical path | Blacklist + rate-limit decision in a single round-trip |
| π§ Reputation pipeline | Static rules + score evaluators + DFA signatures + behavioral entropy |
| π₯ Hot-reload without restart | SIGHUP-driven ruleset swap, no dropped connections |
| πͺ Dynamic backoff | Escalating ban TTLs: 1m β 10m β 24h |
| π§― Self-healing limits | Auto-tightens under load, decays back when traffic clears |
| π Observability built-in | OpenTelemetry spans, Prometheus sidecar, generic stats hook |
| π§© Drop-in middleware | net/http, gin, echo, fiber β one line each |
go get github.com/Zhaba1337228/GuardGoRequires Go 1.25+ Β· Redis 6.2+ / Valkey / KeyDB / Dragonfly
guard := guardgo.New(guardgo.DefaultConfig())
defer guard.Close()Defaults: Redis at
127.0.0.1:6379,1000 req/s.
package main
import (
"net/http"
"time"
guardgo "github.com/Zhaba1337228/GuardGo"
"github.com/redis/go-redis/v9"
)
func main() {
rdb := redis.NewClient(&redis.Options{Addr: "127.0.0.1:6379"})
cfg := guardgo.NewConfig(rdb, 200, 1*time.Second)
cfg.FailOpen = true
cfg.Bloom.Enabled = true
cfg.Reputation.Enabled = true
cfg.Reputation.WarningLevel = 60
cfg.Reputation.Threshold = 100
engine := guardgo.New(cfg)
defer engine.Close()
mux := http.NewServeMux()
mux.HandleFunc("/healthz", func(w http.ResponseWriter, _ *http.Request) {
w.WriteHeader(http.StatusOK)
})
_ = http.ListenAndServe(":8080", engine.Middleware(mux))
}router.Use(guardgo.Gin(engine))
e.Use(guardgo.Echo(engine))
app.Use(guardgo.Fiber(engine)) ββββββββββββββββββββββββββββββββ
request ββββΆ β Local LRU blacklist cache β βββ hit βββΆ block (cached)
ββββββββββββββββββββββββββββββββ
β miss
βΌ
ββββββββββββββββββββββββββββββββ
β Penalty box check β βββ strict mode (UA/Referer required)
ββββββββββββββββββββββββββββββββ
β pass
βΌ
ββββββββββββββββββββββββββββββββ
β Bloom filter (negative) β βββ definitely-not-banned βββΆ allow
ββββββββββββββββββββββββββββββββ
β unknown
βΌ
ββββββββββββββββββββββββββββββββ
β Redis Lua (atomic): β
β β’ blacklist set check β
β β’ rate-limit counter β
ββββββββββββββββββββββββββββββββ
β
βΌ
allow / block
β
βΌ (async, off critical path)
ββββββββββββββββββββββββββββββββ
β Reputation pipeline: β
β β’ static Rule checks β
β β’ Evaluator score β
β β’ DFA signatures β
β β’ behavioral entropy β
β ββΆ penalty / blacklist β
ββββββββββββββββββββββββββββββββ
GuardGo evaluates traffic through a score pipeline:
| Score | Action |
|---|---|
< WarningLevel |
Normal flow |
β₯ WarningLevel |
Penalty mode (strict UA/Referer, tightened limit) |
β₯ Threshold |
Blacklist via Redis Lua, escalating ban TTL |
Fingerprint: IP + User-Agent + Accept-Language (case-folded, hashed).
Dynamic backoff (per IP, sliding window):
| Attempt | Default TTL |
|---|---|
| #1 | 1m |
| #2 | 10m |
| #3+ | 24h |
If RulesetFile or DynamicRules is configured, signatures hot-reload on POSIX SIGHUP:
kill -HUP <pid>No process restart. No dropped connections.
rules.ApplyDefaultSecurityPresets(&cfg)Bundled signatures: SQLi probes, path traversal, scanner UA fingerprints, common exploit paths.
| Surface | What you get |
|---|---|
| OpenTelemetry | guardgo.process span with decision attributes |
| Prometheus sidecar | cmd/guardgo-agent exposes /metrics |
| Live dashboard | cmd/guardgo-cli β terminal UI: top risk, active blocks, DFA stats |
| Generic hook | StatsCollector interface β forward to Datadog / OTEL / custom |
go run ./cmd/guardgo-agent --redis-addr 127.0.0.1:6379 --prefix guardgo --listen :9090
go run ./cmd/guardgo-cli --redis-addr 127.0.0.1:6379 --prefix guardgo --ruleset ./rules.yaml12th Gen Intel(R) Core(TM) i5-12400 Β· windows/amd64 Β· 2026-03-08
| Case | Latency | Throughput | Allocations |
|---|---|---|---|
| Clean Request (Bloom) | 11.8 ns | ~84 M ops/s | 0 B/op 0 allocs/op |
| DFA Match (100 rules) | 454 ns | ~2.2 M ops/s | 24 B/op 1 alloc/op |
| Redis Fallback (parallel, miniredis) | 205β225 Β΅s | ~4.4 K ops/s/core | ~206 KB/op |
Reproduce:
go test ./pkg/bloom -run ^$ -bench BenchmarkBloomCleanRequest -benchmem -benchtime=5s -count=5
go test ./pkg/dfa -run ^$ -bench BenchmarkDFA100RulesMatch -benchmem -benchtime=5s -count=5
go test ./tests/load -run ^$ -bench BenchmarkEngineCheckParallel -benchmem -benchtime=10s -count=5
# Real Redis fallback (recommended for production profiling)
REDIS_ADDR=127.0.0.1:6379 \
go test ./tests/load -run ^$ -bench BenchmarkRedisFallbackRealRedis -benchmem -benchtime=10s -count=5go test ./... # all unit + integration (miniredis)
go test -race ./tests/integration -count=1 # data races
REDIS_ADDR=127.0.0.1:6379 go test ./tests/load -bench . # real Redis perf
go test -tags chaos ./tests/chaos -v -count=1 # chaos (requires Docker).
βββ engine*.go # core decision pipeline (split by concern)
βββ decision.go # Reason / Decision types and headers
βββ config.go # MiddlewareConfig + defaults
βββ frameworks.go # Gin / Echo / Fiber adapters
βββ middleware_http.go # net/http middleware
βββ ruleset.go # YAML/JSON ruleset loader + hot-reload
βββ pkg/
β βββ bloom/ # zero-alloc bloom filter
β βββ dfa/ # multi-pattern DFA matcher
βββ internal/
β βββ blacklist/ # local LRU
β βββ redislua/ # embedded Lua scripts
βββ rules/ # built-in rules and presets
βββ cmd/
β βββ guardgo-agent/ # Prometheus sidecar
β βββ guardgo-cli/ # live dashboard
βββ examples/ # net/http, gin, presets
βββ tests/
βββ integration/ # miniredis-driven
βββ load/ # benchmarks
βββ chaos/ # testcontainers-driven (build tag: chaos)
PRs welcome. See CONTRIBUTING.md and CODE_OF_CONDUCT.md.
Conventional commits are required (feat:, fix:, perf:, docs:, test:, ci:, chore:) β release-please uses them to drive CHANGELOG.md and version bumps.
Found a vulnerability? See SECURITY.md. Please do not open public issues with exploit details before a fix is in place.
MIT Β© GuardGo contributors