This guide walks you through creating your first WAF configuration from scratch, explaining each section and its purpose.
The project includes config.example.yaml which demonstrates all available options. We'll build a basic configuration step by step.
Here's the absolute minimum required configuration:
proxy:
enabled: true
host: "http://localhost:8080"
wafMiddleware:
mode: auditThis configuration:
- Runs in
auditmode (logs only, no blocking) - Proxies requests to
localhost:8080
Note: Port, logging, and GeoIP database paths are configured via environment variables or command-line arguments, not in the YAML configuration file.
Start by defining basic operational parameters:
wafMiddleware:
mode: audit # 'audit' for testing, 'normal' for productionRecommendation: Always start with audit mode to test your rules before enforcing them.
Configure how to detect the real client IP (important if behind a proxy):
wafMiddleware:
detectClientIp:
headers:
- "x-forwarded-for"
- "cf-connecting-ip" # Add if using CloudflareThe WAF checks headers in order. If not found, it falls back to the connection IP.
Set up reverse proxy to your backend:
proxy:
enabled: true
host: "http://your-backend:8080"
config: {} # Optional http-proxy-middleware optionsReplace http://your-backend:8080 with your actual backend URL.
Configure IP banning:
jailManager:
enabled: true
storage:
driver: memory # Use 'memory' for testing, 'file' for production
syncInterval: 5000
syncAlways: false
filterRules: [] # Rules added in next stepFor production, use file-based storage:
jailManager:
enabled: true
storage:
driver: file
driverConfig:
filePath: './data/blocked_ips.json'
locker:
enabled: true
config:
retries: 3
filterRules: []Let's add a simple rate limiting rule:
jailManager:
enabled: true
storage:
driver: memory
filterRules:
# Limit requests from any IP
- name: global-rate-limit
type: composite
uniqueClientKey: ["ip"]
conditions: [] # Applies to all requests
limit: 1000
period: 60 # 1000 requests per 60 seconds
duration: 300 # Ban for 5 minutes if exceeded
escalationRate: 1.5 # Increase ban time on repeat offensesThis rule:
- Limits any IP to 1000 requests per minute
- Bans offenders for 5 minutes
- Increases ban time by 1.5x for repeat offenders
Allow trusted IPs to bypass all checks:
wafMiddleware:
whitelist:
ips:
- "10.0.0.1" # Specific IP
ipSubnet:
- "192.168.1.0/24" # Local network
geoCountry: [] # e.g., ["US", "GB"]
geoCity: []Enable the management API:
api:
enabled: true
auth:
enabled: true
username: "admin"
password: "change-this-password"Security: Always enable auth and use a strong password!
Enable Prometheus metrics:
metrics:
enabled: true
path: '/metrics'Putting it all together:
# Proxy to backend
proxy:
enabled: true
host: "http://localhost:8080"
# API for management
api:
enabled: true
auth:
enabled: true
username: "admin"
password: "secure-password-here"
# Prometheus metrics
metrics:
enabled: true
path: '/metrics'
# WAF middleware configuration
wafMiddleware:
mode: audit
# Client IP detection
detectClientIp:
headers:
- "x-forwarded-for"
# Whitelist trusted sources
whitelist:
ips:
- "127.0.0.1"
ipSubnet:
- "192.168.1.0/24"
geoCountry: []
geoCity: []
# Jail system and filter rules
jailManager:
enabled: true
storage:
driver: memory
filterRules:
# Global rate limit
- name: global-rate-limit
type: composite
uniqueClientKey: ["ip"]
conditions: []
limit: 1000
period: 60
duration: 300
escalationRate: 1.5-
Start the WAF:
# Using Docker docker run -v $(pwd)/config.yaml:/app/config.yaml waf # Or from source npm start
-
Check for errors in the console output
-
Test the health endpoint:
curl http://localhost:3000/waf/healthz
-
Send test requests:
# Send a normal request curl http://localhost:3000/ # Send many requests to trigger rate limit (in audit mode, just logs) for i in {1..1100}; do curl http://localhost:3000/ & done
-
Check the API (if enabled):
curl -u admin:secure-password-here http://localhost:3000/waf/jail-manager/baned-users
Some settings are configured outside the YAML file:
- Port: Set via
PORTenvironment variable or--portflag (default: 3000) - GeoIP databases: Set via
GEOIP_COUNTRY_PATHandGEOIP_CITY_PATHenvironment variables - Log level: Configure via application settings or environment variables
See Environment Variables for full list.
Now that you have a working configuration:
- Add more rules - See Filter Rules
- Switch to normal mode - When ready for production
- Configure geolocation rules - See Geolocation
- Set up monitoring - See Prometheus Metrics
- Wrong backend URL - Requests won't be proxied correctly
- Starting in normal mode - Test in audit mode first!
- Weak API passwords - Always use strong, unique passwords
- Not configuring IP detection - May ban wrong IPs if behind a proxy
For more help, see the Troubleshooting Guide.