WireWall

Advanced traffic firewall with VPN/Proxy/Tor detection, rate limiting, and JS challenge

WireWall — Advanced Security & Firewall Module for ProcessWire

Author: Maxim Semenov
Website: smnv.org
Email: maxim@smnv.org

WireWall

If this project helps your work, consider supporting future development: GitHub Sponsors or smnv.org/sponsor.

Version: 1.14.0 | Requires: ProcessWire 3.0.200+, PHP 8.1+

Apple Private Relay

Allow verified Apple Private Relay is disabled by default. When explicitly enabled, only an address in Apple's official egress-IP feed is exempt from automatic proxy/VPN and datacenter classification. A browser name, ASN label, forwarded header or login URL does not grant this exception. Explicit IP/ASN blocks, emergency rules, temporary bans, rate limits, geographic restrictions, request challenges, global rules and application authentication still apply.

The feed is fetched over verified HTTPS from one fixed URL, with no redirects, a 24 MB response limit and a ten-second total timeout. No visitor IP is sent to Apple. The validated index is stored outside the document root under the existing private WireWall directory, refreshed at most once daily, and searched locally. A failed refresh is retried no more than once per hour; a verified index may remain usable for seven days, after which the normal proxy policy applies. Concurrent requests do not wait for a refresh lock. PHP cURL and a writable private directory are required. Before enabling this on a production site, prewarm and verify the index from an authorized ProcessWire CLI bootstrap:

$result = $modules->get('WireWall')->refreshAppleRelayRanges();
// Require available=true, a recent fetched_at and a nonzero range_count.

The first request after a daily refresh becomes due can spend up to ten seconds fetching the feed; the protected last-good index remains available to concurrent requests. Refresh failure never creates an allow-all fallback. The feature follows Apple's documented IP-range identification.

Enterprise-grade firewall for ProcessWire CMS with geo-blocking, bot protection, rate limiting, VPN/Proxy/Tor detection, JS challenge, and a real-time admin dashboard.


Features


Geographic Control

  • Country blocking — blacklist or whitelist entire countries (200+)
  • City blocking — block specific cities (requires GeoLite2-City)
  • Subdivision / region blocking — block states, provinces, oblasts (requires GeoLite2-City)
  • MaxMind GeoLite2 — fast local geolocation (Country, ASN, City databases)
  • HTTP API fallback — automatic fallback to ip-api.com when MaxMind unavailable
  • IPv4 / IPv6 — full support with CIDR notation

Bot Protection

  • Bad bot blocking — scrapers, scanners, vulnerability tools (wget, curl, sqlmap, nikto…)
  • AI bot blocking — GPTBot, ClaudeBot, GrokBot, Perplexity, Google-Extended…
  • Search engine control — block or allow Googlebot, Bingbot, Yandex, Baidu
  • Custom bot patterns — define your own User-Agent block list
  • Fake browser detection — advanced UA analysis, missing header checks, Chrome version heuristics
  • Headless browser detection — Puppeteer, Playwright, Selenium, PhantomJS

Security

  • Rate limiting — requests per minute per IP, configurable ban duration
  • Local-first IP intelligence — MaxMind/ASN baseline, optional IP2Proxy LITE BIN, and optional cached HTTP enrichment
  • Risk-class policies — separate allow/challenge/block actions for privacy relay, consumer VPN, datacenter proxy, Tor, unknown proxy, and residential proxy signals
  • Sensitive-route escalation — tighten classified traffic on login, checkout, forms, and API paths
  • Datacenter blocking — AWS, Google Cloud, DigitalOcean, Azure, OVH, Hetzner, Akamai…
  • ASN blocking — block entire networks by autonomous system number
  • JavaScript challenge — transparent challenge for suspicious requests
  • URL / User-Agent trigger rules — add strikes or immediately ban IPs when request URLs, query strings, or User-Agents match suspicious patterns
  • Scanner trigger preset — optional immediate bans for obvious .env, .git, wp-config, backup, and phpinfo probes
  • Bare block responses — minimal 404/410 responses that cannot execute site analytics
  • Scoped exceptions — known bots and browser compatibility rules no longer bypass unrelated protections
  • Verified search crawlers — configured Googlebot/Bingbot identities use cached forward-confirmed reverse DNS before network heuristics are relaxed
  • Verified monitor providers — configured UptimeRobot, Pingdom, StatusCake, Datadog Synthetics, and New Relic Synthetics requests are checked against official IP feeds before network heuristics are relaxed
  • IP whitelist / blacklist — exact, wildcard, and CIDR support
  • IP spoofing protection — proxy headers (CF-Connecting-IP, Incap, Sucuri) only trusted when REMOTE_ADDR belongs to the CDN's published IP ranges

Dashboard

  • Real-time statistics — blocked/allowed counts, block rate, unique IPs, active bans, cache size
  • Traffic history for AI analysis — daily JSONL files with allowed/blocked requests, URL, referer, UA, country, ASN, and decision reason
  • Protected report downloads — individual JSONL files, date-range ZIPs, last-24-hours export, and AI incident bundles from the dashboard
  • Redacted settings export — download active settings for AI-assisted review without exposing secret-like values
  • Hourly chart — blocked requests over last 24 hours (Chart.js)
  • Top reasons, countries, IPs — bar charts with counts
  • Emergency actions — reversible TTL blocks for IPs, ASNs, countries, and datacenter traffic
  • Profiles and snapshots — preview protection presets, audit changes, download/diff/restore snapshots, and import/export rules
  • Rule simulator — explain allow/block/challenge decisions without sending a real request
  • False-positive and analytics guard — review browser-like broad-rule blocks and warn about analytics-capable 404 responses
  • Crawler policy helper — generate advisory robots.txt rules while keeping firewall controls explicit
  • Optional Squad analysis — send redacted incident context to the installed Squad module and show review-only recommendations
  • Active bans — live list with TTL countdown
  • Recent events — last 50 log entries, sticky header, newest first
  • Light / dark theme — reads PW CSS variables, adapts automatically
  • Installed as separate Process module — Admin → Setup → WireWall

Management

  • 16-level priority system — precise rule ordering
  • File-based cache — scales to 1M+ IPs, no database overhead
  • Cache management UI — per-type stats, clear buttons
  • Dedicated settings storage — canonical wirewall_settings table with automatic migration and ProcessWire config fallback
  • Module-owned API integrations — installed modules can opt authenticated public routes into a namespaced WireWall exception without overwriting administrator-managed paths
  • Detailed logging — country, city, region, ASN, UA in every log entry
  • Retention and alerts — gzip rotation, retention/disk caps, rate-limited email/webhook notifications, and hookable alert payloads

Requirements


ProcessWire3.0.200 or higher
PHP8.1 or higher
MaxMind GeoLite2Optional but strongly recommended
ComposerOptional (required for MaxMind)
IP2Proxy LITE + SDKOptional for local proxy/privacy classification
SquadOptional for in-dashboard AI recommendations

Installation


# 1. Clone into site/modules/
git clone https://github.com/mxmsmnv/WireWall.git /path/to/site/modules/WireWall

# 2. Install in admin
Admin → Modules → Refresh → WireWall → Install

# 3. Install dashboard module
Admin → Modules → Refresh → WireWall Dashboard → Install

# 4. Configure
Admin → Modules → WireWall → Configure

See INSTALL.md for full installation instructions including MaxMind setup.


Quick Configuration


✅ Enable WireWall
✅ Enable Logging
Block Action: Bare 404 (recommended for bot/scanner protection)

Rate Limiting: 10 req/min, 60 min ban
✅ Block Bad Bots
✅ Block AI Bots
✅ Enable per-class proxy/privacy policy
Privacy Relay: Allow
Consumer VPN: Allow
Datacenter Proxy: Block
Tor: Block
IP Intelligence Mode: Local only

Exceptions → Known Bot User-Agents: Googlebot, Chrome-Lighthouse, Bingbot, UptimeRobot, Pingdom, StatusCake, DatadogSynthetics, NewRelicSynthetics (default)
Exceptions → Known Bot ASNs: 15169 (Google), 8075 (Microsoft)
Custom Block Rules → Scanner Trigger Preset: Standard
IP Control → Whitelist: only explicitly trusted office/home/service IPs

Priority System


LevelCheck
0Admin area — always allowed
0.5Trusted ProcessWire AJAX
0.7Logged-in users — always allowed
1IP whitelist
1.5Emergency IP/ASN/country/datacenter TTL rule
2Active temporary ban
2.5URL / User-Agent trigger rules
3Rate limiting (fixed 60-second window)
4IP blacklist
4.5Verify and classify scoped known-bot / compatibility exceptions
5JS challenge (except scoped compatibility clients)
6Local-first proxy/privacy risk class policy
7Datacenter
8ASN blocking
9Global rules (known bots skip bot heuristics, not explicit rules)
10Country blocking
10.5City blocking
10.6Subdivision blocking
11Country-specific rules

MaxMind GeoLite2


WireWall works without MaxMind, but MaxMind is strongly recommended for production. Optional HTTP enrichment is disabled by default so public requests do not depend on third-party APIs.

With MaxMindWithout MaxMind
Speed0.5–2ms100–500ms
Rate limitsNoneApplies
City/region blocking✅❌
Offline operation✅❌
# Download from maxmind.com (free account)
mkdir -p /path/to/site/assets/WireWall/geoip/
cp GeoLite2-Country.mmdb GeoLite2-ASN.mmdb /path/to/site/assets/WireWall/geoip/

cd /path/to/site/assets/WireWall/
composer require geoip2/geoip2

File Structure


/site/modules/WireWall/
├── WireWall.module.php          Main firewall module
├── ProcessWireWall.module.php   Dashboard module
├── src/                         Internal service classes
│   ├── Dashboard/
│   │   └── WireWallDashboardStats.php
│   ├── WireWallMonitorProviderVerifier.php
│   ├── Storage/
│   │   ├── WireWallCacheInspector.php
│   │   ├── WireWallOperationsStore.php
│   │   ├── WireWallTrafficMaintenance.php
│   │   ├── WireWallTrafficHistoryStore.php
│   │   └── WireWallTrafficReportService.php
│   ├── Intelligence/
│   │   └── WireWallIpIntelligenceService.php
│   └── Support/
│       ├── WireWallIpMatcher.php
│       └── WireWallRuleMatcher.php
├── assets/                      Module artwork and packaged UI assets
│   ├── dashboard.css
│   ├── dashboard.js
│   └── WireWall.png
├── README.md
├── INSTALL.md
├── CONFIGURATIONS.md
└── CHANGELOG.md

/site/assets/WireWall/           Public-root data — GeoIP/vendor only
├── geoip/
│   ├── GeoLite2-Country.mmdb
│   ├── GeoLite2-ASN.mmdb
│   ├── GeoLite2-City.mmdb       optional
│   └── IP2PROXY-LITE.BIN        optional
├── vendor/                      Composer dependencies
├── composer.json
└── composer.lock

../SITE-DIRECTORY-wirewall-private/  Private data outside document root
└── traffic/
    ├── traffic-YYYY-MM-DD.jsonl    AI-friendly request history
    └── traffic-YYYY-MM-DD.jsonl.gz rotated history

Traffic History


Enable Save Traffic History in Admin → Modules → WireWall → Configure.

WireWall writes one JSON object per request to daily files:

../SITE-DIRECTORY-wirewall-private/traffic/traffic-YYYY-MM-DD.jsonl

This is separate from the ProcessWire log and is designed for later traffic analysis. Each row includes time, allow/block status, reason, IP, country, city/region when available, ASN, method, URL path/query, referer, User-Agent, and selected browser headers. Admin pages, logged-in users, CLI requests, and trusted module/API bypasses are not recorded.

Authorized users can open Admin → Setup → WireWall to:

  • download today, yesterday, the last 24 hours, or any individual daily JSONL file;
  • create a ZIP for a selected date range;
  • create an AI incident bundle containing redacted settings, traffic, a summary, and handling notes.

The traffic directory is outside the document root and its files use private filesystem permissions. Report routes require the wirewall-dashboard permission. Set $config->wireWallPrivateDataPath to an absolute path when the default sibling directory is not suitable for the host.

Settings Storage and Export


WireWall stores its canonical configuration in the wirewall_settings database table. Existing ProcessWire module configuration is imported automatically and kept synchronized as a fallback. The firewall runtime and dashboard both read through WireWall::getWireWallSettings().

Use Download settings for AI from the settings screen or dashboard for a redacted JSON snapshot. Keys that look like tokens, passwords, credentials, private keys, secrets, or API keys are replaced automatically.


Troubleshooting


Admin area blocked — WireWall never blocks the admin by design. If you cannot access admin, check server-level firewall rules, not WireWall.

Legitimate traffic blocked — use IP Whitelist only for a tightly controlled full bypass. For bots, add the UA/IP/ASN to the scoped Known Bot fields. For browser-header quirks, use Browser / Client Compatibility Exceptions. Review Admin → Setup → Logs → wirewall.

Search engines blocked — add Googlebot / Bingbot to Known Bot User-Agents and AS15169 / AS8075 to Known Bot ASNs. These rules do not bypass rate limits, triggers, network checks, geo policy, or explicit blocks.

PageSpeed Insights blocked by network rules — add Chrome-Lighthouse to Known Bot User-Agents and AS15169 to Known Bot ASNs. WireWall requires forward-confirmed reverse DNS under *.google.com before the scoped exception can skip proxy, datacenter, and ASN checks.

Synthetic monitor blocked by datacenter rules — add the service UA to Known Bot User-Agents. WireWall verifies UptimeRobot, Pingdom, StatusCake, Datadog Synthetics, and New Relic Synthetics requests against official IP feeds before letting them skip datacenter/proxy/ASN heuristics.

MaxMind not detected — verify .mmdb files are in /site/assets/WireWall/geoip/ and composer autoload exists at /site/assets/WireWall/vendor/autoload.php.

AJAX broken — add the path to Custom Trusted AJAX Paths, or use Custom API Paths for REST endpoints. Last resort: enable "Disable AJAX Protection Completely".

Behind Cloudflare / CDN — set $config->wireWallTrustProxy = true and $config->wireWallProxyHeader = 'HTTP_CF_CONNECTING_IP' in config.php.


Security Notes


WireWall is one layer of a defence-in-depth strategy. It does not replace:

  • ProcessWire / PHP updates
  • HTTPS / SSL
  • Server hardening (SSH, OS firewall)
  • Application-level protections (SQL injection, XSS)
  • DDoS mitigation at network level

License


MIT License. See LICENSE for details.

See CHANGELOG.md for version history.

More modules by Maxim Semenov

  • Context

    Export ProcessWire site context for AI development (JSON + TOON formats)
  • Ichiban (SEO control center)

    Comprehensive SEO module: meta/OG/schema, audit, redirects, revisions, email reports.
  • Mercato

    ProcessWire-native commerce toolkit: products, cart, checkout, orders, payments, discounts, fulfilment, inventory, recovery, reports, and demo storefront.
  • WireWall

    Advanced traffic firewall with VPN/Proxy/Tor detection, rate limiting, and JS challenge
  • Cookie

    Privacy & cookie consent management: banner, category-based async loading of scripts/embeds, consent log, Google Consent Mode v2, visual widget builder.
  • Ally (a11y)

    Self-hosted accessibility widget powered by Sienna (MIT). Adds font, contrast, language, and navigation tools to any page. No external CDN — the JS bundle is served from your own server.
  • Subscribe

    Newsletter subscription handler with lists, double opt-in, honeypot, rate limiting and unsubscribe link.
  • Squad

    AI integration for ProcessWire. Supports Anthropic, OpenAI, Google, xAI, and OpenRouter.
  • Dimensions

    Stores product dimensions (L×W×H) and weight with selectable units of measurement.

All modules by Maxim Semenov

Install and use modules at your own risk. Always have a site and database backup before installing new modules.