Created
December 16, 2019 23:32
-
-
Save icicimov/69456f82e60ea6c53feb341f021fd089 to your computer and use it in GitHub Desktop.
ModSecurity setup for Haproxy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
set -e | |
set -o pipefail | |
#HAPROXY_MAJOR="1.8" | |
#HAPROXY_VERSION="1.8.23" | |
#HAPROXY_MD5="6c35b83a9969449c4b79783a2119551e" | |
#HAPROXY_MAJOR="1.9" | |
#HAPROXY_VERSION="1.9.13" | |
#HAPROXY_MD5="c2364536409044e7cfa646c7e6d2711f" | |
HAPROXY_MAJOR="2.0" | |
HAPROXY_VERSION="2.0.10" | |
HAPROXY_MD5="501f490f0fb6c01099686d2f0e02f644" | |
MODSEC_VERSION="2.9.2" | |
MODSEC_MD5="4d9454efb19269c4288ae408ea438b76" | |
MODSEC_URL="https://www.modsecurity.org/tarball/${MODSEC_VERSION}/modsecurity-${MODSEC_VERSION}.tar.gz" | |
OWASP_MODSEC_VERSION="v3.0.2" | |
OWASP_MODSEC_MD5="9cef8c63937a92dc350275fcf348baab" | |
# Vars in case of modsecurity service setup | |
MODSEC_USER="modsecurity" | |
MODSEC_PORT="12345" | |
MODSEC_WORKERS="10" | |
MODSEC_CAPS="" # eg. "-c pipelining -c async" | |
MODSEC_DEBUG="" # eg. "-d" for debug mode | |
APR_VERSION="1.7.0" | |
APR_UTIL_VERSION="1.6.1" | |
APR_URL="http://apache.mirror.digitalpacific.com.au//apr" | |
APR_COMPILE="n" | |
# Must run as root | |
if [ "$(id -u)" != "0" ]; then | |
echo "This script must be run as root" 1>&2 | |
exit 1 | |
fi | |
# Cleanup | |
function sources_cleanup { | |
rm -rf /usr/src/haproxy /usr/src/modsecurity /usr/src/apr /usr/src/apr-util | |
} | |
# Dependencies | |
function install_dep { | |
DEBIAN_FRONTEND=noninteractive | |
apt install -y --no-install-recommends libexpat1-dev libyajl-dev \ | |
apache2-dev libapr1 libapr1-dev libaprutil1 libaprutil1-dev libldap2-dev \ | |
libsctp-dev libsctp1 uuid-dev libxml2-dev | |
} | |
# APR and APR-UTIL | |
function install_apr { | |
curl -fsSL ${APR_URL}/apr-${APR_VERSION}.tar.gz -o /tmp/apr.tar.gz | |
curl -fsSL ${APR_URL}/apr-util-${APR_UTIL_VERSION}.tar.gz -o /tmp/apr-util.tar.gz | |
mkdir -p /usr/src/apr | |
mkdir -p /usr/src/apr-util | |
tar -xzf /tmp/apr.tar.gz --strip-components=1 -C /usr/src/apr | |
rm /tmp/apr.tar.gz | |
cd /usr/src/apr | |
./configure --prefix=/usr/local/apr | |
make && make install | |
sudo tar -xzf /tmp/apr-util.tar.gz --strip-components=1 -C /usr/src/apr-util | |
rm /tmp/apr-util.tar.gz | |
cd /usr/src/apr-util | |
./configure --prefix=/usr/local/apr-util --with-apr=/usr/local/apr \ | |
--with-openssl=/opt/openssl/include/openssl --with-crypto | |
make && make install | |
rm -rf /usr/src/apr /usr/src/apr-util | |
} | |
# mod-security standalone | |
function install_modsecurity { | |
curl -fsSL ${MODSEC_URL} -o /tmp/modsecurity.tar.gz | |
echo "${MODSEC_MD5} /tmp/modsecurity.tar.gz" | md5sum -c | |
mkdir -p /usr/src/modsecurity | |
tar -xzf /tmp/modsecurity.tar.gz --strip-components=1 -C /usr/src/modsecurity | |
rm /tmp/modsecurity.tar.gz | |
cd /usr/src/modsecurity | |
if [[ "$APR_COMPILE" == [nN0]* ]]; then | |
./configure --prefix=$PWD/INSTALL \ | |
--disable-apache2-module \ | |
--enable-standalone-module \ | |
--enable-pcre-study \ | |
--without-lua \ | |
--enable-pcre-jit \ | |
--with-apxs=/usr/bin/apxs | |
elif [[ "$APR_COMPILE" == [yY1]* ]]; then | |
cp /usr/local/apr/include/apr-1/ap*.h apache2/ | |
cp /usr/local/apr-util/include/apr-1/ap*.h apache2/ | |
./configure --prefix=$PWD/INSTALL \ | |
--disable-apache2-module \ | |
--enable-standalone-module \ | |
--enable-pcre-study \ | |
--without-lua \ | |
--enable-pcre-jit \ | |
--with-apxs=/usr/bin/apxs \ | |
--with-apr=/usr/local/apr | |
fi | |
make -C standalone install | |
mkdir -p $PWD/INSTALL/include | |
cp standalone/*.h apache2/*.h $PWD/INSTALL/include | |
curl -fsSL https://www.haproxy.org/download/${HAPROXY_MAJOR}/src/haproxy-${HAPROXY_VERSION}.tar.gz -o /tmp/haproxy.tar.gz | |
echo "$HAPROXY_MD5 /tmp/haproxy.tar.gz" | md5sum -c | |
mkdir -p /usr/src/haproxy | |
tar -xzf /tmp/haproxy.tar.gz -C /usr/src/haproxy --strip-components=1 | |
rm /tmp/haproxy.tar.gz | |
if [[ "$APR_COMPILE" == [nN0]* ]]; then | |
make -C /usr/src/haproxy/contrib/modsecurity \ | |
MODSEC_INC=/usr/src/modsecurity/INSTALL/include \ | |
MODSEC_LIB=/usr/src/modsecurity/INSTALL/lib \ | |
APACHE2_INC=/usr/include/apache2 | |
elif [[ "$APR_COMPILE" == [yY1]* ]]; then | |
# statically link to apr-1 we built | |
sed -i 's#-lapr-1#/usr/local/apr/lib/libapr-1.a#' /usr/src/haproxy/contrib/modsecurity/Makefile | |
make LDFLAGS="-Wl,--copy-dt-needed-entries" \ | |
-C /usr/src/haproxy/contrib/modsecurity \ | |
MODSEC_INC=/usr/src/modsecurity/INSTALL/include \ | |
MODSEC_LIB=/usr/src/modsecurity/INSTALL/lib \ | |
APACHE2_INC=/usr/include/apache2 \ | |
APR_INC=/usr/local/apr/include | |
fi | |
#mv /usr/src/haproxy/contrib/modsecurity/modsecurity /usr/local/bin/ | |
make -C /usr/src/haproxy/contrib/modsecurity install | |
rm -rf /usr/src/haproxy /usr/src/modsecurity | |
} | |
# OWASP | |
function owasp_modsecurity { | |
mkdir -p /etc/modsecurity/owasp-modsecurity-crs | |
wget -qO/etc/modsecurity/modsecurity.conf https://github.com/SpiderLabs/ModSecurity/raw/v2/master/modsecurity.conf-recommended | |
wget -qO/etc/modsecurity/unicode.mapping https://github.com/SpiderLabs/ModSecurity/raw/v2/master/unicode.mapping | |
wget -qO/tmp/owasp.tar.gz https://github.com/SpiderLabs/owasp-modsecurity-crs/archive/${OWASP_MODSEC_VERSION}.tar.gz | |
echo "$OWASP_MODSEC_MD5 /tmp/owasp.tar.gz" | md5sum -c | |
tar xzf /tmp/owasp.tar.gz --strip-components=1 -C /etc/modsecurity/owasp-modsecurity-crs | |
rm /tmp/owasp.tar.gz | |
find /etc/modsecurity/owasp-modsecurity-crs -name '*.example' -type f \ | |
| while read -r f; do cp -p "$f" "${f%.example}"; done | |
sed -i.example 's/^SecRuleEngine .*/SecRuleEngine On/' /etc/modsecurity/modsecurity.conf | |
sed -i.example 's/^\(SecDefaultAction "phase:[12]\),log,auditlog,pass"/\1,log,noauditlog,deny,status:403"/' \ | |
/etc/modsecurity/owasp-modsecurity-crs/crs-setup.conf | |
find /etc/modsecurity/owasp-modsecurity-crs -maxdepth 1 -name '*.conf' -type f \ | |
| sort | sed 's/^/Include /' > /etc/modsecurity/owasp-modsecurity-crs.conf | |
find /etc/modsecurity/owasp-modsecurity-crs/rules -maxdepth 1 -name '*.conf' -type f \ | |
| sort | sed 's/^/Include /' >> /etc/modsecurity/owasp-modsecurity-crs.conf | |
} | |
# ModSecurity service setup | |
function setup_modsecurity { | |
id -u $MODSEC_USER 2>&1>/dev/null || useradd -c "ModSecurity User" -r -M -s /bin/false $MODSEC_USER | |
cat > /etc/default/modsecurity <<-EOF | |
# User and Group | |
USER="$MODSEC_USER" | |
GROUP="$MODSEC_USER" | |
# Listen port | |
PORT="$MODSEC_PORT" | |
# Number of workers | |
NUM_WORKERS="$MODSEC_WORKERS" | |
# Uncomment for debug mode | |
DEBUG="$MODSEC_DEBUG" | |
# Config files to load | |
EXTRAOPTS="-f /etc/modsecurity/modsecurity.conf -f /etc/modsecurity/owasp-modsecurity-crs.conf" | |
# Example for adding capabilities, one or more of fragmentation,pipelining,async | |
# EXTRACAPS="-c fragmentation -c pipelining -c async" | |
EXTRACAPS="$MODSEC_CAPS" | |
EOF | |
sys_init=$(cat /proc/1/comm) | |
# Systemd service | |
[[ $sys_init == "systemd" ]] && { | |
cat > /etc/systemd/system/modsecurity.service <<-'END' | |
[Unit] | |
Description=Haproxy modsecurity-spoa agent | |
After=network.target | |
[Service] | |
User=${USER} | |
Group=${GROUP} | |
PermissionsStartOnly=true | |
UMask=0007 | |
KillMode=process | |
Restart=on-failure | |
RestartSec=10 | |
NoNewPrivileges=true | |
CapabilityBoundingSet=CAP_SETGID CAP_SETUID CAP_SYS_RESOURCE | |
RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX | |
EnvironmentFile=/etc/default/modsecurity | |
ExecStart=/usr/local/bin/modsecurity ${DEBUG} -n ${NUM_WORKERS} -p ${PORT} $EXTRACAPS $EXTRAOPTS | |
[Install] | |
WantedBy=multi-user.target | |
END | |
} && systemctl daemon-reload \ | |
&& systemctl start modsecurity.service \ | |
&& systemctl enable modsecurity.service | |
# Upstart service | |
[[ $sys_init == "init" ]] && { | |
cat > /etc/init/modsecurity.conf <<-'END' | |
# Ubuntu upstart file at /etc/init/modsecurity.conf | |
description "Haproxy modsecurity-spoa agent" | |
kill timeout 60 # wait 60s between SIGTERM and SIGKILL. | |
respawn | |
console output | |
pre-start script | |
if [ -f /etc/default/modsecurity ]; then . /etc/default/modsecurity; fi | |
DAEMONUSER=${USER:-modsecurity} | |
DAEMONGROUP=${GROUP:-modsecurity} | |
LOGDIR=${LOGDIR:-/var/log/modsecurity} | |
if [ ! -d ${LOGDIR} ]; then | |
mkdir -p ${LOGDIR} && chown ${DAEMONUSER}:${DAEMONGROUP} ${LOGDIR} | |
fi | |
touch /var/run/modsecurity.pid | |
chown $DAEMONUSER /var/run/modsecurity.pid | |
end script | |
start on runlevel [2345] | |
stop on runlevel [06] | |
script | |
ENABLE_DAEMON="yes" | |
DAEMON=/usr/local/bin/modsecurity | |
DAEMONUSER=${USER:-modsecurity} | |
DAEMONGROUP=${GROUP:-modsecurity} | |
LOGDIR=${LOGDIR:-/var/log/modsecurity} | |
if [ -f /etc/default/modsecurity ]; then . /etc/default/modsecurity; fi | |
DAEMON_OPTS="-- "${DAEMON_OPTS:-"$DEBUG -n $NUM_WORKERS -p $PORT $EXTRACAPS $EXTRAOPTS"} | |
if [ "x$ENABLE_DAEMON" = "xyes" ] | |
then | |
exec start-stop-daemon --start \ | |
--chuid $DAEMONUSER:$DAEMONGROUP \ | |
--pidfile /var/run/modsecurity.pid \ | |
--make-pidfile \ | |
--exec $DAEMON $DAEMON_OPTS >> ${LOGDIR}/modsecurity.log 2>&1 | |
fi | |
end script | |
END | |
} && initctl reload-configuration && initctl start modsecurity | |
} | |
sources_cleanup | |
install_dep | |
[[ "$APR_COMPILE" == [yY1]* ]] && install_apr | |
install_modsecurity | |
owasp_modsecurity | |
setup_modsecurity | |
exit 0 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment