Added wp-login filter and jail for Fail2Ban

This commit is contained in:
Mitchell Krog UB1 2017-02-07 16:39:58 +02:00
parent 8288e272dd
commit 7946acf381
7 changed files with 235 additions and 1 deletions

8
.travis.yml Normal file
View file

@ -0,0 +1,8 @@
language: python
cache:
- directories:
- nginx-cache
rvm:
- 2.1
script: ./test-nginx-config.sh
sudo: false

View file

@ -1,4 +1,5 @@
# Fail2Ban Blacklist for Repeat Offenders of Nginx (action.d)
#### also includes wp-login attack filter using [nginx-limit-req] - see lower down
### Author: Mitchell Krog <mitchellkrog@gmail.com>
### Version: 1.1
@ -50,4 +51,12 @@ findtime = 604800 ; 1 week
maxretry = 20
```
# Blocking wp-login.php attacks on Wordpress Sites
See the included /filter.d/nginx-limit-req.conf jail and filter for detecting and blocking wp-login attacks
The original /filter.d/nginx-limit-req.conf file from Fail2Ban is included including a /filter.d/nginx-limit-req.local file with the settings you need to detect and block wp-logins.
An example of the jail settings for your jail.local file is included in the jail.local sample.
This works great at picking up wp-login attacks.
Be sure to add the rate limiting zone to your nginx.conf as per instructions in /filter.d/nginx-limit-req.local
### If this helps you why not [buy me a beer](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=XP2AZ4S5HNAWQ):beer:

View file

@ -0,0 +1,44 @@
# Fail2ban filter configuration for nginx :: limit_req
# used to ban hosts, that were failed through nginx by limit request processing rate
#
# Author: Serg G. Brester (sebres)
#
# To use 'nginx-limit-req' filter you should have `ngx_http_limit_req_module`
# and define `limit_req` and `limit_req_zone` as described in nginx documentation
# http://nginx.org/en/docs/http/ngx_http_limit_req_module.html
#
# Example:
#
# http {
# ...
# limit_req_zone $binary_remote_addr zone=lr_zone:10m rate=1r/s;
# ...
# # http, server, or location:
# location ... {
# limit_req zone=lr_zone burst=1 nodelay;
# ...
# }
# ...
# }
# ...
#
[Definition]
# Specify following expression to define exact zones, if you want to ban IPs limited
# from specified zones only.
# Example:
#
# ngx_limit_req_zones = lr_zone|lr_zone2
#
ngx_limit_req_zones = [^"]+
# Use following full expression if you should range limit request to specified
# servers, requests, referrers etc. only :
#
# failregex = ^\s*\[error\] \d+#\d+: \*\d+ limiting requests, excess: [\d\.]+ by zone "(?:%(ngx_limit_req_zones)s)", client: <HOST>, server: \S*, request: "\S+ \S+ HTTP/\d+\.\d+", host: "\S+"(, referrer: "\S+")?\s*$
# Shortly, much faster and stable version of regexp:
failregex = ^\s*\[error\] \d+#\d+: \*\d+ limiting requests, excess: [\d\.]+ by zone "(?:%(ngx_limit_req_zones)s)", client: <HOST>
ignoreregex =

View file

@ -0,0 +1,16 @@
# Fail2ban filter for detecting abuse against wp-login.php attempts
# Author: Serg G. Brester (sebres)
# https://github.com/fail2ban/fail2ban
# Add into your nginx.conf file the following rate limiting zone
# limit_req_zone $binary_remote_addr zone=wp-login:10m rate=1r/s;
# see jail.local example for the config of this jail
[Definition]
ngx_limit_req_zones = wp-login
failregex = ^\s*\[error\] \d+#\d+: \*\d+ limiting requests, excess: [\d\.]+ by zone "(?:%(ngx_limit_req_zones)s)", client: <HOST>
ignoreregex =

View file

@ -11,4 +11,13 @@ filter = nginxrepeatoffender
banaction = nginxrepeatoffender
bantime = 86400 ; 1 day
findtime = 604800 ; 1 week
maxretry = 20
maxretry = 20
# This is the jail setting for using the Fail2Ban limit-req filter for detecting wp-login attacks
[nginx-limit-req]
enabled = true
port = http,https
filter = nginx-limit-req
logpath = %(nginx_error_log)s
maxretry = 1

114
nginx.conf Normal file
View file

@ -0,0 +1,114 @@
user www-data;
worker_processes auto;
error_log /tmp/error.log;
pid /tmp/nginx.pid;
events {
worker_connections 1024;
multi_accept on;
use epoll;
}
http {
##
# Basic Settings
##
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 90s;
keepalive_requests 1000;
server_tokens off;
client_body_buffer_size 32k;
client_header_buffer_size 1k;
client_max_body_size 50M;
types_hash_max_size 2048;
server_names_hash_bucket_size 64;
server_names_hash_max_size 4096;
large_client_header_buffers 4 16k;
# Our request limiter zone for wp-login attacks
limit_req_zone $binary_remote_addr zone=wp-login:10m rate=1r/s;
# DDos Mitigation
# ***************
# https://www.nginx.com/blog/mitigating-ddos-attacks-with-nginx-and-nginx-plus/
# Limiting the Rate of Requests
limit_req_zone $ratelimited zone=flood:50m rate=90r/s;
# Limiting the Number of Connections
limit_conn_zone $ratelimited zone=addr:50m;
# End Slow conections
#client_body_timeout 5s;
#client_header_timeout 5s;
# use any of the following two
real_ip_header CF-Connecting-IP;
include /etc/nginx/mime.types;
default_type application/octet-stream;
##
# Logging Settings
##
log_format custom '$remote_addr - $http_x_forwarded_for $remote_user $server_port [$time_local] "$request" '
'$status "$http_referer" "$http_user_agent" "$http_header"'
'"$body_bytes_sent" - "$gzip_ratio"';
log_format timedcombined '$remote_addr - $http_cf_connecting_ip $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'PORT:$server_port $request_time $upstream_response_time $pipe "$gzip_ratio"';
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
log_format wordpress '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"'
'PORT:$server_port $request_time $upstream_response_time $pipe "GZIP:$gzip_ratio"';
access_log /var/log/nginx/access.log timedcombined;
error_log /var/log/nginx/error.log;
##
# Gzip Settings
##
gzip on;
gzip_disable "MSIE [1-6]\.";
gzip_vary on;
gzip_static on;
gzip_min_length 20;
gzip_proxied expired no-cache no-store private auth;
gzip_comp_level 7;
gzip_buffers 32 4k;
gzip_http_version 1.1;
gzip_types text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript;
#gzip_types text/plain text/css text/xml text/javascript application/x-javascript application/xml;
##
# Virtual Host Configs
##
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
server {
listen 80;
server_name fakedomain.com;
root /var/www;
limit_conn conn_limit_per_ip 10;
limit_req zone=req_limit_per_ip burst=10 nodelay;
}
}
}

34
test-nginx.sh Executable file
View file

@ -0,0 +1,34 @@
#!/bin/bash
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
NGINX_CONFIG="${DIR}/nginx.conf"
NGINX_CONFIG_LOG="/tmp/nginx-config-check.log"
NGINX_CACHE_DIR="${DIR}/nginx-cache"
NGINX_BINARY="${NGINX_CACHE_DIR}/nginx"
NGINX_DEB_URL="https://nginx.org/packages/ubuntu/pool/nginx/n/nginx/nginx_1.10.0-1~trusty_amd64.deb"
#NGINX_DEB_URL="https://launchpad.net/~ondrej/+archive/ubuntu/nginx-mainline/+build/10448355/+files/nginx-light_1.11.2-1~exp1+deb.sury.org~trusty+3_amd64.deb"
# Download nginx binary, if necessary
mkdir -p ${NGINX_CACHE_DIR}
if [[ ! -f "${NGINX_BINARY}" ]]; then
DEB_TMP_PATH="/tmp/nginx.deb.$$"
DEB_TMP_UNPACKED="/tmp/nginx-deb/"
wget "${NGINX_DEB_URL}" -O "${DEB_TMP_PATH}"
pushd /tmp
mkdir -p "${DEB_TMP_UNPACKED}"
dpkg-deb -R "${DEB_TMP_PATH}" $(basename "${DEB_TMP_UNPACKED}")
cp "${DEB_TMP_UNPACKED}/usr/sbin/nginx" "${NGINX_BINARY}"
popd
fi
chmod +x ${NGINX_CACHE_DIR}/nginx
${NGINX_CACHE_DIR}/nginx -t -c "${NGINX_CONFIG}" 2>${NGINX_CONFIG_LOG}
if [[ $(cat $NGINX_CONFIG_LOG | egrep "syntax is ok" | wc -l) -eq 1 ]]; then
echo "Nginx configuration OK!"
exit 0
else
echo -e "Nginx configuration invalid:\n"
cat ${NGINX_CONFIG_LOG}
exit 1
fi