mod_repudiator is an Apache HTTP Server module for reputation-based limiting and blocking of potentially malicious clients.
The module evaluates incoming HTTP requests using several reputation sources:
- client IP address and configured IP/network ranges
- User-Agent regular expressions
- requested URI regular expressions
- Autonomous System Number (ASN)
- country code
- HTTP response status codes
- request frequency per IP, network and ASN
Depending on the resulting reputation score, a client is classified as
OK, WARN or BLOCK. Clients in the configurable intermediate range can
optionally be challenged with a Proof-of-Work (POW) challenge.
The module is implemented as an Apache module in C and uses Apache Portable Runtime (APR), libmaxminddb and, optionally, PCRE2.
- Apache HTTP Server module using the Apache module API
- IPv4 and IPv6 support
- configurable reputation rules
- IP/CIDR-based reputation
- User-Agent regex reputation
- URI regex reputation
- ASN-based reputation
- country-based reputation
- HTTP status-based reputation
- request counters per IP, network and ASN
- configurable warning and blocking thresholds
- configurable HTTP response codes
- optional Proof-of-Work challenge
- optional passphrase-based encoding of the POW cookie
- MaxMind database integration for ASN and country lookups
- optional PCRE2 regex engine
X-Reputationresponse header- optional debug logging
- persistent request statistics
- JSON statistics handler
- fail2ban integration
For every request, the module determines the client IP and, when configured, looks up the corresponding ASN and country using MaxMind databases.
The configured reputation components are accumulated and combined with frequency-based penalties.
Conceptually, the resulting score consists of:
basic reputation
+ per-IP reputation
+ per-network reputation
+ per-ASN reputation
+ HTTP-status reputation
The basic reputation is calculated from the configured IP, User-Agent, URI, ASN and country rules.
For repeated requests, the configured per-IP, per-network and per-ASN penalties are applied according to the request counters.
By default, negative values represent undesirable behaviour while positive values can be used to explicitly increase reputation.
| Setting | Default | Meaning |
|---|---|---|
RepudiatorWarnReputation |
-200 |
Warning threshold |
RepudiatorBlockReputation |
-400 |
Blocking threshold |
RepudiatorPerIPReputation |
-0.033 |
Penalty per IP request |
RepudiatorPerNetReputation |
-0.0033 |
Penalty per network request |
RepudiatorPerASNReputation |
-0.00033 |
Penalty per ASN request |
RepudiatorScanTime |
60 |
Request counting interval in seconds |
The module supports both the usual configuration where the block threshold is lower than the warning threshold and the inverse ordering.
Requests whose reputation falls into the configured POW range can be redirected to a challenge endpoint.
The default endpoint is:
/rep-pow-challenge
The challenge contains a random token and a difficulty value. The client has to find a numeric solution whose SHA-256 hash contains at least the required number of leading zero bits.
A successful solution creates the REP-PASSED cookie. The cookie contains the
client IP and is valid for the configured period.
The default POW settings are:
| Setting | Default | Meaning |
|---|---|---|
RepudiatorPOWUri |
/rep-pow-challenge |
POW challenge URI |
RepudiatorPOWCookiePassphrase |
not set |
Optional passphrase for POW cookie encoding |
RepudiatorPOWDifficulty |
16 |
Required leading zero bits |
RepudiatorPOWCookieMaxAge |
3600 seconds |
POW cookie lifetime |
RepudiatorPOWAboveReputation |
-150.0 |
Upper POW reputation boundary |
RepudiatorPOWBelowReputation |
-1000.0 |
Lower POW reputation boundary |
The challenge template is supplied through RepudiatorPOWTemplateFile.
The module also performs basic client-information checks. For example,
clients reporting WebDriver/headless operation, disabled cookies, zero
hardware concurrency, a 0x0 screen resolution or zero colour depth are
rejected by the POW validation path.
The following development packages are required:
- Apache HTTP Server development headers
- GCC or another compatible C compiler
- libmaxminddb development headers
- MaxMind GeoLite2 ASN database
- MaxMind GeoLite2 Country database when country reputation is used
- PCRE2 development headers when PCRE2 support is enabled
The source also includes the following implementation files directly:
json.c
sha256.c
pow_template.c
state_template.c
...
Therefore these files must be available in the source directory when building
mod_repudiator.c.
dnf -y install gcc httpd-devel libmaxminddb-devel pcre2-devel redhat-rpm-configapt -y install gcc apache2-dev libmaxminddb-dev libpcre2-devThe module uses libmaxminddb to obtain:
- ASN information from the
autonomous_system_numberfield - country information from
country.iso_code
The original project documentation recommends obtaining the ASN database
with geoipupdate.
Example configuration:
RepudiatorASNDatabase /path/to/GeoLite2-ASN.mmdb
RepudiatorCountryDatabase /path/to/GeoLite2-Country.mmdbIf no matching MaxMind entry is found, the module falls back to a host-specific
network mask (/32 for IPv4 or /128 for IPv6).
apxs -c -lmaxminddb mod_repudiator.capxs -c -DPCRE2 -lmaxminddb -lpcre2-8 mod_repudiator.cPCRE2 is used instead of the POSIX regex.h implementation when the
PCRE2 preprocessor symbol is defined.
apxs -c -DPCRE2 -DREP_DEBUG -lmaxminddb -lpcre2-8 mod_repudiator.cWith REP_DEBUG, the module emits extended reputation information to the
Apache error log.
A minimal configuration looks like this:
LoadModule repudiator_module modules/mod_repudiator.so
RepudiatorEnabled true
RepudiatorASNDatabase /path/to/GeoLite2-ASN.mmdb
RepudiatorCountryDatabase /path/to/GeoLite2-Country.mmdb
RepudiatorWarnReputation -200
RepudiatorBlockReputation -400The module configuration commands are restricted to server configuration
contexts (RSRC_CONF), i.e. they are intended for the Apache server or
virtual-host configuration.
After changing the Apache configuration, validate it before restarting:
apachectl configtestThen restart Apache using the service mechanism of the operating system, for example:
systemctl restart httpdor:
systemctl restart apache2Enables or disables the module.
Default:
RepudiatorEnabled falseAccepted values:
RepudiatorEnabled true
RepudiatorEnabled falseInvalid values disable the module and are logged as warnings.
Sets the warning threshold.
Default:
RepudiatorWarnReputation -200Sets the blocking threshold.
Default:
RepudiatorBlockReputation -400The threshold comparison adapts to the ordering of the two configured values.
Reputation penalty per request from the same IP within the scan window.
Default:
RepudiatorPerIPReputation -0.033Reputation penalty based on request frequency within the network returned by the MaxMind lookup.
Default:
RepudiatorPerNetReputation -0.0033Reputation penalty based on request frequency within the ASN.
Default:
RepudiatorPerASNReputation -0.00033Defines the request counting interval in seconds.
Default:
RepudiatorScanTime 60ASN and network counters older than twice the scan interval are cleaned up.
Adds a reputation value for an IP address or CIDR network.
The directive can be specified multiple times.
Example:
RepudiatorIPReputation 192.168.0.0/16 1000.0
RepudiatorIPReputation 203.0.113.42 -500.0
RepudiatorIPReputation 2001:db8::/32 -100.0Both IPv4 and IPv6 are supported.
Multiple matching IP rules contribute to the resulting reputation.
Adds a reputation value when the User-Agent matches a regular expression.
Example:
RepudiatorUAReputation ".*MSIE [1-9].0.*" -400.0The regular expression engine is:
- PCRE2 when compiled with
-DPCRE2 - POSIX extended regular expressions otherwise
Adds a reputation value when the requested URI matches a regular expression.
Example:
RepudiatorURIReputation ".*\\.(env|git|bash(rc|_(history|profile))).*" -1000.0Multiple URI rules can be configured.
Adds a reputation value for a specific ASN.
Example:
RepudiatorASNReputation 15169 100.0ASN 0 can be used as a fallback/default ASN rule when no more specific
matching ASN is configured.
Adds a reputation value for a country identified by its ISO country code.
Example:
RepudiatorCountryReputation DE 100.0
RepudiatorCountryReputation CN -100.0Country matching is case-insensitive.
Adds a reputation value based on the HTTP response status.
The accepted status range is 99 through 599.
Example:
RepudiatorStatusReputation 404 -1.0
RepudiatorStatusReputation 500 -10.0The status contribution is evaluated when the response filters process the request.
HTTP status returned when the warning threshold is reached.
Default:
RepudiatorWarnHttpReply 429HTTP status returned when the blocking threshold is reached.
Default:
RepudiatorBlockHttpReply 403Loads an HTML template used when a request reaches WARN or BLOCK.
Example:
RepudiatorStateTemplateFile /path/to/state.htmlThe template can contain the following placeholder:
{JSON}
The placeholder is replaced with JSON containing the current reputation information.
The generated data includes:
{
"state": "warn",
"warn": -200.00,
"block": -400.00,
"ip": 0.00,
"asn": 0.00,
"ua": 0.00,
"uri": 0.00,
"country": 0.00,
"status": 0.00,
"perIp": 0.00,
"perNet": 0.00,
"perASN": 0.00
}The repository is expected to contain example templates in a templates/
directory.
Sets the POW challenge URI.
Default:
RepudiatorPOWUri /rep-pow-challengeExample:
RepudiatorPOWUri /pow-challengeLoads the HTML template used by the POW challenge.
Example:
RepudiatorPOWTemplateFile /path/to/pow.htmlThe template uses the following placeholder:
{TOKEN}
The placeholder receives a Base64 encoded JSON challenge token.
Sets an optional passphrase used to XOR-encode the POW cookie payload before Base64 encoding. If no passphrase is configured, the cookie payload is only Base64 encoded.
Example:
RepudiatorPOWCookiePassphrase change-this-secretThe passphrase is server-side configuration and is not sent to the client. The implementation uses XOR encoding for obfuscation; this setting should not be considered a replacement for authenticated encryption or a cryptographic signature.
Sets the difficulty of the POW challenge. The configured value must be between
1 and 32 inclusive.
Default:
RepudiatorPOWDifficulty 16Example:
RepudiatorPOWDifficulty 8Sets the lifetime of the successful POW cookie in seconds.
Default:
RepudiatorPOWCookieMaxAge 3600Example:
RepudiatorPOWCookieMaxAge 1800Sets the upper reputation boundary of the POW range.
Default:
RepudiatorPOWAboveReputation -150.0Sets the lower reputation boundary of the POW range.
Default:
RepudiatorPOWBelowReputation -1000.0A request enters the POW flow when:
reputation < RepudiatorPOWAboveReputation
AND
reputation >= RepudiatorPOWBelowReputation
The following example combines several reputation sources:
LoadModule repudiator_module modules/mod_repudiator.so
RepudiatorEnabled true
RepudiatorASNDatabase /var/lib/GeoIP/GeoLite2-ASN.mmdb
RepudiatorCountryDatabase /var/lib/GeoIP/GeoLite2-Country.mmdb
RepudiatorWarnReputation -200
RepudiatorBlockReputation -400
RepudiatorPerIPReputation -0.033
RepudiatorPerNetReputation -0.0033
RepudiatorPerASNReputation -0.00033
RepudiatorScanTime 60
RepudiatorWarnHttpReply 429
RepudiatorBlockHttpReply 403
RepudiatorIPReputation 192.168.0.0/16 1000.0
RepudiatorIPReputation 203.0.113.0/24 -100.0
RepudiatorUAReputation ".*MSIE [1-9].0.*" -400.0
RepudiatorURIReputation ".*\\.(env|git|bash(rc|_(history|profile))).*" -1000.0
RepudiatorASNReputation 15169 100.0
RepudiatorCountryReputation DE 100.0
RepudiatorStatusReputation 404 -1.0
RepudiatorPOWUri /rep-pow-challenge
RepudiatorPOWCookiePassphrase change-this-secret
RepudiatorPOWDifficulty 16
RepudiatorPOWCookieMaxAge 3600
RepudiatorPOWAboveReputation -150
RepudiatorPOWBelowReputation -1000
RepudiatorStateTemplateFile /path/to/templates/state.html
RepudiatorPOWTemplateFile /path/to/templates/pow.htmlThe relevant processing path is:
HTTP request
|
v
Client IP detection
|
+--> MaxMind ASN lookup
|
+--> MaxMind country lookup
|
+--> IP reputation rules
+--> User-Agent reputation rules
+--> URI reputation rules
+--> ASN reputation rules
+--> Country reputation rules
|
+--> IP/network/ASN request counters
|
v
Calculate total reputation
|
+--> OK
|
+--> POW range --> POW challenge
|
+--> WARN --> configured warning response
|
+--> BLOCK --> configured blocking response
|
v
Response filters
|
+--> X-Reputation header
+--> HTTP status reputation
The module registers its access checks with Apache and also installs output and
error filters. These filters add the X-Reputation header and feed the final
HTTP response status back into the reputation calculation.
For requests already tracked by the module, the response can contain:
X-Reputation: WARN (-250.00)
Possible states are:
OK
WARN
BLOCK
The header therefore provides a convenient way to expose the current classification and score to downstream components.
mod_repudiator maintains persistent aggregate counters for requests, warnings,
blocks and Proof-of-Work activity, including failed POW client-information checks.
The statistics are stored in the Apache runtime directory in the binary file:
repudiator_stats
The statistics file is accessed with an exclusive/shared file lock, allowing the counters to be updated and read while Apache is running. The module periodically flushes in-process counters to this file.
The module provides the handler names repudiator-stats and
application/x-rep-stats. A GET request returns JSON. For example:
<Location "/repudiator-stats">
SetHandler repudiator-stats
</Location>The response has the following structure:
{
"version": "dev",
"requests": 12345,
"blocked": 42,
"warned": 123,
"powRequests": 456,
"powCIFailed": 7,
"powCompleted": 321,
"updated": 1726500000
}The fields are:
| Field | Description |
|---|---|
version |
Module version reported by REP_VERSION |
requests |
Number of processed requests recorded by the persistent counter |
blocked |
Number of requests classified as BLOCK |
warned |
Number of requests classified as WARN |
powRequests |
Number of POW challenge requests generated |
powCIFailed |
Number of POW submissions rejected by client-information checks |
powCompleted |
Number of successfully completed POW challenges |
updated |
Unix timestamp of the last statistics update |
If the statistics file cannot be opened during module initialization, statistics
processing is disabled and the module logs a warning. The statistics handler then
returns 404.
Security: Do not expose the statistics handler publicly unless the returned aggregate traffic information is intentionally public. Restrict the location with your normal Apache access-control mechanisms when necessary.
The module logs reputation decisions through the Apache error log.
A normal log entry contains information such as:
- client IP
- network mask
- ASN
- country
- hostname
- requested URI
- User-Agent
- reputation state
- total reputation score
A build with REP_DEBUG additionally logs the individual reputation
components and request counters.
The repository can be integrated with fail2ban to ban clients that are reported by the Apache module.
Install the supplied filter:
cp fail2ban/filter.d/apache-mod_repudiator.conf /etc/fail2ban/filter.d/Then add a jail to /etc/fail2ban/jail.local:
[apache-mod_repudiator]
enabled = true
backend = polling
port = http,https
filter = apache-mod_repudiator
logpath = /var/log/httpd/error_log
maxretry = 1
findtime = 120
bantime = 600Restart fail2ban:
systemctl restart fail2banAdjust logpath for systems where Apache uses a different error-log location.
The main implementation is contained in:
mod_repudiator.c
The module directly includes several source files:
json.c
sha256.c
pow_template.c
state_template.c
...
A typical repository layout is:
.
├── mod_repudiator.c
├── json.c
├── sha256.c
├── pow_template.c
├── state_template.c
├── templates/
├── fail2ban/
│ └── filter.d/
│ └── apache-mod_repudiator.conf
└── README.md
The module maintains request, network and ASN counters in dynamically allocated vectors. Network and ASN counters are periodically removed when they have not been seen for twice the configured scan interval.
Configuration cleanup releases the dynamically allocated reputation vectors, regular expressions, request/network/ASN vectors and configured strings. MaxMind databases are registered with APR pool cleanup handlers.
Because the module runs inside the Apache process, memory handling errors can affect the complete Apache worker process. Production deployments should therefore be tested with the intended Apache MPM and representative traffic.
mod_repudiator is a traffic-control mechanism and should be treated as one
layer of a broader security architecture.
Recommended practices include:
- keep MaxMind databases up to date
- carefully test reputation thresholds before enabling blocking
- whitelist trusted networks using positive reputation where appropriate
- test regular expressions against representative User-Agent and URI values
- monitor Apache logs for false positives
- validate Apache configuration before reload/restart
- use fail2ban only after confirming that the generated log events are correct
- test the POW templates and redirect handling before deployment
The module derives its client IP from Apache's request connection information. If Apache is deployed behind a reverse proxy, load balancer or another forwarding layer, the Apache client-IP configuration must be correct before using reputation decisions based on the client address.
A useful development build is:
apxs -c -DPCRE2 -DREP_DEBUG -lmaxminddb -lpcre2-8 mod_repudiator.cAfter installation, verify:
apachectl configtestThen inspect the Apache error log while generating test traffic.
When changing the module, also test the statistics handler and verify that
requests, warned, blocked, powRequests, powCIFailed and powCompleted are updated as
expected. The persistent statistics update is throttled to approximately once per
second.
When changing reputation rules, test at least:
- IPv4 addresses
- IPv6 addresses
- CIDR networks
- matching and non-matching User-Agent rules
- matching and non-matching URI rules
- configured ASN and country rules
- repeated requests inside and outside
RepudiatorScanTime - warning threshold
- blocking threshold
- POW challenge and successful POW cookie
- HTTP status reputation
- response header generation
This program is licensed under the GNU General Public License, version 3 or any later version (GPLv3+).
See the source header and the accompanying LICENSE file for
the complete license text.
This software is provided in the hope that it will be useful, but without any warranty. See the GNU General Public License for the applicable terms and conditions.