Skip to content

NGINX Configuration Reference ​

Configuration schema, options, and parameters for RouteWarden for NGINX & OpenResty (github.com/routewarden/nginx-warden).


1. Lua Module Initialization ​

Initialize RouteWarden using routewarden.new(config) within NGINX's init_by_lua_block or init_worker_by_lua_block. The returned instance is re-entrant and shared across request worker threads:

http {    lua_package_path "/usr/local/openresty/site/lualib/?.lua;/etc/nginx/lua/lib/?.lua;/etc/nginx/lua/lib/?/init.lua;;";    init_by_lua_block {        local routewarden = require("resty.routewarden")        warden = routewarden.new({            -- Configuration options go here        })    }}

2. Complete Configuration Options ​

warden = routewarden.new({    -- Master toggle    enabled = true,                        -- Default: true    debug = false,                         -- Default: false (outputs trace logs via ngx.log)    security_log = true,                   -- Default: false (emits JSON security events for CrowdSec/SIEM)    -- Built-in rules    enable_default_patterns = true,        -- Default: true (blocks .env, .git, .aws, dumps, actuator)    enable_default_allow_patterns = true,  -- Default: true (permits /robots.txt, /sitemap*.xml, /.well-known/*)    -- Deep inspection    check_query = false,                   -- Default: false (evaluates unescaped query string)    check_headers = {                      -- Default: {} (inspects forwarded headers for path smuggling)        "X-Forwarded-Uri",        "X-Rewrite-URL"    },    -- HTTP Method filtering    methods = { "GET", "HEAD" },           -- Default: { "GET" } (non-matching methods bypass checks)    -- IP / CIDR Subnet Allowlist    allowed_ips = {        "127.0.0.1",        "10.0.0.0/8",        "192.168.1.0/24",        "::1"    },    -- Custom regular expressions (PCRE-compatible)    path_patterns = {        "(?i)^/admin(/.*)?$",        "(?i)^/api/internal(/.*)?$"    },    -- Safe pattern exemptions (takes precedence over block patterns)    allow_patterns = {        "(?i)^/api/internal/health$"    },    -- Response action configuration    response = {        mode = "json",                     -- Options: json, html, text, xml, redirect, captcha,                                           -- silentDrop, gzipBomb, tarpit, fakeSuccess,                                           -- rateLimitChallenge, proxy, infiniteStream        status_code = 403,        body = '{"error":"Access Denied"}',        headers = {            ["X-Frame-Options"] = "DENY"        },        redirect_url = "https://example.com/blocked",        proxy_url = "http://127.0.0.1:9999/canary",        gzip_bomb_mb = 10,        retry_after_seconds = 300,        tarpit_delay_ms = 1000,        tarpit_max_duration_seconds = 60,        stream_size_mb = 100,        captcha = {            provider = "turnstile",        -- Options: turnstile, hcaptcha, recaptcha            site_key = "0x4AAAAAAAxxyyzz",            title = "Security Verification"        }    }})

3. Options Reference Table ​

KeyTypeDefaultDescription
enabledbooleantrueEnables or disables RouteWarden inspection.
debugbooleanfalseWhen true, logs normalization transformations and rule matching details.
security_logbooleanfalseEmits single-line structured JSON security events on stdout for CrowdSec and SIEM auto-ban.
enable_default_patternsbooleantrueIntercepts common exposure targets (.env, .git, .aws, database dumps, actuator, debug files).
enable_default_allow_patternsbooleantruePermits standard discovery files (/robots.txt, /sitemap*.xml, /.well-known/*, /security.txt).
check_querybooleanfalseInspects raw and URL-decoded query string parameters for sensitive targets.
methodstable{"GET"}Array of HTTP verbs to inspect. Verbs outside this list bypass inspection.
allowed_ipstable{}Array of IPv4/IPv6 addresses or CIDR subnets allowed to bypass path inspection.
path_patternstable{}Array of custom PCRE regular expressions to block. Alias: block_patterns.
allow_patternstable{}Array of custom PCRE regular expressions to exempt from blocking.
responsetable{ mode = "json", status_code = 403 }Response execution table.

4. Response Modes Table ​

RouteWarden for NGINX supports 13 response modes matching the core engine:

ModeKey SettingsAction
jsonstatus_code, bodySends structured JSON with application/json header.
htmlstatus_code, bodyServes custom HTML error page.
textstatus_code, bodyReturns plain text with text/plain.
xmlstatus_code, bodyServes XML payload with application/xml.
redirectstatus_code, redirect_urlRedirects client via HTTP 301, 302, or 307.
captchacaptcha.provider, captcha.site_keyServes interactive Cloudflare Turnstile, hCaptcha, or reCAPTCHA page.
silentDropNoneTerminates TCP connection immediately via NGINX HTTP 444.
gzipBombgzip_bomb_mbDelivers highly compressed zero-byte gzip stream that expands in client RAM.
tarpittarpit_delay_ms, tarpit_max_duration_secondsTrickles bytes slowly to tie up bot sockets and worker pools.
fakeSuccessstatus_code (200), body (optional)Deceptive honeypot returning realistic .env, .git/HEAD, or Spring Actuator mock data.
rateLimitChallengeretry_after_seconds (300)Returns HTTP 429 with standard Retry-After header.
proxyproxy_urlTransparently proxies request to an internal canary or forensic honeypot container.
infiniteStreamstream_size_mb (100)Streams high-speed random characters to exhaust scanner storage and buffers.

5. Client IP Resolution ​

RouteWarden evaluates client addresses using the following priority:

  1. X-Forwarded-For header (first non-internal IP)
  2. X-Real-IP header
  3. Socket address ngx.var.remote_addr

When deploying behind Cloudflare, AWS ALB, or an outer proxy, set standard NGINX real-ip directives:

set_real_ip_from 10.0.0.0/8;set_real_ip_from 172.16.0.0/12;set_real_ip_from 192.168.0.0/16;real_ip_header X-Forwarded-For;real_ip_recursive on;

Released under the MIT License.