Block malicious IP behind reverse proxy with Apache2 and Crowdsec

Block IP crowdsec apache2 x-forwarded-for

Purpose

Block malicious incoming IP with Apache2 behind a reverse proxy using X-Forwarding-For and Crowdsec solution.
It’s not a Crowdsec help installation. Read the documentation for that :D, browse Internet, we hope you already know the solution.

You need to have a Apache2 installation of course.

Architecture

Configuration

Your web server is behind a reverse proxy and the only IP he see is the reverse proxy one. You need to activate X-Forwarded-For HTTP header to add client IP in HTTP query. Now, you need to configure Apache2 to logs X-ForWarded-For IP instead of reverse proxy IP. There is multiple example on Internet but basically you can replace :

LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined

by

LogFormat "%{X-Forwarded-For}i %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined

in apache2.conf/httpd.conf

Now you can install Crowdsec to your server to protect you from attack. Here is the documentation : install crowdsec

Normally Crowdsec install the right Collections (parsers and scenarios) to ingest your Apache2 logs (access.log).

# cscli collections list

check you see Apache2, base-http-scenario, http-cve

# cscli parsers list

check you see apache2-logs, dataparse-enrich, goip-enrich, http-logs, syslog-logs

# cscli scenarios list

a lot …

At this point Crowdsec will process the logs and make decisions/alerts (# cscli metrics).
Now we are going to install custom-bouncer in Crowdsec, all is here https://doc.crowdsec.net/docs/bouncers/custom/.
When the installation is done we are going to create a folder

# mkdir /etc/crowdsec/custom-script

and add this script blocklist.sh with vi, vim , nano …

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
 #!/bin/bash
# 0x25

logpath='/tmp/blocklist.log'
filepath='/etc/apache2/blocklist.txt'
tmpfilepath='/tmp/blocklist.tmp'

action=''
ip=''
duration=''
reason=''
json=''

# check action
if [[ "$1" != "add" && "$1" != "del" ]]; then
echo "$(date) - Error: first arg need to be add or del - $@" >> $logpath
exit 1
fi
action=$1

# check IP IPV4
if ! [[ "$2" =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
echo "$(date) - Error: seconf arg need to be an IPv4 - $@" >> $logpath
exit 1
fi
ip=$2

# check time
if ! [[ "$3" =~ ^[-0-9]+$ ]]; then
echo "$(date) - Error: third arg need to be an integer - $@" >> $logpath
exit 1
fi

duration=$3
reason=$4
json=$5


if [[ "$action" == "add" ]]; then
# Add IP
if ! grep -q -F $ip $filepath; then
echo "$(date) - Info: add $ip" >> $logpath
echo "$ip b" >> $filepath
else
echo "$(date) - Warning: add $ip already exist" >> $logpath
fi
else
# Del IP
echo "$(date) - Info: del $ip" >> $logpath
pattern="$ip b"
sed "/$pattern/d" $filepath > $tmpfilepath
cp $tmpfilepath $filepath
fi

disable script log in production

# chmod +x blocklist.sh

configure the custom-bouncer by editing the file

# /etc/crowdsec/bouncers/crowdsec-custom-bouncer.yaml.local

it depend on your installation but if the file not exist edit the file without .local

Edit

bin_path: /etc/crowdsec/custom-script/blocklist.sh
api_key: <follow doc>

now restart crowdsec

# systemctl restart crowdsec.service

Normally you will see a file in /etc/apache2/ with name bloacklist.txt with data like

blocklist

1.2.3.4 b
2.3.4.5 b
...

If there is no file you need to check the logs (Crowdsec custom bouncer and blocklist.sh)

Now we need to configure Apache2 to use this list and block income traffic \o/

install modrewrite

# a2enmod rewrite

edit apache2.conf/httpd.conf and add

active "AllowOverride All"

add

1
2
3
4
RewriteEngine On
RewriteMap blocklist txt:/etc/apache2/blocklist.txt
RewriteCond ${blocklist:%{HTTP:X-Forwarded-For}} ^b$ [NC]
RewriteRule .* - [F,L]

/!\ change apache 2 to httpd if needed

restart apache2

# systemctl restart apache2

and it is finish :), have fun.

demo