On This Page
WAFio Documentation
WAFio is a self-hosted Web Application Firewall and kernel-level security platform. It runs entirely on your infrastructure — no cloud dependency, no data leaves your network.
HTTP L7 WAF + eBPF kernel firewall + runtime security tracing — all reporting to the same control plane.
Semantic engine + OWASP CRS run in parallel. Decision latency target is under 5ms p99 inline.
One control plane manages multiple projects. Each project is fully isolated with its own agents, rules, and credentials.
All data stays on your infrastructure. WAFio contacts wafio.cloud only to download binaries and security-data updates — no account or API key required.
- 1 Control Plane (dashboard + REST API + gRPC agent orchestration)
- WAF Agent — HTTP L7 inspection reverse proxy sidecar
- Host Agent — eBPF kernel firewall (XDP/TC) + runtime security tracing
- Bundles downloaded from
wafio.cloud— free, no API key
Quick Start (install.sh)
The fastest way to deploy WAFio is the all-in-one installer script. One command — downloads garble-obfuscated binaries, installs PostgreSQL + TimescaleDB, runs migrations, creates your admin account, provisions mTLS certificates, and starts all three components as systemd services.
- Linux — Ubuntu 22.04+ or Debian 12+ recommended
- Kernel 5.8+ with BTF enabled (required for host agent eBPF)
- x86_64 (amd64) architecture
- Root access
- PostgreSQL 14+ with the TimescaleDB extension — the installer sets this up automatically (fresh install), or enables TimescaleDB on your existing PostgreSQL. Required only for the Control Plane.
- No account or API key required — WAFio is free to download.
The Control Plane stores all data in PostgreSQL, and uses the TimescaleDB extension for time-series event storage (WAF decisions, host security events, firewall events) with automatic 30-day retention.
- Fresh server: the installer installs PostgreSQL 17 + TimescaleDB and tunes it automatically.
- Existing PostgreSQL: the installer creates a dedicated
wafiodatabase and enables the TimescaleDB extension only inside that database. Your other databases and data are never touched. Existingshared_preload_librariesare preserved (timescaledb is merged in, not overwritten), and your memory/worker tuning is left as-is.
WAF Agent and Host Agent installs do not require PostgreSQL.
SSH into your Linux server and run:
curl -fsSL https://wafio.cloud/install.sh | sudo bash WAFio is free to download — no account or API key required. To install a specific component non-interactively:
curl -fsSL https://wafio.cloud/install.sh | sudo bash -s -- --component waf-agent The installer will prompt you for:
- Component selection — choose All Components for a complete setup
- PostgreSQL — fresh install or connect to an existing instance
- Admin account — name, email, and password for the WAFio dashboard
- Project name — a label for your first security project
The installer automatically:
- Downloads garble-obfuscated WAFio binaries from
wafio.cloud(free, no signup) - Verifies SHA-256 checksums of all downloaded bundles
- Installs or configures PostgreSQL + TimescaleDB
- Downloads all security data (GeoIP, OWASP CRS, FireHOL, JA3, Bot signatures)
- Runs all database migrations
- Creates your admin account and first project
- Provisions mTLS certificates for WAF and host agents
- Installs and starts all components as systemd services
Total installation time: approximately 3–8 minutes depending on server internet speed.
When installation completes, the dashboard is available at http://your-server:9087. Log in with the admin credentials you created during installation.
Both agents are already connected and running. Navigate to your project to see them online:
- WAF Agents — your WAF agent is registered and awaiting traffic configuration
- Hosts — your host agent is online and the eBPF firewall is active
- Go to WAF Agents → click your agent → Add Application to configure your upstream app
- Go to Firewall to configure L3/L4 rules for your host
- Go to Runtime Security to review and tune detection rules
Verify Services
After installation, verify all services are running:
sudo systemctl status wafio wafio-waf-agent wafio-host-agent
# View live logs
sudo journalctl -u wafio -f
sudo journalctl -u wafio-waf-agent -f
sudo journalctl -u wafio-host-agent -f PostgreSQL Already Installed?
If your server already has PostgreSQL running, the installer asks for your connection details. It creates a dedicated wafio database — your existing databases are not touched. Required: PostgreSQL 14+ with TimescaleDB extension.
Upgrading an Existing Install
Re-running the installer on a server that already has WAFio is safe and idempotent. The script auto-detects an existing install and switches to upgrade mode:
- Stops the running services before replacing binaries (no "text file busy")
- Preserves your
config.yaml— JWT secret and database credentials are kept, so users stay logged in and login keeps working (a timestamped.bakis saved) - Skips admin, project, and credential creation — no duplicate projects, no setup errors
- Keeps existing agent
*.envfiles and certificates - Refreshes binaries, frontend assets, database migrations, and security data, then restarts services
# Same command — upgrades in place
curl -fsSL https://wafio.cloud/install.sh | sudo bashArchitecture
WAFio uses a hub-and-spoke architecture. The Control Plane is the central brain — it stores configuration, aggregates telemetry, and pushes rule updates to agents over a gRPC mTLS channel.
Component Roles
| Binary | Role | Port |
|---|---|---|
wafio | Control plane: dashboard, REST API, agent orchestration, telemetry storage | HTTP :9087, gRPC :9090 |
wafio-waf-agent | HTTP reverse proxy sidecar — inspects every request before it reaches your app | Configurable (e.g. :8080) |
wafio-host-agent | Linux-only eBPF agent — L3/L4 kernel firewall + runtime security tracing | N/A (kernel space) |
How Agents Connect
Agents connect to the control plane over gRPC using mutual TLS (mTLS). Each agent presents a client certificate provisioned from the Credentials page. The certificate's SHA-256 fingerprint identifies which project the agent belongs to — no additional API key needed at runtime.
On connect, the control plane pushes a bundle containing the full WAF configuration. The agent applies it and begins inspecting traffic. Subsequent configuration changes are pushed automatically without restarting the agent.
Storage
| Store | Purpose |
|---|---|
| PostgreSQL + TimescaleDB | All control-plane data: users, projects, agents, WAF decisions, host security events, firewall events, and audit logs. TimescaleDB hypertables for time-series event storage with 30-day auto-retention. |
Security Data Setup
WAFio requires external threat intelligence data — GeoIP databases, OWASP CRS rules, IP reputation lists, JA3 fingerprints, and bot signatures. This data is not bundled in the binary and must be downloaded separately.
When you install WAFio using install.sh, security data is downloaded automatically. This section is relevant only if you need to refresh data or used a manual install.
If security data is missing, WAFio starts but GeoIP blocking, bot protection, JA3 filtering, CRS detection, and FireHOL IP reputation will be non-functional.
Download Everything (Recommended)
# Download all security data (no MaxMind account required)
./wafio fetch-data
# Output example:
# ── GeoIP country ✓ (DB-IP free, 2026-05)
# ── GeoIP city ✓ (DB-IP free, 2026-05)
# ── GeoIP ASN ✓ (DB-IP free, 2026-05)
# ── OWASP CRS ✓ v4.x (147+ rule files)
# ── FireHOL L1 ✓ (812,291 entries)
# ── FireHOL L2 ✓ (additional 1.4M entries)
# ── JA3 blacklist ✓ (Salesforce + abuse.ch)
# ── Bot UA list ✓ (nginx bad-bot-blocker)
# ✅ All security data fetched successfully What Gets Downloaded
| Component | Files | Used for |
|---|---|---|
geoip | security-data/geoip/country.mmdbcity.mmdb, asn.mmdb | GeoIP country blocking, dashboard geo map, IP enrichment |
crs | security-data/crs/coreruleset/ | OWASP Core Rule Set v4 — WAF detection rules (Coraza engine) |
firehol | security-data/firehol/firehol_level1.netsetfirehol_level2.netset | IP reputation blocklists (known malicious IPs, botnets, scanners) |
ja3 | security-data/ja3/ja3.txt | JA3 TLS fingerprint blacklist (malware C2, exploit kits) |
ua | security-data/user-agents/bot.txt | Bad bot user-agent strings (scrapers, attack tools) |
GeoIP Provider: DB-IP vs MaxMind
By default, WAFio downloads from DB-IP — a free GeoIP provider with no account or license key required. If you need MaxMind GeoLite2, obtain a free license key at maxmind.com and set it in config:
geo:
maxmind_license_key: "YOUR_FREE_LICENSE_KEY_HERE" Then re-run ./wafio fetch-data --force.
Keeping Data Fresh
GeoIP databases update monthly. FireHOL and JA3 lists update daily. Recommended monthly cron:
# /etc/cron.d/wafio-update-security-data
0 3 1 * * root /opt/wafio/wafio fetch-data --profile all >> /var/log/wafio/fetch-data.log 2>&1Setup Wizard (Manual Install)
If you installed WAFio using the install.sh script (recommended), the Setup Wizard was already completed automatically. This section is only relevant for advanced users who installed manually.
On first launch of a manually installed control plane, WAFio shows a 3-step Setup Wizard at http://your-server:9087. It configures the control plane, runs database migrations, and creates your first admin account.
Fill in the connection details for your infrastructure. Minimum required fields:
| Field | What to set |
|---|---|
| PostgreSQL host / port / name / user / password | Your PostgreSQL instance credentials |
| JWT Secret | Any long random string (e.g. openssl rand -hex 32). Required in production. |
| SMTP host / user / password | Your SMTP server for email (OTP codes, alerts). Can be skipped initially. |
| Environment | Set to production for live deployments. |
Click Save & Validate to test database connectivity and proceed to Step 2.
This step applies all pending database migrations. WAFio uses golang-migrate with numbered migration files. The wizard shows live progress as each migration runs.
- "permission denied" — ensure the DB user has
CREATE TABLEprivileges - "extension does not exist" — run
CREATE EXTENSION IF NOT EXISTS "uuid-ossp"as superuser - TimescaleDB extension must be installed:
CREATE EXTENSION IF NOT EXISTS timescaledb
Create the first admin user. This account gets system role: admin — it can access all projects, manage members, and reach admin API endpoints. Click Complete Setup to finish and redirect to /login.
After the Wizard
- Log in with your admin credentials at
http://your-server:9087/login - Click New Project to create your first security project
- Go to Credentials and provision an mTLS certificate for each agent
- Deploy WAF and/or Host agents using the certificates
Manual Install
This section describes manual installation. If you are deploying for the first time, use Quick Start (install.sh) above — the installer script handles everything automatically.
Prerequisites
- Linux server (Ubuntu 22.04+ or Debian 12+ recommended), x86_64
- Kernel 5.8+ with BTF (
ls /sys/kernel/btf/vmlinuxmust exist) - PostgreSQL 14+ with TimescaleDB extension
- Ports 9087 (HTTP) and 9090 (gRPC) open in your firewall
Download Binaries
Download bundles from the portal — free, no API key:
# Download WAFio bundles
curl -fsSL "https://wafio.cloud/api/download/controlplane" -o wafio-controlplane.tar.gz
curl -fsSL "https://wafio.cloud/api/download/waf-agent" -o wafio-waf-agent.tar.gz
curl -fsSL "https://wafio.cloud/api/download/host-agent" -o wafio-host-agent.tar.gz
# Verify checksums (from manifest)
MANIFEST=$(curl -fsSL https://wafio.cloud/api/download/manifest)
# Extract sha256 values and verify with sha256sumStart Dependencies
WAFio requires PostgreSQL with the TimescaleDB extension.
docker compose up -d dbConfigure the Control Plane
cp config/config.example.yaml config/config.yaml Minimum required settings:
server:
http_addr: ":9087"
env: production
database:
host: localhost
port: 5432
name: wafio
user: wafio
password: your-db-password
jwt:
secret: "your-32-char-secret-here"Run the Control Plane
# Run migrations + start server
./wafio serve --migrate
# Or run in background
nohup ./wafio serve --migrate > wafio-server.log 2>&1 & Open http://your-server:9087 and complete the Setup Wizard to create your admin account and first project.
Provision Credentials
Go to Credentials in your project sidebar. Enter a name and click Provision. Download the credential bundle immediately — the private key is shown only once.
The bundle contains: ca.crt, client.crt, client.key.
Deploy WAF Agent
scp wafio-waf-agent user@agent-server:/usr/local/bin/
scp ca.crt client.crt client.key user@agent-server:/etc/wafio/certs/
WAFIO_GRPC_SERVER=your-control-plane:9090 \
WAFIO_CA_CERT=/etc/wafio/certs/ca.crt \
WAFIO_CLIENT_CERT=/etc/wafio/certs/client.crt \
WAFIO_CLIENT_KEY=/etc/wafio/certs/client.key \
WAFIO_AGENT_NAME=edge-waf-prod \
WAFIO_LISTEN_ADDR=:8080 \
WAFIO_UPSTREAM=http://localhost:3000 \
./wafio-waf-agentVerify
In the dashboard, navigate to WAF Agents. Your agent should appear as ONLINE. Test with a SQL injection payload:
curl "http://your-agent:8080/?id=1' OR '1'='1"
# Expected: 403 Forbidden (if blocking mode is enabled)Dashboard Tour
The WAFio dashboard gives you a real-time view of your infrastructure's security posture. Here is a walkthrough of every section.
Projects List
The projects list is your starting point. Each project represents an isolated security environment — with its own agents, credentials, WAF rules, and event log.
Project Overview
The Overview shows the health of all protection layers: WAF Agents, Firewall, Runtime Security, and Hosts. Key metrics include Security Score, WAF latency SLA, total blocked requests, and critical event count.
A 0–100 composite score based on agent health, event severity distribution, and SLA compliance.
Target is under 5ms p99 inline. The SLA indicator turns red if detection adds excessive latency.
Shows the percentage of your traffic surface covered by each protection layer.
Count of BLOCK-level decisions in the current window. Drill down in the WAF event log.
WAF Agents
The WAF Agents page lists all registered agents for this project. Each agent card shows its online status, protected application count, and last connection time. Click View applications → to configure per-app WAF rules.
Firewall
The Firewall page manages the eBPF kernel firewall on each host. Configure inbound/outbound rules, IP blocklists, country blocking, and SYN flood protection. Rules are applied instantly via BPF maps — no iptables, no service restart.
Runtime Security
Runtime Security uses eBPF tracepoints to monitor process execution, file access, network connections, and privilege escalation — at the kernel level, with zero application instrumentation. Events are categorized by severity (INFO, LOW, MEDIUM, HIGH, CRITICAL).
Hosts
The Hosts page lists all machines running the WAFio host agent. Each entry shows online status, OS and kernel version, CPU/memory info, host key prefix, and last-seen time.
Credentials
Credentials provisions mTLS client certificates for agents. The private key is shown once at provisioning time — download and store it securely. It is never stored on the control plane.
Audit Log
The Audit Log records every action taken by project members: logins, configuration changes, credential provisioning, agent registration, and WAF rule changes. Use it for compliance, incident investigation, and change tracking.
WAF Agent Setup
The WAF agent is a lightweight HTTP reverse-proxy sidecar. Deploy it in front of any HTTP/HTTPS application. It intercepts every request, runs it through the detection pipeline, and either forwards, logs, or blocks it — in under 5ms p99.
Detection Pipeline
Systemd Service
[Unit]
Description=WAFio WAF Agent
After=network.target
[Service]
Type=notify
ExecStart=/usr/local/bin/wafio-waf-agent
ExecReload=/bin/kill -USR2 $MAINPID
Restart=on-failure
RestartSec=5s
Environment=WAFIO_GRPC_SERVER=10.1.1.2:9090
Environment=WAFIO_CA_CERT=/etc/wafio/certs/ca.crt
Environment=WAFIO_CLIENT_CERT=/etc/wafio/certs/client.crt
Environment=WAFIO_CLIENT_KEY=/etc/wafio/certs/client.key
Environment=WAFIO_AGENT_NAME=waf-prod-01
Environment=WAFIO_LISTEN_ADDR=:8080
Environment=WAFIO_UPSTREAM=http://localhost:3000
[Install]
WantedBy=multi-user.target systemctl daemon-reload
systemctl enable --now wafio-waf-agent
systemctl status wafio-waf-agent Zero-Downtime Reload
The WAF agent supports graceful restarts via tableflip. Send SIGUSR2 (or systemctl reload wafio-waf-agent) to perform a zero-downtime restart. Supports Type=notify in systemd — sends READY=1 only after the first bundle is received from the control plane.
Key Environment Variables
| Variable | Required | Description |
|---|---|---|
WAFIO_GRPC_SERVER | Yes | Control plane gRPC address (e.g. 10.1.1.2:9090) |
WAFIO_CA_CERT | Yes | Path to CA certificate |
WAFIO_CLIENT_CERT | Yes | Path to agent client certificate |
WAFIO_CLIENT_KEY | Yes | Path to agent private key |
WAFIO_AGENT_NAME | Yes | Must match the name used when provisioning the credential |
WAFIO_LISTEN_ADDR | Yes | Address/port the WAF agent listens on (e.g. :8080) |
WAFIO_UPSTREAM | Yes | Upstream application URL (e.g. http://localhost:3000) |
WAFIO_GRPC_SERVER_NAME | No | Override TLS SNI — useful when connecting via IP (set to 127.0.0.1) |
Host Agent Setup
The host agent runs on Linux and provides two capabilities: a kernel-level eBPF firewall (XDP/TC) and runtime security tracing (syscall/tracepoint hooks). It requires root privileges and Linux kernel 5.8+ with BTF enabled.
- Linux kernel 5.8+ with BTF (
CONFIG_DEBUG_INFO_BTF=y) - Root privileges (systemd service runs as root)
- Verify BTF:
ls /sys/kernel/btf/vmlinux— file must exist - eBPF objects are CO-RE (Compile Once, Run Everywhere) — no kernel headers needed at deploy time
- Linux amd64 (x86_64) only — host agent does not run on macOS or ARM
Register a Host
- Go to Hosts in your project sidebar
- Click Register Host
- Enter a name and description
- Copy the generated host key — pass this to the agent via
WAFIO_HOST_KEY
Systemd Service
[Unit]
Description=WAFio Host Agent
After=network.target
[Service]
Type=simple
ExecStart=/usr/local/bin/wafio-host-agent
Restart=on-failure
RestartSec=5s
Environment=WAFIO_GRPC_SERVER=10.1.1.2:9090
Environment=WAFIO_CA_CERT=/etc/wafio/certs/ca.crt
Environment=WAFIO_CLIENT_CERT=/etc/wafio/certs/client.crt
Environment=WAFIO_CLIENT_KEY=/etc/wafio/certs/client.key
Environment=WAFIO_HOST_KEY=your-host-key-here
[Install]
WantedBy=multi-user.target What the Host Agent Monitors
Every execve with full command line, parent/grandparent, UID, cgroup, and container context.
Opens to sensitive paths (/etc/passwd, /proc/, web shells) with read/write flags.
Outbound TCP connections — detect C2 callbacks, reverse shells, and data exfiltration.
setuid/setgid, capability grants, and container namespace escapes detected at syscall level.
Container Enrichment
The host agent polls Docker/containerd sockets every 10 seconds to map cgroup IDs → container metadata (image, name, labels, Kubernetes pod/namespace). All trace events from containers are automatically tagged with this context. Degrades gracefully if no Docker socket is present.
Credentials (mTLS)
Every agent authenticates to the control plane using a mutual TLS client certificate. WAFio uses its own internal CA per project — no public CA involved.
Provisioning a Credential
- Navigate to Credentials in your project
- Enter a descriptive name (e.g.
waf-prod-edgeorhost-vpn-server) - Set expiry in days (default: 365)
- Click Provision
- The modal shows the one-time credential bundle — copy or download it immediately
Credential Bundle Contents
| File | Description |
|---|---|
ca.crt | Project CA certificate — used by the agent to verify the control plane's identity |
client.crt | Agent's client certificate — presented to the control plane during TLS handshake |
client.key | Agent's private key — shown once, never stored on the server |
The private key (client.key) is never stored on the control plane. If you lose it, revoke the credential and provision a new one. Revocation takes effect within seconds — the agent will disconnect immediately.
Revoking a Credential
Click Revoke next to any issued credential. The agent loses its connection within seconds. Revocation is immediate and permanent — provision a new credential to reconnect.
Firewall
The WAFio firewall operates at the kernel level using eBPF XDP and TC hooks. It processes packets before they reach the kernel's network stack — orders of magnitude faster than iptables or nftables.
Firewall Rule Types
| Rule Type | Description |
|---|---|
| IP Blocklist | Drop all traffic from specific IP addresses or CIDR ranges |
| IP Allowlist | Only allow traffic from whitelisted IPs (default-deny mode) |
| Country Block | GeoIP-based blocking — drop all traffic from specified country codes |
| Port Rules | Block or allow specific TCP/UDP ports |
| SYN Flood Protection | Rate-limit new TCP connections per source IP |
| Egress Control | Block outbound connections to specific IPs/ports (C2 callback prevention) |
Rule Application
Rules are pushed to the agent as BPF map updates — they take effect instantly with no traffic interruption. No agent restart needed. Changes reflect in the dashboard within 1–2 seconds.
Enforcement Modes
| Mode | Value | Behavior |
|---|---|---|
| Monitor | 0 | Log only — no packets dropped |
| Alert | 1 | Log + send alert to control plane |
| Kill | 2 | Drop packet (for kernel rules) or SIGKILL process (for userspace rules) |
| Simulate | 3 | Simulate enforcement — log as if blocked without actually dropping |
Runtime Security
Runtime security uses eBPF tracepoints to hook into kernel syscalls — detecting suspicious behavior at the source rather than relying on log-based detection after the fact.
Detection Rules
WAFio ships with built-in detection rules seeded at project creation. Rules cannot be deleted (only disabled). Custom rules can be added, updated, or deleted by project owners. Each rule has ordered AND-ed conditions and an action:
| Action | Effect |
|---|---|
suppress | Drop the event — reduce noise from known-good processes |
escalate | Raise event severity — force attention to high-value events |
downgrade | Lower severity — tune noisy rules without disabling them |
tag | Add a label to the event — useful for SIEM correlation |
Condition Fields
Rules can match on: comm, parent_comm, grandparent_comm, event_name, category, severity, filename, addr, port, uid, gid, addr_family, flags, is_container, container_image.
Supported operators: eq, neq, in, not_in, contains, starts_with, glob, gte, lte.
Example: Suppress Noisy Docker Events
conditions:
- field: comm
op: eq
value: containerd-shim
action: suppress SIEM Export
Runtime security events can be exported to external SIEM systems via webhook or stdout. Configure in the project settings under Data Retention & Export.
Detection Engine
WAFio's detection pipeline runs two independent analysis layers on every HTTP request. Both results are combined by the Decision Engine to produce a final verdict.
Layer 1: Semantic Engine (14 Analyzers)
Fourteen AST/parser-based analyzers run in parallel — each specialized for a specific attack category. They operate on decoded, normalized input with multiple smudge attempts to defeat evasion techniques. Each input is gated by a fast pre-filter, so only the analyzers relevant to a given payload actually run.
| Analyzer | Detects | Key techniques |
|---|---|---|
| SQL | SQL injection | Full SQL AST parsing, UNION, subqueries, boolean blinds, versioned comments (/*!50000*/) |
| XSS | Cross-site scripting | HTML/JS parser, event handler analysis, CRLF evasion, entity decode chains, protocol obfuscation |
| CMD | OS command injection | Shell metacharacter detection, $IFS expansion, ANSI-C octal escapes, backtick/process substitution |
| LFI | Local file inclusion / path traversal | ../ patterns, null bytes, encoded variants, Windows 8.3 short names |
| SSRF | Server-side request forgery | RFC-1918 targets, cloud metadata endpoints (169.254.169.254), IPv6 translation addresses |
| Java | Java deserialization, SpEL/OGNL, Log4Shell | Recursive Log4j lookup unfold, nested obfuscation, JNDI protocol variants |
| PHP | PHP code injection, wrapper abuse | php://, data://, dangerous function detection, string concat eval |
| Python | Python code / template injection | eval/exec, os.system, __class__.__mro__ gadget chains, pickle opcodes |
| NoSQL | NoSQL injection | MongoDB operator injection ($where, $ne, $gt), JS expression injection, JSON-encoded operator smuggling |
| LDAP | LDAP injection | Filter metacharacter injection, blind boolean filters, wildcard / null-byte abuse in DN and search filters |
| SSTI | Server-side template injection | Jinja2 / Twig / Freemarker / Velocity expression syntax, sandbox-escape gadgets, arithmetic probes |
| XXE | XML external entity | External / parameter entity declarations, SYSTEM / PUBLIC DTDs, OOB exfil, billion-laughs expansion |
| Deser | Insecure deserialization | Java serialized streams (rO0 / ac ed), PHP O:/a: objects, Python pickle, .NET / YAML gadget markers |
| Proto Pollution | Prototype pollution | __proto__ / constructor / prototype key injection in JSON and query/body params |
Layer 2: OWASP CRS v4
Coraza runs OWASP Core Rule Set v4 in DetectionOnly mode — it never blocks directly. Matched rule IDs are fed into the Decision Engine. When all semantic engines return clean and skip_coraza_when_semantic_clean: true (default), CRS attack-category results are suppressed to reduce false positives.
Decision Engine
For each matched CRS rule, the Decision Engine looks up its RuleMeta: attack category, base score, sensitivity level, and confidence multiplier. Rules above the project's sensitivity threshold are silently dropped. Remaining scores are summed:
total_score = Σ (base_score × confidence) for each matched rule
if total_score >= block_threshold → BLOCK
if total_score >= log_threshold → LOG
else → ALLOW If both the semantic engine and CRS agree on the same attack category, the score is elevated via cross-engine boost.
Sensitivity Levels
| Level | Value | Use Case |
|---|---|---|
| Safe | 1 | Only high-confidence rules fire. Lowest FP rate. Good for APIs and tightly-typed endpoints. |
| Balanced | 2 | Default. Good balance for most web applications. |
| Aggressive | 3 | High sensitivity — more detections, more potential false positives. Useful in honeypot/research mode. |
Tuning False Positives
- Lower the project sensitivity level (Aggressive → Balanced → Safe)
- Raise the
block_thresholdin project WAF config - Add path exceptions for known-safe routes (health checks, webhooks)
- Enable
skip_coraza_when_semantic_clean: true(default) to suppress CRS noise when semantic engine finds nothing - Bump individual CRS rule
Sensitivityto 3 for known-noisy rules indecision.go
Configuration Reference
Configuration is loaded in priority order: config/config.yaml → WAFIO_* environment variables → CLI flags. Every YAML key maps to an env var: server.http_addr → WAFIO_SERVER_HTTP_ADDR.
Required Settings
| Key | Env Var | Description |
|---|---|---|
database.name | WAFIO_DATABASE_NAME | PostgreSQL database name — server refuses to start if empty |
jwt.secret | WAFIO_JWT_SECRET | Must be changed from default in env: production |
Hot-Reload vs Restart Required
| Setting group | Reload behavior |
|---|---|
server.*, database.*, jwt.*, crs.* | Restart required — wired at boot |
smtp.*, limits.*, dashboard.cache_ttl_sec | Read live — no restart needed |
| Project WAF rules JSON | Pushed to agents via gRPC automatically — no restart |
Common Settings
server:
http_addr: ":9087" # HTTP listen address
grpc_addr: ":9090" # gRPC listen address for agents
env: production # "development" or "production"
database:
host: localhost
port: 5432
name: wafio
user: wafio
password: secret
max_conns: 20
jwt:
secret: "change-me-in-production"
expiry_hours: 24
smtp:
host: smtp.example.com
port: 587
user: noreply@example.com
password: smtp-password
crs:
path: "./security-data/crs" WAF Project Config (per-project JSON)
{"block_threshold": 5.0,
"log_threshold": 2.0,
"sensitivity": 2,
"skip_coraza_when_semantic_clean": true,
"geo_block_countries": [],
"bot_protection": true,
"rate_limit_rps": 100
}Downloads
WAFio is free to download from the wafio.cloud portal — no account, signup, or API key required. Every download is recorded anonymously (component, version, and network metadata) for release analytics; no personal data is collected.
Download Endpoints
| Endpoint | Auth | Description |
|---|---|---|
GET /api/download/manifest | None | Returns latest.json with version and SHA-256 checksums for all bundles |
GET /api/download/controlplane | None | Download control plane bundle (garble-obfuscated, amd64) |
GET /api/download/waf-agent | None | Download WAF agent bundle (garble-obfuscated, amd64) |
GET /api/download/host-agent | None | Download host agent bundle (garble-obfuscated, amd64) |
Using the API
# Check current version and checksums
curl -s https://wafio.cloud/api/download/manifest | python3 -m json.tool
# Download WAF agent bundle (no key needed)
curl -fsSL "https://wafio.cloud/api/download/waf-agent" -o wafio-waf-agent.tar.gz
# Verify checksum
EXPECTED=$(curl -s https://wafio.cloud/api/download/manifest \
| python3 -c "import sys,json; print(json.load(sys.stdin)['bundles']['waf-agent']['sha256'])")
echo "$EXPECTED wafio-waf-agent.tar.gz" | sha256sum -c Bundle Contents
Each bundle is a .tar.gz archive containing the binary and an install.sh helper script. Binaries are built with garble obfuscation (-literals -seed=random) for distribution — symbol names, package paths, and string literals are obfuscated in every release.
Error Responses
| HTTP Status | Condition |
|---|---|
400 | Unknown component name (must be controlplane, waf-agent, or host-agent) |
503 | Bundle not yet uploaded — check manifest for current version |