Skip to content

Commit 8d2460a

Browse files
committed
Swap mod_evasive with mod_shield
1 parent 0a53b80 commit 8d2460a

File tree

3 files changed

+198
-1
lines changed

3 files changed

+198
-1
lines changed

docs/.vuepress/config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ module.exports = {
180180
children: [
181181
"admin/Apache",
182182
"admin/PHP-FPM",
183-
"admin/Evasive",
183+
"admin/Shield",
184184
"admin/ModSecurity",
185185
"admin/Fortification",
186186
"admin/Audit"

docs/admin/Shield.md

Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
---
2+
title: Brute-force protection
3+
4+
---
5+
6+
**New in 3.2.48**
7+
mod_shield is an advanced bean counter that tracks HTTP requests, status codes, and response times over a large window to discriminate against malicious actors. When an IP address exceeds the point threshold within the duration, a configurable response is immediately returned and information is emitted from syslog to fail2ban, which allows [Rampart](../FIREWALL.md) to respond to to the incident. Additionally a file named */tmp/dos-IP* is created marking the event.
8+
9+
Requests are tracked by two methods: same URI and same site. An IP which exceeds either limit is blocked in the same manner.
10+
11+
## Configuration
12+
13+
`apache.shield` [Scope](Scopes.md) manages mod_shield parameters. This Scope interacts with /etc/httpd/conf.d/shield.conf and adds a 2 minute delay to reloading HTTP configuration.
14+
15+
*Apache directives are parenthesized for each named directive.*
16+
17+
### Page tracking
18+
19+
Same URI tracks the full URI provided to Apache. When `canonical` (`DOSCanonical on|off`) is enabled (default), query strings are truncated from the request: */foo* is the same as */foo?bar=baz* and */foo?quu=qux&bar=baz*.
20+
21+
`page-count` (`DOSPageCount AMOUNT`) and `page-interval` (`DOSPageInterval SECONDS`) control hit count and window. Recommended settings are a low interval and count greater than interval.
22+
23+
```bash
24+
cpcmd scope:set apache.shield page-count 20
25+
cpcmd scope:set apache.shield page-interval 5
26+
```
27+
28+
Above triggers protection if more than a score of 20 is reached on the same URI within 5 seconds.
29+
30+
### Page deadlines
31+
32+
Scoring may be adjusted if a response takes longer than *n* seconds using `shield-deadline` (`DOSPageDeadline DURATION SCORE|off`). Score may be any whole number, positive or negative. Deadlines are additive. Each page request always generates 1 point. Setting `off` disables this feature.
33+
34+
```bash
35+
# Any page that loads below 250 ms receives a -2 score
36+
cpcmd scope:set apache.shield-deadline 0 -2
37+
# Ignore any page that loads under 500 ms
38+
cpcmd scope:set apache.shield-deadline 0.250 0
39+
# Any page that loads above 500 ms is scored 1 extra point
40+
cpcmd scope:set apache.shield-deadline 0.500 1
41+
# Alternative form
42+
cpcmd scope:set apache.shield-deadline '[0:-2, 0.250:0, 0.500:1]'
43+
44+
# Cancel 250 ms score
45+
cpcmd scope:set apache.shield-deadline 0.250 null
46+
# Reset scoring to default
47+
cpcmd scope:set apache.shield-deadline null
48+
# Disable all deadline scoring
49+
cpcmd scope:set apache.shield-deadline false
50+
# Accepted for interoperability
51+
cpcmd scope:set apache.shield-deadline off
52+
```
53+
54+
### Site tracking
55+
56+
Site tracking ignores URI distinctions and looks at all requests originating from an IP against a HTTP hostname. */foo* and */bar* both accumulate hits.
57+
58+
`site-count` (`DOSSiteCount AMOUNT`) and `site-interval` (`DOSSiteInterval SECONDS`) control hit count and window. This ratio *must* be higher than page-based accumulation. Setting a high interval or low count will trigger false positives at a much higher rate, especially in plugin-dependent Web Applications, such as WordPress.
59+
60+
```bash
61+
cpcmd scope:set apache.shield site-count 300
62+
cpcmd scope:set apache.shield site-interval 2
63+
```
64+
65+
Above triggers protection if more than 300 requests are made within 2 seconds.
66+
67+
### Status penalties
68+
69+
Scoring may be adjusted for any HTTP response code, such as a 304, 403, 404 or even a custom status like [418 I'm a teapot](https://en.wikipedia.org/wiki/Hyper_Text_Coffee_Pot_Control_Protocol) using `shield-status` (`DOSPageStatus STATUS SCORE|off`).. Status codes are evaluated from the *final* response in a processing pipeline.
70+
71+
```bash
72+
# Add 50 points if HTTP status code is 418
73+
cpcmd scope:set apache.shield-status 418 50
74+
# Remove penalty for 302, "0" works as well
75+
cpcmd scope:set apache.shield-status 302 false
76+
# Add a -5 point adjustment for 204, not modified
77+
cpcmd scope:set apache.shield-status 204 -5
78+
# Reset scoring to default
79+
cpcmd scope:set apache.shield-status null
80+
# Disable all deadline scoring
81+
cpcmd scope:set apache.shield-status false
82+
# Accepted for interoperability
83+
cpcmd scope:set apache.shield-status off
84+
```
85+
86+
### Status handler
87+
88+
A separate status handler named `shield-status` is available. Settings, active blocks, and individual counters for same-page and site resources are provided.
89+
90+
It may be activated with the following directives in `/etc/httpd/conf/httpd-custom.conf`:
91+
92+
```makefile
93+
<Location /shield>
94+
SetHandler shield-handler
95+
# It's a good idea to limit traffic to your IP.
96+
# Accepts CIDR-style
97+
Require ip your.ip.address
98+
</Location>
99+
```
100+
101+
![Shield sample handler](./images/shield-handler.png)
102+
103+
104+
### Empirical estimates
105+
106+
Running a site through webpagetest.org or using [DevTools](https://developers.google.com/web/tools/chrome-devtools) to see the average number of subrequests per page view can help you estimate a good baseline for your site. An ideal setting allows typical usage while disabling atypical extremes: bots don't adhere to netiquette when brute-forcing credentials. Some protection is necessary.
107+
108+
### Disabling per site
109+
110+
Shield may be disabled directly with `DOSEnabled off` or indirectly by setting *apache*,*shield*=0 for the site.
111+
112+
#### Direct disablement
113+
Create a file named `custom` in `/etc/httpd/conf/siteXX` where *siteXX* is the site ID for the domain. `get_site_id domain.com` from command-line will help you locate this value. Within `custom` add:
114+
115+
`DOSEnabled off`
116+
117+
Then rebuild and reload, `htrebuild && systemctl reload httpd`.
118+
119+
#### Indirect
120+
```bash
121+
EditDomain -c shield,shield=0 domain.com
122+
```
123+
124+
## Status handler
125+
126+
127+
## Filtering individual resources
128+
129+
mod_shield is context-aware using Apache directives. For example, Shield ships with a filter to restrict POST attempts to xmlrpc.php and wp-login.php. `cpcmd config:set apache.shield-wordpress-filter true` enables this filter with a very stringent post rate of 3 attempts in 2 seconds.
130+
131+
As an example, the following rule applies to files named "wp-login.php", *glob is quicker than regular expression patterns by a factor of 5-10x!* If the request method isn't a POST, disable bean counting. If more than 3 POST attempts to the same resource occur within a 2 second interval, then return a `DOSHTTPStatus` response (429 Too Many Requests) and log the message via syslog to /var/log/messages. fail2ban will pick up the request and place the IP address into the temporary ban list.
132+
133+
# Block wp-login brute-force attempts
134+
<Files "wp-login.php">
135+
<If "%{REQUEST_METHOD} != 'POST'">
136+
DOSEnabled off
137+
</If>
138+
DOSPageCount 3
139+
DOSPageInterval 2
140+
</Files>
141+
142+
### Customizing
143+
144+
Copy `resources/templates/rampart/shield/wordpress-filter.blade.php` to `config/custom/resources/templates/rampart/shield/wordpress-filter.blade.php` creating parent directory structure as necessary:
145+
146+
```bash
147+
cd /usr/local/apnscp
148+
install -D -m 644 resources/templates/rampart/shield/wordpress-filter.blade.php config/custom/resources/templates/rampart/shield/wordpress-filter.blade.php
149+
```
150+
151+
**First time** use requires regeneration of cache or restart of ApisCP,
152+
153+
```bash
154+
cd /usr/local/apnscp
155+
./artisan config:clear
156+
```
157+
158+
## Adjusting cache size
159+
160+
Shield implements a cyclic shared buffer - default 512 KB - for each tracking criteria (site, page, and blocks). Each record is 176 bytes allowing for 2,978 unique entries that covers approximately 25 unique requests/second over a 2 minute tracking window.
161+
162+
Cache backend and size are both modifiable. [Redis](https://httpd.apache.org/docs/2.4/mod/mod_socache_redis.html) and [Memcached](https://httpd.apache.org/docs/2.4/mod/mod_socache_memcache.html) may be used to share hit data across servers. Latency spikes during locking may occur with either backend.
163+
164+
`cpcmd config:set apache.shield cache-size N` will adjust the cache size. If no unit is specified, KB is assumed. If a cache provider other than shmcb is active, this setting has no effect.
165+
166+
Cache size can also be set directly in `httpd-custom.conf`.
167+
168+
```
169+
# Resize cache size to 1 MB
170+
DOSCache shmcb:none(1048576)
171+
```
172+
173+
174+
## Proxy Compatibility
175+
176+
Shield may pierce a downstream proxy applying the block directly against the client IP. IPs blocked in this manner cannot be blocked by firewall but will continue to report an error code without further request processing.
177+
178+
### Cloudflare
179+
180+
mod_cloudflare updates the IP address of a request in `ap_hook_post_read_request()` before `ap_hook_access_checker()`; thus, at evaluation `rec->useragent_ip` reflects the upstream IP.
181+
182+
183+
### Others
184+
185+
[mod_remoteip](https://httpd.apache.org/docs/2.4/mod/mod_remoteip.html) defines a set of trusted downstream proxies for which the forwarded IP is truthful. Support may be added in [httpd-custom.conf](Customizing.md#Apache).
186+
187+
```
188+
LoadModule remoteip_module modules/mod_remoteip.so
189+
# Header downstream sends connecting IP
190+
RemoteIPHeader X-Client-IP
191+
RemoteIPTrustedProxy 4.4.4.4
192+
```
193+
194+
::: info Trusting internal network addresses
195+
`RemoteIPTrustedProxy` discards any internal network ranges (10/8, 172.16/12, 192.168/16, 169.254/16, 127/8 or outside IPv6 public 2000::/3 block). Specify [`RemoteIPInternalProxy`](https://httpd.apache.org/docs/2.4/mod/mod_remoteip.html#remoteipinternalproxy) instead if your network topology includes internal networks also subject to filtering.
196+
:::
197+
551 KB
Loading

0 commit comments

Comments
 (0)