Reference

Settings Keys and Tables

This page lists the storage the module uses, for administrators who script against the database or Omeka's settings.

Settings keys

All settings are stored in Omeka's global setting table with the prefix traffic_guard_.

Key Type Default Notes
traffic_guard_enabled bool true Master switch.
traffic_guard_mode string normal One of normal, elevated, under_attack. Any other value is treated as normal.
traffic_guard_auto_ban bool true Ban on block decisions.
traffic_guard_auto_ban_ttl_seconds int 3600 Auto-ban duration. Values below 60 are raised to 60. The Settings page edits this in hours.
traffic_guard_trust_xff bool false Use X-Forwarded-For.
traffic_guard_retention_days int 30 Event retention; 0 keeps forever.
traffic_guard_auto_allowlist_private bool true Exempt private and reserved ranges.
traffic_guard_log_allow bool false Log allowed requests.
traffic_guard_per_page int 50 Dashboard page size; minimum 10.
traffic_guard_rate_limits JSON string see below Limits per mode and category.
traffic_guard_thresholds JSON string see below Throttle and block scores per mode.
traffic_guard_window_seconds JSON string {"global":60,"search":60,"api":60,"item":60} Window length per category. Written at install time; there is no admin form for it.

Default traffic_guard_rate_limits:

{
  "normal":       {"global": 120, "search": 20, "api": 60, "item": 80},
  "elevated":     {"global": 80,  "search": 10, "api": 40, "item": 50},
  "under_attack": {"global": 40,  "search": 5,  "api": 20, "item": 25}
}

Default traffic_guard_thresholds:

{
  "normal":       {"throttle": 40, "block": 70},
  "elevated":     {"throttle": 30, "block": 55},
  "under_attack": {"throttle": 20, "block": 40}
}

If a mode or category is missing from the stored JSON, the built-in default for that entry is used.

Database tables

All tables use InnoDB with utf8mb4_unicode_ci. Timestamps are stored in UTC.

tg_rate_windows

Column Type Notes
ip_address VARCHAR(45) Client IP (IPv4 or IPv6).
category VARCHAR(20) global, search, api or item.
window_start DATETIME Start of the 60-second window.
hit_count INT UNSIGNED Requests counted in the window.

Primary key (ip_address, category, window_start).

tg_bans

Column Type Notes
id INT UNSIGNED Auto-increment.
ip_address VARCHAR(45) Banned IP.
reason VARCHAR(128) auto_score or manual.
banned_at DATETIME When the ban was placed.
expires_at DATETIME NULL NULL means permanent.
unbanned_at DATETIME NULL Set when a ban is lifted.
banned_by VARCHAR(128) NULL system for automatic bans.
notes TEXT NULL Notes entered on a manual ban.

A ban is active when unbanned_at IS NULL AND (expires_at IS NULL OR expires_at > NOW()).

tg_events

Column Type Notes
id BIGINT UNSIGNED Auto-increment.
occurred_at DATETIME Inspection time.
ip_address VARCHAR(45) Client IP.
user_agent VARCHAR(512) NULL Truncated to 512 characters.
request_path VARCHAR(512) Path without query string.
category VARCHAR(20) Path category, or banned.
risk_score TINYINT UNSIGNED 0 to 100.
decision VARCHAR(12) allow, throttle or block.
signals JSON NULL Map of signal name to weight, for example {"bot_ua_pattern":30,"rate_exceeded_hard":30}.

Indexed on ip_address, occurred_at and decision.

tg_ua_rules

Column Type Notes
id INT UNSIGNED Auto-increment.
pattern VARCHAR(512) Substring or regular expression without delimiters.
match_type VARCHAR(10) substring or regex.
action VARCHAR(10) allow or block.
priority SMALLINT Lower is checked first; default 100.
label VARCHAR(128) NULL Optional description.
enabled TINYINT(1) Only enabled rules are evaluated. The admin pages always create rules enabled; set to 0 in SQL to disable one without deleting it.
created_at DATETIME Creation time.

Enabled rules are cached in memory per PHP worker. The cache is cleared when a rule is added or deleted through the admin pages; after editing the table directly, restart PHP-FPM (or wait for workers to recycle) for the change to apply everywhere.

tg_ip_allowlist

Column Type Notes
id INT UNSIGNED Auto-increment.
ip_cidr VARCHAR(50) Single IP or CIDR; unique.
label VARCHAR(128) NULL Optional description.
added_at DATETIME When added.
added_by VARCHAR(128) NULL Who added it.

The allowlist is read from the database on every inspected request, so changes apply immediately.

Useful queries

Blocked requests per hour for the last day:

SELECT DATE_FORMAT(occurred_at, '%Y-%m-%d %H:00') AS hour, COUNT(*) AS blocked
FROM tg_events
WHERE decision = 'block' AND occurred_at >= NOW() - INTERVAL 1 DAY
GROUP BY hour ORDER BY hour;

Most common user agents among throttled and blocked requests:

SELECT LEFT(user_agent, 80) AS ua, COUNT(*) AS hits
FROM tg_events
WHERE decision <> 'allow'
GROUP BY ua ORDER BY hits DESC LIMIT 20;

Services for developers

The module registers four services in the service manager: TrafficGuard\Service\IpInspector (IP extraction, CIDR matching, path classification), TrafficGuard\Service\RateLimiter, TrafficGuard\Service\RiskScorer and TrafficGuard\Service\RequestGuard. RequestGuard::inspect($request, $settings) returns allow, throttle or block, and RequestGuard::issueBan($ip, $reason, $ttlSeconds) and liftBan($banId) can be called from other modules. The RequestGuard class declares two protected stub methods, applyCloudflareHeaders() and lookupExternalReputation(), but the inspection pipeline does not call them yet, so overriding them has no effect in this version.

Log in for Support