Get the WAF up and running in just a few minutes using Docker.
- Docker installed (for Option 1)
- Downloaded GeoIP databases (see below)
- A backend service to protect
Download the required GeoIP databases:
# Create directory
mkdir -p geoip_data && cd geoip_data
# Download databases
wget https://github.com/P3TERX/GeoLite.mmdb/releases/latest/download/GeoLite2-Country.mmdb
wget https://github.com/P3TERX/GeoLite.mmdb/releases/latest/download/GeoLite2-City.mmdb
cd ..Create your configuration file:
# Create config.yaml
cat > config.yaml <<'EOF'
proxy:
host: "http://localhost:8080" # Change to your backend URL
api:
auth:
enabled: false
username: 'admin'
password: 'admin'
metrics:
enabled: true
auth:
enabled: false
username: 'admin'
password: 'admin'
wafMiddleware:
mode: audit # Use 'audit' for testing, 'normal' for production
detectClientIp:
headers:
- "x-forwarded-for"
detectClientCountry:
method: geoip
detectClientCity:
method: geoip
jailManager:
enabled: true
storage:
driver: memory
filterRules:
- name: "global-rate-limit"
type: "composite"
uniqueClientKey: ["ip"]
conditions: []
period: 60
limit: 100
duration: 300
escalationRate: 1.5
sentry:
enabled: false
dsn: ''
debug: false
EOFNote: See Configuration Examples for production-ready configurations.
The easiest way to run WAF is using Docker:
# Pull latest image
docker pull ghcr.io/someblackmagic/web-application-firewall:latest
# Create data directory
mkdir -p data
# Run WAF
docker run -d \
--name waf \
-p 3000:3000 \
-v $(pwd)/config.yaml:/app/config.yaml:ro \
-v $(pwd)/geoip_data:/app/geoip_data:ro \
-v $(pwd)/data:/app/data \
ghcr.io/someblackmagic/web-application-firewall:latest
# Check logs
docker logs -f wafYou should see output similar to:
[INFO] WAF starting in audit mode
[INFO] GeoIP databases loaded successfully
[INFO] Server listening on port 3000
See Running with Docker for more details.
Download pre-built binaries from GitHub releases:
# Download latest release (Linux x64 example)
wget https://github.com/SomeBlackMagic/WebApplicationFirewall/releases/latest/download/waf-linux-x64
chmod +x waf-linux-x64
# Run
./waf-linux-x64Note: Check Releases page for available platforms (Linux, macOS, Windows).
For development and testing:
# Clone repository
git clone https://github.com/SomeBlackMagic/WebApplicationFirewall.git
cd WebApplicationFirewall
# Install dependencies
npm install
# Copy config
cp config.example.yaml config.yaml
# Download GeoIP databases to project root
wget https://github.com/P3TERX/GeoLite.mmdb/releases/latest/download/GeoLite2-Country.mmdb
wget https://github.com/P3TERX/GeoLite.mmdb/releases/latest/download/GeoLite2-City.mmdb
# Run
npm startSee Development Setup for detailed instructions.
curl http://localhost:3000/waf/healthzExpected response:
Hello from WAF server!
Send a request through the WAF to your backend:
curl http://localhost:3000/The request should be proxied to your backend.
For Docker:
docker logs wafFor binary/source: Check console output
In audit mode, the WAF logs all activity but doesn't block requests.
Let's add a simple rate limiting rule. Edit config.yaml:
jailManager:
enabled: true
storage:
driver: memory
filterRules:
- name: "test-rate-limit"
type: "composite"
uniqueClientKey: ["ip"]
conditions: [] # Applies to all requests
period: 60 # 60 seconds
limit: 100 # 100 requests per period
duration: 300 # Ban for 5 minutes
escalationRate: 1.5For Docker:
docker restart wafFor binary:
Press Ctrl+C and restart: ./waf-linux-x64
For source:
Press Ctrl+C and restart: npm start
Once you've tested and are satisfied with the configuration, switch to normal mode:
Edit config.yaml:
wafMiddleware:
mode: normalRestart the WAF. Now it will actively block requests that violate rules.
For Docker:
docker restart wafSend multiple requests to trigger the rate limit:
# Send 110 requests (exceeds limit of 100)
for i in {1..110}; do curl -s http://localhost:3000/ > /dev/null && echo "Request $i"; doneAfter 100 requests, you should see 429 responses (Too Many Requests).
Now that you have the WAF running:
- Add more rules - See Filter Rules
- Configure whitelisting - See Static Lists
- Set up monitoring - See Prometheus Metrics
- Deploy to production - See Docker Compose
- Enable the API - See API Configuration
For production, use:
- Docker Compose - Docker Compose Guide
- File-based storage - For persistent bans
- Strong API passwords - If enabling the API
- Normal mode - After testing in audit mode
Example production Docker command:
docker run -d \
--name waf \
--restart unless-stopped \
-p 3000:3000 \
-v $(pwd)/config.yaml:/app/config.yaml:ro \
-v $(pwd)/geoip_data:/app/geoip_data:ro \
-v $(pwd)/data:/app/data \
-e SENTRY_DSN=your-sentry-dsn \
ghcr.io/someblackmagic/web-application-firewall:latestIf port 3000 is already in use:
For Docker:
docker run -d \
--name waf \
-p 3001:3000 \ # Map to different host port
...Ensure your backend service is running and accessible:
# Test backend directly
curl http://localhost:8080/
# For Docker, use host.docker.internal instead of localhost
# Update config.yaml:
# proxy:
# host: "http://host.docker.internal:8080"Verify that database files exist:
ls -lh geoip_data/*.mmdbIf missing, download them again (see Step 1).
On Linux: Use 172.17.0.1 (Docker bridge IP) instead of localhost
On Mac/Windows: Use host.docker.internal instead of localhost
proxy:
host: "http://host.docker.internal:8080"For more troubleshooting, see the Troubleshooting Guide.
- Configuration Overview - Learn about all configuration options
- Docker Deployment - Detailed Docker instructions
- First Configuration - Step-by-step configuration guide