Key Features
- Multi-layered Security Rules:
- IP Address/CIDR (with priority for exact IP match over subnet).
- User-Agent (types: contains, exact match, regular expression).
- Referrer (types: contains, exact match, regular expression).
- Request URI (types: contains, exact match, regular expression, starts with; with or without query string matching).
- Flexible Rule Actions: Block (403), CAPTCHA, Allow.
- Local CAPTCHA: Numeric, with a "first/last 3 digits" task from a 6-digit image, session-based.
- Logging System: Detailed WAF trigger logs, configurable modes (`full`, `triggered`, `off`), automatic old log cleanup.
- Daily Reports: Aggregated statistics on WAF events, rule types, search engine bot hits, top N offenders (in JSON).
- Management Interface (CMP): Tabs for logs, each rule type, and reports; create, edit, enable/disable, delete rules.
Installation
- Upload the component package via the "Installer" (Extras -> Installer) in the MODX manager.
- Find the "IskWaf" package and click "Install".
- Follow the on-screen instructions.
Configuration
After installing the component, you need to configure a few system settings and create a page for CAPTCHA.
1. System Settings
Find them in "System" (cog icon) -> "System Settings", selecting the iskwaf
namespace.
Key |
Description |
Possible Values/Action |
iskwaf_iskwaf_captcha_resource_id |
MODX Resource ID for displaying the CAPTCHA page. |
Create a new MODX resource (e.g., with alias captcha-verify ), ensure it is not cacheable. In the "Resource Content" field, place the snippet call [[!IskWafCaptcha]] . Specify the ID of this resource here. |
iskwaf_iskwaf_option_log |
WAF Logging Mode. |
full : All requests are logged (triggered rules + normal visits).
triggered : (Default if empty) Only requests that trigger a rule are logged.
off : Logging is disabled (but rules continue to operate).
|
iskwaf_iskwaf_log_retention_days |
Number of days to keep records in the iskwaf_logs log. Old records are deleted by a CRON script. |
Number (e.g., 7 , 30 ). Default in script: 7. |
2. CAPTCHA Page
As mentioned above, create a MODX resource to display the CAPTCHA. It should be non-cacheable and contain the snippet call [[!IskWafCaptcha? &tpl=`your_form_chunk_name`]]
(the `&tpl` parameter is optional, defaults to `iskWafCaptchaFormTpl`).
3. CRON Jobs
For automatic report generation and old log cleanup, set up two CRON jobs:
Cleaning up old logs:
- Script:
core/components/iskwaf/elements/cron/clear_log.php
(path may vary slightly)
- Frequency: Recommended once daily.
- Example command:
/usr/bin/php /path/to/your/site/core/components/iskwaf/elements/cron/clear_log.php
Generating daily reports:
- Script:
core/components/iskwaf/elements/cron/generate_daily_report.php
(check path)
- Frequency: Recommended once daily, after midnight (e.g., at 00:05).
- Example command:
/usr/bin/php /path/to/your/site/core/components/iskwaf/elements/cron/generate_daily_report.php
Ensure the paths to the PHP interpreter and scripts are correct for your server.
Usage (CMP)
Access the IskWaf management interface via the main MODX manager menu (usually in the "Extras" or "Applications" section).
- "Logs" Tab: View all WAF log entries with search functionality.
- Rule Tabs (IP, User-Agent, Referrer, Request URI): Manage rules of the respective type. You can create, edit, enable/disable, and delete rules.
- Pattern: The main value for comparison (IP/CIDR, User-Agent string, etc.).
- Pattern Type: How to interpret the pattern ("contains", "exact match", "regular expression", "starts with").
- Match Query String (for URI rules): Flag to apply the pattern to the entire URI or only the path.
- Rule Type (Action):
block
, allow
, captcha
.
- "Report" Tab: View daily summary reports.
Rule Types (Detailed)
IP Rules
Designed to block, allow, or show CAPTCHA based on the visitor's IP address or CIDR subnet.
- Fields:
IP/CIDR
, Rule Type (action)
, Description
, Active
.
- Priority Logic: An exact IP match takes precedence over a CIDR subnet. Among CIDR subnets containing the same IP, the narrower one (largest mask) takes precedence.
Pattern Examples for IP/CIDR
:
- Single IPv4:
192.168.1.100
- IPv4 CIDR (subnet):
10.0.0.0/8
- IPv4 CIDR (smaller subnet):
192.168.1.0/24
- Single IPv6:
2001:db8:1234:5678::1
- IPv6 CIDR:
2001:db8::/32
User-Agent Rules
Allow applying actions based on the User-Agent string sent by the browser or bot.
- Fields:
User-Agent Pattern
(can be TEXT), Pattern Type
, Rule Type (action)
, Description
, Active
.
- Pattern Types:
contains
: User-Agent contains the specified substring (case-insensitive).
exact
: User-Agent exactly matches the specified string (case-insensitive).
regex
: User-Agent matches the specified regular expression (including delimiters and flags, e.g., /BadBot/i
).
Pattern Examples for User-Agent Pattern
:
- Pattern Type:
contains
- Pattern:
AhrefsBot
(will block User-Agents containing "AhrefsBot")
- Pattern:
python-requests
- Pattern Type:
exact
- Pattern:
Mozilla/5.0 (compatible; SpecificUndesirableBot/1.0)
- Pattern Type:
regex
- Pattern:
/^EvilCorp Crawler\/[0-9\.]+/i
(blocks "EvilCorp Crawler/1.0", "EvilCorp Crawler/2.1", etc.)
- Pattern:
/(SemrushBot|MJ12bot)/i
(blocks multiple bots)
- Pattern:
/^$/
(blocks empty User-Agent)
Referrer Rules
Filter requests based on the HTTP Referrer — the page from which the user arrived.
- Fields:
Referrer Pattern
(can be TEXT), Pattern Type
, Rule Type (action)
, Description
, Active
.
- Pattern Types: Similar to User-Agent rules (
contains
, exact
, regex
).
Pattern Examples for Referrer Pattern
:
- Pattern Type:
contains
- Pattern:
spam-site.com
(blocks if "spam-site.com" is in the Referrer)
- Pattern Type:
exact
- Pattern:
http://exact-spam-source.com/some/page.html
- Pattern Type:
regex
- Pattern:
/^https?:\/\/([\w-]+\.)*spammerdomain\.com/i
(blocks everything from spammerdomain.com and its subdomains)
- Pattern:
/^$/
(blocks requests with an empty Referrer. **Caution:** may block legitimate users).
Request URI Rules
Apply actions based on the requested URI (path or full URI with query string).
- Fields:
URI Pattern
(can be TEXT), Pattern Type
, Match Query String
(yes/no), Rule Type (action)
, Description
, Active
.
- Pattern Types:
contains
, exact
, regex
, starts_with
.
- Match Query String: If 'yes' (1), the pattern applies to the entire URI (including parameters after
?
). If 'no' (0), only to the path.
Pattern Examples for URI Pattern
:
- Pattern Type:
exact
, Match Query String: no
- Pattern:
/wp-login.php
(blocks exact path)
- Pattern Type:
starts_with
, Match Query String: no
- Pattern:
/admin-backup/
(blocks access to all URLs starting with /admin-backup/
)
- Pattern Type:
contains
, Match Query String: yes
- Pattern:
eval(
(blocks if eval(
is anywhere in the full URI)
- Pattern:
UNION SELECT
(SQL injection attempt)
- Pattern Type:
regex
, Match Query String: yes
- Pattern:
/(\.\.\/|\.\.\\\\)/
(blocks directory traversal attempts)
- Pattern:
/SELECT.+FROM.+WHERE/i
(simple example of SQL injection detection)
CAPTCHA System
IskWaf uses a local numeric CAPTCHA:
- An image with 6 digits is generated.
- The user is randomly asked to enter either the first three or the last three digits.
- Completion is remembered in the user's session.
- Displayed via the
[[!IskWafCaptcha]]
snippet on a dedicated page (ID specified in system settings). The snippet supports a &tpl
parameter for form chunk customization.
Reporting System
The IskWafReportDaily
table stores a daily summary:
- Report Date.
- Total WAF events, blocks, CAPTCHA displays, allowances by rule.
- Number of triggers for each rule type (IP, User-Agent, Referrer, URI).
- Hits from major search engines (Googlebot, Bingbot, YandexBot, DuckDuckBot, Baiduspider, Applebot).
- Top N blocked IPs and triggered rules (in JSON format).
- Time the summary was generated.
- Reports are generated by the
generate_daily_report.php
CRON script.
Important Notes
- Order of Rule Execution: The plugin checks rules in the sequence: IP -> User-Agent -> Referrer -> Request URI. The first triggered rule determines the action.
- Regular Expressions: When using the "regular expression" pattern type, ensure your expressions are correct and include necessary delimiters and flags (e.g.,
/badbot/i
). Test them thoroughly.
- Visitor's IP Address: Uses
$_SERVER['REMOTE_ADDR']
by default. If your site is behind a reverse proxy (Cloudflare, Nginx, etc.), adapt the logic to get the real visitor IP in the plugin (e.g., via HTTP_X_FORWARDED_FOR
).
- Performance: A large number of complex rules or
full
logging mode on high-traffic sites can impact performance.
- False Positives: There is always a risk. Regularly review logs. It's recommended to test new "aggressive" rules with a non-blocking action first.
Disclaimer
IskWaf is a tool for basic protection and is not a substitute for comprehensive enterprise security solutions or specialized WAF services. Use it at your own risk. It is always recommended to have up-to-date backups of your site.