#!/bin/bash
#
# NoLoris 0.1b by Andrei Dragan
#
# TODO
# - 3 modes: relaxed, normal, insane
# - pipe to fw/ipt
# - cloudflare check
# - command line args for modular use
#

if [ "$1" = "screenmon" ];then
tail -f /usr/local/apache/logs/error_log|awk -F'c=' '/error/ && /mod_qos/ && /access denied/ {print$NF}'|grep -oP '[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}' >> /root/ipban
fi
if [ "$(whoami)" != "root" ];then echo "yeah... about that... you need to be root.";exit 1;fi
pwd=$(pwd)
tmpd=/root/.noloris
rm -rf $tmpd
mkdir $tmpd
compat_chk() {
printf "[+] Checking Apache version... "
apv=$(httpd -V|awk -F'/' '/Server version:/ {print$2}')
if [ -n "$(echo $apv|grep ^2)" ];then printf "OK\n";else  printf "$apv is not supported.\n";exit 1;fi
printf "[+] Checking MPM... "
mpm=$(httpd -V|awk '/Server MPM:/ && !(/Event/ || /Worker/) {print$NF}')
if [ -z "$mpm" ];then printf "OK\n";else  printf "$mpm is not supported.\n";exit 1;fi
printf "[+] Checking for firewall... "
if [ -d /etc/firewall -a ! -f /etc/csf/csf.conf ];then fw=HG
elif [ ! -d /etc/firewall -a -f /etc/csf/csf.conf ];then fw=CSF
elif [ ! -d /etc/firewall -a ! -f /etc/csf/csf.conf ];then fw=IPTables
fi
printf "$fw\n"
printf "[+] Checking for previous mod_qos and mod_evasive installations... "
aproot=$(httpd -V|awk -F'"' '/HTTPD_ROOT/ {print$2}')
if [ -f "$aproot/modules/mod_evasive20.so" ];then evasive=1;mods=$(echo $mods mod_evasive);chmod 755 $aproot/modules/mod_evasive20.so;fi
if [ -f "$aproot/modules/mod_qos.so" ];then qos=1;mods=$(echo $mods mod_qos);chmod 755 $aproot/modules/mod_qos.so;fi
if [ -f "$aproot/modules/mod_antiloris.so" ];then antiloris=1;mods=$(echo $mods mod_antiloris);chmod 755 $aproot/modules/mod_qos.so;fi
if [ -z "$mods" ];then printf "None\n";else printf "$mods\n";fi
if [ -n "$antiloris" ];then
printf "[+] Checking for previous mod_antiloris...\n"
grep -Rin '^LoadModule antiloris_module' $aproot/conf/*|while IFS=':' read file line data;do
# search n destroy
if [ ! -f "$tmpd/.com" ];then touch $tmpd/.com;fi
sed -i "${line}s:^:#:" $file
printf "[!!] Line $line commented out in $file ($data)\n"
done
fi
if [ -n "$evasive" ];then
printf "[+] Checking for previous mod_evasive configurations and commenting them out...\n"
egrep -Rni '^LoadModule evasive20_module|^DOS' $aproot/conf/*|while IFS=':' read file line data;do
# search n destroy
if [ ! -f "$tmpd/.com" ];then touch $tmpd/.com;fi
sed -i "${line}s:^:#:" $file
printf "[!!] Line $line commented out in $file ($data)\n"
done
fi
if [ -n "$qos" ];then
printf "[+] Checking for previous mod_qos configurations and commenting them out...\n"
egrep -Rin '^LoadModule qos_module|^QS_' $aproot/conf/*|while IFS=':' read file line data;do
# search n destroy
if [ ! -f "$tmpd/.com" ];then touch $tmpd/.com;fi
sed -i "${line}s:^:#:" $file
printf "[!!] Line $line commented out in $file ($data)\n"
done
fi
if [ ! -f "$tmpd/.com" ];then printf "[+] No configs found.\n";fi
echo "[+] Pre-installation checks done! Proceeding to download and install..."
}

grab_em() {
wget -qq http://www.zdziarski.com/blog/wp-content/uploads/2010/02/mod_evasive_1.10.1.tar.gz -P $tmpd/
#wget -qq http://superb-sea2.dl.sourceforge.net/project/mod-qos/mod_qos-9.79.tar.gz -P $tmpd/
wget -qq http://iweb.dl.sourceforge.net/project/mod-qos/mod_qos-10.13.tar.gz -P $tmpd/
wget -qq http://superb-sea2.dl.sourceforge.net/project/mod-antiloris/mod_antiloris-0.4.tar.bz2 -P $tmpd/
tar zxf $tmpd/mod_ev* -C $tmpd/
tar zxf $tmpd/mod_qos* -C $tmpd/
tar jxf $tmpd/mod_anti* -C $tmpd/
pushd $tmpd/mod_eva*>/dev/null 2>&1 && apxs -ca mod_evasive20.c>/dev/null 2>&1
pushd $tmpd/mod_qos-10*/apache2>/dev/null 2>&1 && apxs -ca mod_qos.c>/dev/null 2>&1
pushd $tmpd/mod_antil*>/dev/null 2>&1 && apxs -ca mod_antiloris.c>/dev/null 2>&1
cp -pvf ${tmpd}/mod_*/{apache2/,}.libs/*.so /usr/local/apache/modules/
}

do_cfg() {
# place our configs delimited so we may replace them later if needed

echo "
#NoLoris Start
LoadModule antiloris_module   modules/mod_antiloris.so
LoadModule evasive20_module   modules/mod_evasive20.so

<IfModule mod_evasive20.c>
DOSHashTableSize 3097
DOSSiteCount 80
DOSSiteInterval 1

DOSPageCount 10
DOSPageInterval 1

DOSBlockingPeriod 600
#DOSSystemCommand "iptables -I INPUT -s %s -p tcp -j REJECT --reject-with tcp-reset"
</IfModule>

LoadModule qos_module modules/mod_qos.so

<IfModule mod_qos.c>
QS_SrvMinDataRate 80 400
QS_SrvMaxConnClose 180
QS_SrvMaxConnPerIP 50
#MaxClients 150
QS_ClientEventBlockCount 20 300
QS_SetEnvIfStatus       400     QS_Block
QS_SetEnvIfStatus       401     QS_Block
QS_SetEnvIfStatus       403     QS_Block
QS_SetEnvIfStatus       404     QS_Block
QS_SetEnvIfStatus       405     QS_Block
QS_SetEnvIfStatus       406     QS_Block
QS_SetEnvIfStatus       408     QS_Block
QS_SetEnvIfStatus       411     QS_Block
QS_SetEnvIfStatus       413     QS_Block
QS_SetEnvIfStatus       414     QS_Block
QS_SetEnvIfStatus       417     QS_Block
QS_SetEnvIfStatus       500     QS_Block
QS_SetEnvIfStatus       503     QS_Block
QS_SetEnvIfStatus       505     QS_Block
QS_SetEnvIfStatus       QS_SrvMinDataRate QS_Block
QS_SetEnvIfStatus       NullConnection  QS_Block
</IfModule>
#NoLoris END" >> $aproot/conf/includes/pre_main_global.conf
}
do_ipstack() {
echo "[+] Setting IP stacks..."
if [ ! -f /etc/sysctl.conf.noloris ];then cp -pv /etc/sysctl.conf /etc/sysctl.conf.noloris;fi
echo "
# Disables packet forwarding
net.ipv4.ip_forward = 0

# Disables IP source routing
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.eth0.accept_source_route = 0
net.ipv4.conf.eth1.accept_source_route = 0
net.ipv4.conf.default.accept_source_route = 0

# Enables source route verification and enable spoof protection
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1
net.ipv4.conf.eth0.rp_filter = 1
net.ipv4.conf.eth1.rp_filter = 1

# Disable ICMP Redirect Acceptance
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv4.conf.eth0.accept_redirects = 0
net.ipv4.conf.eth1.accept_redirects = 0

# Don't Log Spoofed Packets, Source Routed Packets, Redirect Packets
net.ipv4.conf.all.log_martians = 0

# Disables IP source routing
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.lo.accept_source_route = 0
net.ipv4.conf.eth0.accept_source_route = 0
net.ipv4.conf.default.accept_source_route = 0

# Disable ICMP Redirect Acceptance
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.lo.accept_redirects = 0
net.ipv4.conf.eth0.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0

# Disables the magic-sysrq key
kernel.sysrq = 0

# Decrease the time default value for tcp_fin_timeout connection
net.ipv4.tcp_fin_timeout = 15

# Decrease the time default value for tcp_keepalive_time connection
net.ipv4.tcp_keepalive_time = 300

# Turn on the tcp_window_scaling
net.ipv4.tcp_window_scaling = 1

# Turn on the tcp_sack
net.ipv4.tcp_sack = 1

# tcp_fack should be on because of sack
net.ipv4.tcp_fack = 1

# Turn on the tcp_timestamps
net.ipv4.tcp_timestamps = 1

# Enable TCP SYN Cookie Protection
net.ipv4.tcp_syncookies = 1

# Enable ignoring broadcasts request
net.ipv4.icmp_echo_ignore_broadcasts = 1


# Enable bad error message Protection
net.ipv4.icmp_ignore_bogus_error_responses = 1

# Make more local ports available
net.ipv4.ip_local_port_range = 1024 65000

# Increase maximum amount of memory allocated to shm
kernel.shmmax = 1073741824

# Improve file system performance
vm.bdflush = 100 1200 128 512 15 5000 500 1884 2

# This will increase the amount of memory available for socket input/output queues at the cost of more cpu usage
#net.ipv4.tcp_rmem = 4096 25165824 25165824
#net.core.rmem_max = 25165824
#net.core.rmem_default = 25165824
#net.ipv4.tcp_wmem = 4096 65536 25165824
#net.core.wmem_max = 25165824
#net.core.wmem_default = 65536
#net.core.optmem_max = 25165824

# Increase nr of semaphores
kernel.sem = 250 256000 32 1024
kernel.msgmni = 1024

# Increases performance, but can cause issues - beware.

net.core.netdev_max_backlog = 2500
#net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_tw_reuse = 1" >> /etc/sysctl.conf
sysctl -p >/dev/null 2>&1
sysctl -w net.ipv4.route.flush=1 >/dev/null 2>&1
}

compat_chk
grab_em
do_cfg
do_ipstack
sleep 5
screen -dmS noloris /bin/bash $pwd/$(basename $0) screenmon
for i in {1..10};do
echo "[!!] Rolling apache..."
killall -9 httpd php >/dev/null 2>&1
service httpd start
sleep 20
done
screen -S noloris -p 0 -X stuff $'\cC'
killall -9 httpd php >/dev/null 2>&1
echo "[!!] Flushing semaphores..."
ipcs -s | grep nobody | perl -e 'while (<STDIN>) { @a=split(/\s+/); print `ipcrm sem $a[1]`}' >/dev/null 2>&1
service httpd start
grep -oP '[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}' /root/ipban|sort|uniq -c|sort -rn
