5.6 KiB
Caddy WAF, Prometheus and Grafana
Monitor your caddy-waf performance and security in real-time with Prometheus and Grafana. Track key metrics like allowed/blocked requests, rule hits (e.g., "block-scanners", "sql-injection", "xss-attacks", browser integrity checks), and more, to understand your WAF's effectiveness against threats.
This guide helps you create a Prometheus exporter to bridge Caddy WAF's JSON metrics (from /waf_metrics) to Prometheus's format. You'll then visualize these metrics in Grafana dashboards for actionable insights.
Step 1: Set Up Your Environment
-
Install Python: Get Python 3.x from python.org.
-
Install Libraries:
pip install prometheus-client requests
Step 2: Create the Exporter Script (exporter.py)
from prometheus_client import start_http_server, Counter, Gauge
import requests
import time
import json
# Define Prometheus metrics
TOTAL_REQUESTS = Counter('caddywaf_total_requests', 'Total requests processed')
BLOCKED_REQUESTS = Counter('caddywaf_blocked_requests', 'Total requests blocked')
ALLOWED_REQUESTS = Counter('caddywaf_allowed_requests', 'Total requests allowed')
RULE_HITS = Counter('caddywaf_rule_hits', 'Hits per WAF rule', ['rule_id'])
RULE_HITS_BY_PHASE = Counter('caddywaf_rule_hits_by_phase', 'Rule hits by phase', ['phase'])
DNS_BLACKLIST_HITS = Counter('caddywaf_dns_blacklist_hits', 'DNS blacklist hits')
GEOIP_BLOCKED = Counter('caddywaf_geoip_blocked', 'Blocked by GeoIP')
IP_BLACKLIST_HITS = Counter('caddywaf_ip_blacklist_hits', 'IP blacklist hits')
RATE_LIMITER_BLOCKED_REQUESTS = Counter('caddywaf_rate_limiter_blocked_requests', 'Rate limiter blocked')
RATE_LIMITER_REQUESTS = Counter('caddywaf_rate_limiter_requests', 'Rate limiter requests')
WAF_VERSION = Gauge('caddywaf_version', 'WAF version', ['version'])
def fetch_metrics():
try:
response = requests.get("http://localhost:8080/waf_metrics")
response.raise_for_status()
data = response.json()
TOTAL_REQUESTS.inc(data["total_requests"])
BLOCKED_REQUESTS.inc(data["blocked_requests"])
ALLOWED_REQUESTS.inc(data["allowed_requests"])
DNS_BLACKLIST_HITS.inc(data["dns_blacklist_hits"])
GEOIP_BLOCKED.inc(data["geoip_blocked"])
IP_BLACKLIST_HITS.inc(data["ip_blacklist_hits"])
RATE_LIMITER_BLOCKED_REQUESTS.inc(data["rate_limiter_blocked_requests"])
RATE_LIMITER_REQUESTS.inc(data["rate_limiter_requests"])
WAF_VERSION.labels(version=data["version"]).set(1)
for rule_id, hits in data["rule_hits"].items():
RULE_HITS.labels(rule_id=rule_id).inc(hits)
if "rule_hits_by_phase" in data:
for phase, hits in data["rule_hits_by_phase"].items():
RULE_HITS_BY_PHASE.labels(phase=phase).inc(hits)
except requests.exceptions.RequestException as e:
print(f"Error fetching metrics: {e}")
except json.JSONDecodeError as e:
print(f"JSON Decode Error: {e}")
if __name__ == '__main__':
start_http_server(8000)
print("Exporter started on http://localhost:8000/metrics")
while True:
fetch_metrics()
time.sleep(10)
Step 3: Run the Exporter
-
Start:
python exporter.py -
Verify:
http://localhost:8000/metricsin browser. Check for Prometheus format.Example output snippet:
# HELP caddywaf_rule_hits_by_phase Rule hits by phase # TYPE caddywaf_rule_hits_by_phase counter caddywaf_rule_hits_by_phase{phase="1"} 1461 caddywaf_rule_hits_by_phase{phase="2"} 705
Step 4: Configure Prometheus
-
Install: prometheus.io/download/
-
Edit
prometheus.yml:scrape_configs: - job_name: 'caddywaf_exporter' static_configs: - targets: ['localhost:8000'] -
Start:
./prometheus --config.file=prometheus.yml -
Verify: Prometheus UI (
http://localhost:9090) > Status > Targets >caddywaf_exportershould be UP.
Step 5: Set Up Grafana
-
Install: grafana.com/grafana/download
-
Start:
http://localhost:3000(login:admin/admin) -
Add Data Source: Configuration > Data Sources > Add data source > Prometheus. URL:
http://localhost:9090. Save & Test. -
Create Dashboard: Create > Dashboard > Add panel. Example queries:
- Total Requests:
sum(rate(caddywaf_total_requests[1m])) - Blocked Requests:
sum(rate(caddywaf_blocked_requests[1m])) - Top Rule Hits:
topk(10, sum by (rule_id) (rate(caddywaf_rule_hits[1m]))) - Rule Hits by Phase:
sum by (phase) (rate(caddywaf_rule_hits_by_phase[1m])) - WAF Version:
caddywaf_version
Customize dashboards as needed.
- Total Requests:
Step 6: Run Everything Together
- Start Caddy WAF (
/waf_metricsaccessible). - Start Exporter:
python exporter.py - Start Prometheus (with config).
- Start Grafana (connected to Prometheus).
- Visualize metrics in Grafana.
Optional: Exporter as Service (systemd)
-
Create:
sudo nano /etc/systemd/system/caddywaf-exporter.service -
Content:
[Unit] Description=Caddy WAF Prometheus Exporter After=network.target [Service] User=your_user ExecStart=/usr/bin/python3 /path/to/exporter.py Restart=always [Install] WantedBy=multi-user.target -
Run:
sudo systemctl daemon-reload sudo systemctl start caddywaf-exporter sudo systemctl enable caddywaf-exporter -
Verify:
sudo systemctl status caddywaf-exporter