Universal Active Deception Web Application Firewall (WAF) Proxy
Miragewaf is a universal active deception Web Application Firewall (WAF) proxy. Unlike traditional WAFs that block bot request payloads with intrusive error pages (which alerts attackers and prompts them to switch proxy IPs), Miragewaf leverages active deception. It feeds deterministic, realistic mock data to crawlers, fuzzers, and scrapers, while injecting hidden trapdoor honeypot links into HTML responses to automatically flag scraper IPs.
Warning
This software is designed solely for authorized security audits, defense research, and frontend robustness testing. Running this proxy to deceive users, spoof assets in unauthorized scenarios, or intercept unauthorized networks is illegal. The creators and contributors assume no liability for misuse, damages, or legal actions resulting from the use of this software. By utilizing this repository, you agree to use it in strict accordance with local laws and security guidelines.
[Client / Bot / Scraper]
|
| HTTP/S Request (HTML page / API endpoint)
v
[Miragewaf Proxy] (127.0.0.1:8080)
|
| Evaluates Client IP & User-Agent
|
+---> [Classified as Bot & Requesting Protected API]:
| Generates and returns deterministic spoofed data (no backend query).
|
+---> [Requests Honeypot Link]:
| Flags Client IP as BOT, returns mock success payload.
|
+---> [Legitimate request / Human]:
Forwards request to Backend Server (e.g., PHP, WordPress, Next.js, FastAPI).
Injects hidden honeypot link into HTML body on-the-fly before returning response.
- Active Deception Strategy: Returns status code 200 OK with realistic dummy data to crawlers instead of blocking them. Attackers waste resource bandwidth parsing useless datasets without realizing they have been detected.
- Polymorphic Honeypots: Generates randomized decoy paths on startup (e.g.,
/db-config-a8e0f1.sql) and dynamically injects them into HTML outputs using morphing tags (a,link,iframe,img), varied styles (display:none,opacity:0), and fake descriptors to bypass static scraper exclusions. - Backend Signature Mimicry: Sniffs response header signatures (such as
ServerandX-Powered-By) from the real backend and copies them onto spoofed responses, keeping the proxy footprint invisible. - Client Behavior & Header Fingerprinting (CBHF): Inspects request headers sequence. If a client User-Agent claims to be a modern browser (Chrome/Safari) but lacks standard browser headers (Accept/Accept-Language), it is instantly flagged as a bot.
- Seeded Deterministic Generators: Uses hash-based seeds derived from query parameters/IDs. If a scraper queries the same record multiple times, it receives identical spoofed results, maintaining the illusion of a real database.
- On-The-Fly Honeypot Link Injection: Intercepts HTML responses and appends hidden link tags right before
</body>. Real users cannot see or interact with them, but DOM parsers follow them, instantly flagging their IP. - Stateful IP Bot Tracking: Automatically records flagged IPs in-memory. Once an IP is flagged, all subsequent requests to protected API endpoints from that IP receive spoofed data, regardless of User-Agent rotations.
- Fully Universal: Acts as a standalone HTTP reverse proxy that sits in front of any application server (Next.js, Express, Django, Laravel, Go, PHP, etc.) without requiring framework-specific integrations.
Attackers often spoof their User-Agent to mimic regular browsers (e.g., Chrome, Safari, or Firefox). Miragewaf detects this bypass by checking for the presence of mandatory browser headers:
- If the request claims to be a browser in the
User-Agentbut completely omits standard headers likeAcceptorAccept-Language, Miragewaf instantly flags the client IP as a bot. - Real browsers always negotiate content type preferences and languages, while command-line security tools or script libraries (e.g., python-requests, curl, sqlmap) typically omit these headers by default.
To prevent automated parsers from identifying and filtering out hidden honeypot links based on static patterns, Miragewaf dynamically morphs the structure, tags, styles, and names of injected traps on every response:
- Tag Types Used:
<a>: Anchor tags with random anchor text.<link rel="prefetch">: Pre-fetch headers that DOM parsers follow.<iframe>: Inline frame tags.<img>: Image source elements.
- Inline CSS Obfuscation Variations:
display:none;visibility:hidden;position:absolute;left:-9999px;opacity:0;position:absolute;width:0;height:0;z-index:-100;width:0;height:0;border:0;display:inline;position:absolute;top:-5000px;
- Dynamic Anchors / Descriptions:
- "Admin Configuration Backup Details"
- "Developer API Status Log"
- "Database Statistics Check"
- "System Status Settings"
<html>
<head><title>Dashboard</title></head>
<body>
<h1>Welcome User</h1>
</body>
</html><html>
<head><title>Dashboard</title></head>
<body>
<h1>Welcome User</h1>
<iframe src="/db-config-cdf70449.sql" style="width:0;height:0;border:0;display:inline;position:absolute;top:-5000px;" aria-hidden="true"></iframe>
</body>
</html>Since Miragewaf runs as an independent HTTP reverse proxy at the network boundary, it integrates seamlessly with any backend programming language, framework, or web server:
Configure your local web server (e.g., Nginx or Apache) to listen on an internal port (like 8080), and point Miragewaf to proxy requests from port 80/443 to it.
Nginx Configuration (/etc/nginx/sites-available/default):
server {
listen 8080; # Move Nginx to listen internally
server_name your-website.com;
root /var/www/html;
index index.php index.html;
location / {
try_files $uri $uri/ /index.php?$args;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php8.2-fpm.sock;
}
}Start Miragewaf in front of Nginx:
./miragewaf -listen 127.0.0.1:80 -backend http://127.0.0.1:8080 -config miragewaf.jsonRun your Next.js application internally on port 3000, and place Miragewaf in front of it to intercept scraper traffic:
Start Next.js App:
npm run start -- -p 3000Start Miragewaf to receive public traffic on port 80:
./miragewaf -listen 127.0.0.1:80 -backend http://127.0.0.1:3000 -config miragewaf.jsonPoint Miragewaf to your Python/Ruby application server instance:
- FastAPI / Uvicorn:
uvicorn main:app --host 127.0.0.1 --port 8000 ./miragewaf -listen 0.0.0.0:80 -backend http://127.0.0.1:8000
- Ruby on Rails / Puma:
rails server -b 127.0.0.1 -p 3000 ./miragewaf -listen 0.0.0.0:80 -backend http://127.0.0.1:3000
Use Docker Compose to deploy Miragewaf as the public-facing service routing to a backend container service inside a shared virtual network:
version: '3.8'
services:
miragewaf:
image: golang:1.21-alpine
ports:
- "80:80"
volumes:
- ./miragewaf:/app
working_dir: /app
command: go run main.go -listen 0.0.0.0:80 -backend http://backend-app:3000
depends_on:
- backend-app
backend-app:
image: node:18-alpine
working_dir: /app
command: npm run startEnsure Go is installed (version 1.20+ recommended), then compile locally:
# Clone the repository
git clone https://github.com/fa33az/miragewaf.git
# Move into the project directory
cd miragewaf
# Compile into a local binary
go build -o miragewaf main.goThe behavior of Miragewaf is controlled entirely via miragewaf.json. Below is an explanation of the default setup structure:
{
"listen_addr": "127.0.0.1:8080",
"backend": "http://127.0.0.1:3000",
"honeypots": [
"/admin/backup",
"/wp-admin"
],
"bot_user_agents": [
"sqlmap",
"gobuster",
"curl",
"python-requests"
],
"protected_paths": {
"/api/users": {
"response_format": "json",
"template": {
"id": "{{id}}",
"name": "{{name}}",
"email": "{{email}}",
"balance": "{{balance}}"
}
}
}
}| Placeholder | Generates | Example |
|---|---|---|
{{id}} |
The requested ID extracted from the URL | 123 |
{{name}} |
Seed-based deterministic name | Michael Smith |
{{email}} |
Seed-based deterministic email address | user_123@gmail.com |
{{balance}} |
Seed-based deterministic floating-point balance | 4.2750 |
{{random_int}} |
Seed-based deterministic integer value | 8472 |
{{random_float}} |
Seed-based deterministic decimal value | 42.75 |
{{uuid}} |
Seed-based deterministic UUID | e9300190-6e71-a30f-c4ca-be5a4f026dcf |
{{ethereum_address}} |
Seed-based deterministic Ethereum address | 0x4f0d32477d4c8b5cc7b6a54fca34c7599f6503fe |
{{hash}} |
Seed-based deterministic SHA256 string | 84a70409... |
{{address}} |
Seed-based deterministic physical address | 769 View Rd, Jakarta |
{{paragraph}} |
Seed-based deterministic natural text block | Smart contract transaction validation state... |
You can start Miragewaf immediately by passing the target backend URL directly:
# Proxies public traffic from http://127.0.0.1:8080 to your local backend on port 3000
./miragewaf http://localhost:3000Instead of manually writing JSON files, choose an optimized preset tailored to your tech stack:
# WordPress protection (auto traps /wp-login.php, /xmlrpc.php, /wp-config.php.bak, etc.)
./miragewaf --preset wordpress http://localhost:80
# Next.js / React protection (auto traps /.env.local, /_next/backup, protects /api/*)
./miragewaf --preset nextjs http://localhost:3000
# Laravel protection (auto traps /.env, /telescope, /storage/logs, protects /api/v1/*)
./miragewaf --preset laravel http://localhost:8000
# REST API protection (auto traps /api/keys, /swagger/backup.json, protects /api/*)
./miragewaf --preset api http://localhost:3000You can also run with a customized JSON config:
./miragewaf -listen 127.0.0.1:8080 -backend http://127.0.0.1:3000 -config miragewaf.jsonTip
Anti-Port Collision: Miragewaf includes an automatic port collision detector. If you accidentally point the proxy -listen address to the exact same port as your -backend on localhost, Miragewaf will stop with a helpful error message to prevent self-loop crashes.
Route requests through the listener to test behavior:
- Legitimate Browser Request (Simulated with standard browser headers):
curl -i -H "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36" -H "Accept: application/json" -H "Accept-Language: en-US,en;q=0.9" http://127.0.0.1:8080/api/users/1 # Returns real database data from the backend
- Bot Request (via Scanner User-Agent or hitting honeypot):
curl -i -H "User-Agent: sqlmap" http://127.0.0.1:8080/api/users/1 # Returns spoofed JSON data matching the template definition
- Honeypot Trap Trigger:
curl -i http://127.0.0.1:8080/admin/backup # Flags the client IP as a bot and returns mock success payload
| Argument | Type | Default | Description |
|---|---|---|---|
[positional] |
string |
none |
Shorthand backend URL (e.g. miragewaf http://localhost:3000) |
-preset |
string |
"" |
Smart preset (wordpress, nextjs, laravel, api, generic) |
-listen |
string |
127.0.0.1:8080 |
Local address to bind proxy listener |
-backend |
string |
http://127.0.0.1:3000 |
Target backend server URL |
-config |
string |
miragewaf.json |
Path to the configuration JSON file |
