Skip to content

Latest commit

 

History

History
139 lines (108 loc) · 5.42 KB

configuration.md

File metadata and controls

139 lines (108 loc) · 5.42 KB

Configuration

The adapter has exactly two options (WithMaxBodyBytes, WithLogger); all security tuning is engine configuration. See the guard-core-go configuration reference for the full SecurityConfig surface.

Minimal tuned setup

cfg := guardcore.DefaultSecurityConfig()
cfg.EnableRateLimiting = true
cfg.RateLimit = 30
cfg.RateLimitWindow = 60
cfg.EndpointRateLimits = map[string]guardcore.RateLimitEntry{
    "/rate/strict": {Requests: 1, Window: 10},
}
cfg.EnableIPBanning = true
cfg.AutoBanThreshold = 5
cfg.AutoBanDuration = 300
cfg.CustomErrorResponses = map[int]string{
    403: "Blocked by fiber-guard",
}

Address headers

The engine skips ssrf scanning for address headers (host, x-forwarded-for, x-real-ip, ...) through its built-in default set (guardcore.DefaultExcludedHeaders, the reference's _DEFAULT_EXCLUDED_HEADERS), so no manual exclusion is needed. ExcludedDetectionHeaders only adds names on top of that default.

Custom response modifier

cfg.CustomResponseModifier runs on every pass-through response after the security and CORS headers, as the last step of the reference response pass, and CORS headers are applied again after it. Blocked responses already carry it from the engine. With a modifier configured the adapter holds the whole handler response in memory until the handler returns, so a streamed response is delivered at the end instead of incrementally; without one the response is untouched and streams as usual.

Redis

Distributed bans and rate limits require Redis:

cfg.EnableRedis = true
cfg.RedisURL = os.Getenv("REDIS_URL") // e.g. redis://redis:6379
cfg.RedisPrefix = "fiber_guard:"

Without Redis the managers fall back to in-process state, which does not share across replicas.

Body inspection

WithMaxBodyBytes bounds what the detector sees. Bodies larger than the limit are still forwarded to your handler in full (fasthttp buffers the whole body before the middleware runs); only the inspected prefix is truncated. The default matches the engine's MaxBodyInspectBytes (262144).

Trusted proxies

The adapter resolves the client from the fasthttp transport peer (RequestCtx().RemoteIP()), never from c.IP(): with TrustProxy plus a ProxyHeader configured, Fiber would resolve the client from proxy headers, and trusting proxy headers is policy the engine owns. When behind a reverse proxy, trust only the proxy hop so the engine resolves the real client IP from forwarded headers:

cfg.TrustedProxies = []string{"172.16.0.0/12", "10.0.0.0/8"}
cfg.TrustedProxyDepth = 1

Behavior rules

The engine's behavioral surface is configurable through the global fields:

cfg.GlobalBehaviorRules = []guardcore.BehaviorRuleConfig{
    {RuleType: "usage", Threshold: 100, Window: 3600, Action: "ban"},
}
cfg.BehaviorScanResponseBody = true
cfg.BehaviorMaxResponseBodyInspectBytes = 262144

BehaviorScanResponseBody gates return-pattern rules that read the response body (regex:, json:, or bare substring patterns; status: patterns work without it). With the flag on, the adapter captures the leading BehaviorMaxResponseBodyInspectBytes of Fiber's buffered response body and reports status code plus captured prefix to Engine.ProcessResponse after your handler runs, mirroring the reference response factory's behavioral phase. Return rules never modify the response. Note: Fiber buffers the response, so every handler response is observed; no framework limitation applies.

Geo lifecycle

Country rules resolve through the engine's geo lifecycle. A token enables the full IPInfo download/refresh lifecycle; a database path keeps local-file mode. OnGeoEvent receives country_blocked, geo_lookup_failed, and decorator_violation events:

cfg.IPInfoToken = os.Getenv("IPINFO_TOKEN")
cfg.IPInfoMaxAge = 86400 // 0 falls back to the reference default
cfg.BlockedCountries = []string{"CN"}
cfg.OnGeoEvent = func(ev guardcore.GeoEvent) { ... }

Route-level country rules (RouteConfig.BlockedCountries / WhitelistCountries) emit the same events through the same hook.

Per-route detection exclusions

Route configuration lives in the engine registry and reaches the middleware through guardfiber.WithRouteID (see Usage). Every guardcore.RouteConfig field is reachable, including the per-route detection exclusion surface:

engine.Routes.Register("search", func(rc *guardcore.RouteConfig) {
    rc.ExcludedDetectionParams = map[string]bool{"q": true}
    rc.ExcludedDetectionHeaders = map[string]bool{"referer": true}
    rc.ExcludedDetectionBodyFields = map[string]bool{"note": true}
    rc.EnabledDetectionCategories = []string{"xss", "sqli"}
    scanOff := false
    rc.DetectionScanBody = &scanOff
    rc.BehaviorRules = []guardcore.BehaviorRuleConfig{
        {RuleType: "usage", Threshold: 10, Window: 60, Action: "ban"},
    }
})

CORS

Set cfg.EnableCORS = true (plus any CORSAllowOrigins, CORSAllowMethods, CORSAllowHeaders, CORSAllowCredentials, CORSExposeHeaders, CORSMaxAge tuning). Preflights are short-circuited by the engine through guardfiber.New, blocked responses carry the CORS headers over the security-header set, and the adapter merges Engine.CORSResponseHeaders(req) into every pass-through response.

Custom error bodies

cfg.CustomErrorResponses replaces the body of any engine verdict status code; the status code and security headers stay engine-owned.