iskwaf2x — Web Application Firewall for MODX Revolution 2.x

Author: Ivan Sergeevich K. (ivan@iskwaf.com)
Website: iskwaf.ru | iskwaf.com

iskwaf2x is a component for MODX Revolution 2.x that implements a basic Web Application Firewall (WAF) to protect your website from threats, bots, and suspicious activity. It provides flexible rules, logging, reporting, IP geolocation analysis, built-in numeric CAPTCHA, and supports various logging and WAF check modes.

Key Features

  • Flexible multi-layered rules:
    • IP address / CIDR (exact IP match takes priority over subnet)
    • User-Agent: contains, exact, regex
    • Referrer: contains, exact, regex
    • Request URI: contains, exact, regex, starts_with (with or without query string match)
  • Rule actions: Block (403), CAPTCHA, Allow
  • Built-in CAPTCHA: 6-digit numeric, enter 3 digits (first or last), session-based
  • WAF check modes:
    • On every request (default)
    • Once per session
  • Logging system: Modes: `full`, `triggered`, `off`, automatic cleanup (via CRON), can show rules skipped due to "once per session" mode
  • IP geolocation: IP2Location LITE (country, city, ASN, ISP) via a separate CRON job
  • Reports: Daily aggregates of WAF events, top IPs, rules, search bots, geodata
  • Management interface (CMP): Tabs for logs (with geodata), rule types, reports; create, (de)activate, delete, edit rules

Installation

  1. Upload the iskwaf2x-x.y.z.transport.zip package via "Extras → Installer" in MODX 2.x.
  2. Install the iskwaf2x package.
  3. Access the CMP from the MODX manager menu as "iskwaf2x".

Configuration

After installation, configure system settings, create a CAPTCHA page, and prepare GeoIP environment.

1. System Settings

Go to "System" → "System Settings" and select the iskwaf2x namespace.

Key Description Possible values/action
iskwaf2x_captcha_resource_id ID of the MODX resource for the CAPTCHA page Create a new non-cacheable resource and place [[!iskwaf2xCaptcha]] in the content.
Specify its ID here.
iskwaf2x_option_log WAF logging mode
  • full — all requests (default)
  • triggered — only rule-triggered events
  • off — logging is disabled
iskwaf2x_waf_check_mode WAF rule check mode
  • on_every_request — check on every request (default)
  • once_per_session — only once per session
iskwaf2x_log_retention_days How many days to keep logs Number (e.g., 7 or 30)
iskwaf2x_ip2location_download_token Token for IP2Location database downloads Register at lite.ip2location.com, obtain the token, and specify it here
iskwaf2x_ip_analysis_limit_per_run Maximum IPs to analyze per CRON run Number, default 5000
iskwaf2x_ip_analysis_update_interval Days between geodata updates for each IP Number, default 30

2. CAPTCHA Page

Create a non-cacheable resource and insert:
[[!iskwaf2xCaptcha? &tpl=`iskwaf2xCaptchaFormTpl`]]
The &tpl parameter is optional.

3. GeoIP Setup (IP2Location)

  1. Register at lite.ip2location.com, obtain your token, and specify it in iskwaf2x_ip2location_download_token
  2. PHP library should be located in
    core/components/iskwaf2x/lib/ip2location/src/
  3. Create and make writable:
    core/components/iskwaf2x/tmp_db_download/
    core/components/iskwaf2x/geoip_db/
  4. Run the ip2location_download.php CRON script once for initial database download

4. CRON Jobs

Download/update GeoIP databases:
  • Script: core/components/iskwaf2x/elements/cron/ip2location_download.php
  • Frequency: once a month
  • Example: /usr/bin/php /path/to/your/site/core/components/iskwaf2x/elements/cron/ip2location_download.php
Analyze IPs from logs and populate GeoIP:
  • Script: core/components/iskwaf2x/elements/cron/analyze_ip2location_details.php
  • Frequency: every few hours or once a day
Clean up old logs:
  • Script: core/components/iskwaf2x/elements/cron/clear_log.php
  • Frequency: once a day

Usage (CMP)

  • Open the iskwaf2x menu item in the manager.
  • Available tabs: Logs (shows country/city), IP Rules, User-Agent, Referrer, URI, Reports.
  • Create, edit, activate, delete rules and view logs/reports.

Rule Types

IP Rules

  • Fields: IP/CIDR, Action, Description, Active
  • Exact IP takes priority over CIDR. The narrowest subnet wins among CIDR matches.
Examples:
  • Single IPv4: 192.168.1.100
  • IPv4 CIDR: 10.0.0.0/8
  • IPv6 CIDR: 2001:db8::/32

User-Agent Rules

  • Fields: Pattern, Pattern Type ('contains', 'exact', 'regex'), Action, Description, Active
Examples:
  • Type: contains, pattern: AhrefsBot
  • Type: regex, pattern: /^EvilCorp Crawler\/[0-9\.]+/i

Referrer Rules

  • Fields: Pattern, Pattern Type ('contains', 'exact', 'regex'), Action, Description, Active
Examples:
  • Type: contains, pattern: spam-site.com
  • Type: regex, pattern: /^https?:\/\/([\w-]+\.)*spammerdomain\.com/i

Request URI Rules

  • Fields: Pattern, Pattern Type ('contains', 'exact', 'regex', 'starts_with'), Match Query String, Action, Description, Active
Examples:
  • Type: exact, Query String: no, pattern: /wp-login.php
  • Type: starts_with, Query String: no, pattern: /admin-backup/
  • Type: contains, Query String: yes, pattern: eval(

CAPTCHA System

Built-in numeric CAPTCHA: 6 digits, enter 3. Call with [[!iskwaf2xCaptcha? &tpl=`iskwaf2xCaptchaFormTpl`]]. Result stored in session.

Reporting System

Daily aggregates (iskwaf2x_report_daily): WAF events, blocks, CAPTCHAs, allows, rule types, bots, top N IPs and rules (JSON). Generated by a CRON script.

This product includes IP2Location LITE data available from https://lite.ip2location.com.

Important Notes

Please Note

  • Rule order: IP → User-Agent → Referrer → URI. First triggered rule applies.
  • Regex: Use delimiters (e.g. /badbot/i).
  • Visitor IP: Uses $_SERVER['REMOTE_ADDR']. For proxy setups, adapt accordingly.
  • Performance: Large rule sets or full logging mode may affect speed.
  • Check your logs! False positives are possible.

Disclaimer

iskwaf2x is a basic WAF and is not a replacement for corporate security solutions or specialized WAF services. Use at your own risk. Always maintain up-to-date site backups!