|  | 
|  | 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 | + | 
|  | 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 | + | 
0 commit comments