Firewallscript: Automatische Erkennung und Blockierung von Flooding-Angriffen und Portscans auf (Web)servern

Firewallscript: Automatische Erkennung und Blockierung von Flooding-Angriffen und Portscans auf (Web)servern

Dieser Artikel ist eine Fortsetzung zu meinem vorherigen Artikel der sich ebenfalls mit Angriffen auf Webserver auseinandergesetzt hat. Der nachfolgende Artikel zeigt auf wie ein Angriff erkannt und blockiert werden kann – und das vollständig ohne kostenpflichtige Tools.

Das Script schützt nicht nur gegen Flooding-Angriffe sondern aufgrund seiner Funktionsweise auch gegen größere Portscans.

Um unsere wichtigen und echten Besucher allerdings nicht zu behindern, führen wir zusätzlich eine Prüfung durch aus welchem Land unsere Besucher tatsächlich kommen.

Demgemäß werden z. B. Angriffe aus Deutschland in den Standardeinstellungen absichtlich nicht blockiert (siehe weiter unten). Im Gegensatz hierzu werden Nutzer aus verdächtigeren Staaten wie z. B. Russland schneller blockiert als Nutzer anderer Staaten.

Schnellstart – Fertiges Firewallscript von lautenbacher.io

Das ist Euch alles zu kompliziert? Ihr könnt das Firewall-Script samt Cronjob auch mit diesem Script installieren oder mich über mein Kontaktformular zu günstigen Stundensätzen buchen.

Das Script zum Installieren importiert zusätzlich eine CIDR Blockliste und aktualisiert diese täglich (Cronjob). Das Firewallscript selbst wird minütlich als Cronjob ausgeführt.

Im Installationsprozess werdet Ihr nach Eurer E-Mail-Adresse gefragt. Die E-Mail-Adresse wird im Script verwendet um Euch automatisch eine Benachrichtigung zu einem Vorfall zu senden (sofern Euer Server zum versenden von E-Mail richtig konfiguriert ist).

Die Logdatei wird per Cronjob am Anfang vom Monat gelöscht.

Ich übernehme selbstverständlich keine Garantie oder Haftung für das nachfolgende Script. Bitte prüft die Dateien vor jedem Download selbst und testet die funktionsweise auf einer Testmaschine bzw. in einer Testumgebung.

Das Script funktioniert neben Debian natürlich auch auf dem Raspberry Pi und neben der Plesk Firewall.

Bei Fehlern oder Problemen könnt Ihr gerne einen Kommentar hinterlassen.

apt-get update && apt-get install -y wget && wget -O /root/install.sh https://www.lautenbacher.io/firewallscript/install.sh && chmod 777 /root/install.sh && /root/install.sh

Tutorial

Es werden die Pakete iptables, netstat und geoip-bin zwingend vorausgesetzt, diese werden installiert mit

apt-get update
apt-get install -y sudo
apt-get install -y geoip-bin
apt-get install -y iptables
apt-get install -y whois
apt-get install -y iptables-persistent
apt-get install -y net-tools #insbesondere auf Raspbian nicht installiert

Unser Testscript test.sh legen wir wie gewohnt per

touch /root/test.sh
touch /root/test.log
touch /root/test.txt
chmod 777 /root/test.log
chmod 777 /root/test.txt
chmod 777 /root/test.sh
nano /root/test.sh

an. Das Skript prüft hier hauptsächlich anhand der Ausgabe von netstat die Anzahl der etablierten Verbindungen pro IP-Adresse:

Das Shellskript hat den nachfolgenden Inhalt:

#!/bin/bash
echo Shellscript powered by lautenbacher.io
echo Block more than 200 Connections
netstat -ant | egrep '(:80|:443) .*:.*ESTABLISHED' | awk '{print $5}' | cut -d: -f1 | sort | uniq -c > test.txt
sed 's/^[ \t]*//' -i test.txt
sed '/^$/d' -i test.txt
while read a b; do
    if [[ $a > "200" ]]; then

bGF1dGVuYmFjaGVyLmlv=$(geoiplookup $b | awk -v ip="$b" '{FS=" "} {if($4 != "AT," && $4 != "US," && $4 != "DE,") {print "1";}}')

if [[ $bGF1dGVuYmFjaGVyLmlv = "1" ]]; then
echo checking ip $b
geoiplookup $b
echo add ip $b to iptables blocklist
sudo iptables -I INPUT -s $b -j DROP
#mail -s 'Alert Message regarding '$b [email protected] <<< $b' exceeded the connection limit of 200'
fi

  fi
done < test.txt

In diesem Beispiel werden alle IPs mit mehr als 200 Verbindungen, welche nicht aus Deutschland, Österreich oder den Vereinigten Staaten sind automatisch blockiert.

Natürlich lässt sich das auch umdrehen und wir können ein zusätzliches Script erstellen, welches alle Verbindungen aus Russland, Indien und China automatisch blockiert sobald mehr als 10 Verbindungen gleichzeitig bestehen.

Die beiden Skripte lassen sich natürlich auch kombinieren!

#!/bin/bash
echo "Shellscript powered by lautenbacher.io"
#bad countries RU CN IND IDN HKG TH VN UKR BLR VEN - limit 20
netstat -ant | egrep ':.*ESTABLISHED' | awk '{print $5}' | cut -d: -f1 | sort | uniq -c > testcc.txt
sed 's/^[ \t]*//' -i testcc.txt
sed '/^$/d' -i testcc.txt
while read c d; do
    if [[ $c > "20" ]]; then

bGF1dGVuYmFjaGVyLmlv=$(geoiplookup $d | awk -v ip="$d" '{FS=" "} {if($4 == "RU," || $4 == "CN," || $4 == "IND," || $4 == "IDN," || $4 == "HKG," || $4 == "TH," || $4 == "VN," || $4 == "UKR," || $4 == "BLR," || $4 == "VEN,") {print 1}}')

 if [[ $bGF1dGVuYmFjaGVyLmlv = "1" ]]; then
echo "running part 4"
bGF1dGVuYmFjaGVyLmlX=$(whois $d)
echo checking ip $d
geoiplookup $d

echo try to add ip $d to blocklist


whoisvar=0
if [[ "$bGF1dGVuYmFjaGVyLmlX" == *"CLOUDFLARE"* ]]; then
whoisvar=1
echo Cloudflare detected
fi

if [[ "$whoisvar" != 1 ]]; then
sudo iptables -I INPUT -s $d -j DROP
whois=$(whois $d)
hostvar=$(hostname)
mail -s 'Warning Message regarding '$d [email protected] <<< $d' bad country host exceeded the connection limit of 20'$whois
echo blocking $d
fi

 fi

   fi
done < testcc.txt

Mit unseren beiden Shellskripten haben wir unsere Firewall bereits intelligent automatisiert. Es fehlt natürlich noch an der regelmäßigen Ausführung. Hierzu legen wir am einfachsten einen Cronjob mit

crontab -e

an und erweitern die Datei beispielhaft um folgenden Inhalt:

*/1 * * * * /root/test.sh >> /root/test.log 2>&1

In diesem Beispiel wird das Skript innerhalb der Datei test.sh jede Minute ausgeführt. Demnach prüft unser Script ab jetzt jede Minute die Verbindungen auf Auffälligkeiten und blockiert diese.

Als Alternative zum sofortigen blockieren könntet Ihr Euch Angreifer IPs auch einfach per E-Mail senden lassen:

mail -s 'Warning Message regarding '$b [email protected] <<< $b' exceeded the connection limit of 100'

Das ist insbesondere eine gute Idee um die Einstellungen zu testen ohne die IP sofort zu blockieren.

Finale Version – Teil 1: Connection-Flooding Erkennung mit Analyse per Countrycode und whois-Daten

Anbei noch eine umfangreichere kombinierte Version des Scripts, welches auch versucht Cloudflare auszuschließen, jedoch benötigt die whois Abfrage das whois Paket

apt-get install whois

und einiges an Zeit bei der Abfrage. Selbstverständlich können auch andere Netze anhand der whoisdaten von Sperren ausgeschlossen werden.

#!/bin/bash
#powered by lautenbacher.io
#all hosts except DE AT CH US IE CA UK FR ES - limit 75
roundvar1=$(date +"%s")
datevar=$(date)
echo $datevar
echo starting round $roundvar1
echo "running part 1"
netstat -ant | egrep '(:80|:443) .*:.*ESTABLISHED' | awk '{print $5}' | cut -d: -f1 | sort | uniq -c > test.txt
sed 's/^[ \t]*//' -i test.txt
sed '/^$/d' -i test.txt
while read a b; do
    if [[ $a > "75" ]]; then

bGF1dGVuYmFjaGVyLmlvA=$(geoiplookup $b | awk -v ip="$b" '{FS=" "} {if($4 != "AT," && $4 != "US," && $4 != "DE," && $4 != "CH," && $4 != "IE," && $4 != "CA," && $4 != "UK," && $4 != "FR," && $4 != "ES,") {print "1";}}')
bGF1dGVuYmFjaGVyLmlvc=$(geoiplookup $b)
if [[ $bGF1dGVuYmFjaGVyLmlvA = "1" ]]; then
echo "running part 2"
echo checking ip $b
geoiplookup $b
echo try to add ip $b to blocklist

whois=$(whois $b)
whoisvar=0
#echo whoisvar 0
if [[ "$whois" == *"CLOUDFLARE"* ]]; then
whoisvar=1
echo Cloudflare detected
fi

if [[ "$whoisvar" != 1 ]]; then
hostvar=$(hostname)
mail -s 'Warning Message regarding '$b [email protected] <<< $b' exceeded the connection limit of 75'$whois
sudo iptables -I INPUT -s $b -j DROP
echo blocking $b
echo $b/32 >> /root/blockedcidr.txt
fi


fi

  fi
done < test.txt



echo "running part 3"
#bad countries RU CN IND IDN HKG TH VN UKR BLR VEN - limit 30
netstat -ant | egrep ':.*ESTABLISHED' | awk '{print $5}' | cut -d: -f1 | sort | uniq -c > testcc.txt
sed 's/^[ \t]*//' -i testcc.txt
sed '/^$/d' -i testcc.txt
while read c d; do
    if [[ $c > "30" ]]; then

bGF1dGVuYmFjaGVyLmlv=$(geoiplookup $d | awk -v ip="$d" '{FS=" "} {if($4 == "RU," || $4 == "CN," || $4 == "IND," || $4 == "IDN," || $4 == "HKG," || $4 == "TH," || $4 == "VN," || $4 == "UKR," || $4 == "BLR," || $4 == "VEN,") {print 1}}')

 if [[ $bGF1dGVuYmFjaGVyLmlv = "1" ]]; then
echo "running part 4"
bGF1dGVuYmFjaGVyLmlX=$(whois $d)
echo checking ip $d
geoiplookup $d

echo try to add ip $d to blocklist


whoisvar=0
if [[ "$bGF1dGVuYmFjaGVyLmlX" == *"CLOUDFLARE"* ]]; then
whoisvar=1
echo Cloudflare detected
fi

if [[ "$whoisvar" != 1 ]]; then

whois=$(whois $d)
hostvar=$(hostname)
mail -s 'Warning Message regarding '$d [email protected] <<< $d' bad country host exceeded the connection limit of 30'$whois
echo blocking $d
sudo iptables -I INPUT -s $d -j DROP
echo $d/32 >> /root/blockedcidr.txt
fi

 fi

   fi
done < testcc.txt

echo finishing $roundvar1

Zur Übersichtlichkeit schreiben wir noch nach jeder Ausführung das aktuelle Datum mit Uhrzeit und die aktiven iptables Regeln in die Logdatei bzw. geben diese aus mit:

rulevar=$(sudo iptables -n --list --line-numbers | sed '/^num\|^$\|^Chain/d' | wc -l)
echo There are $rulevar rules active

Ihr benötigt Hilfe bei Eurem Server? Schreibt mir einfach über mein Kontaktformular.

Finale Version – Teil 2: Import einer CIDR-Blockliste von lautenbacher.io

Hier empfiehlt es sich nicht jede Minute ein Update durchzuführen, sondern nur jeden Tag! Das Script prüft zusätzlich ob bereits eine andere Regel zum CIDR-Block existiert und fügt die Regel nur hinzu wenn keine andere Regel existiert.

0 0 * * * /root/block.sh >> /root/block.log 2>&1

Der Code des Scripts unter /root/block.sh lautet:

#!/bin/bash
wgetb=$(wget -O /root/cidr.txt https://www.lautenbacher.io/firewallscript/cidr.txt)
whois 1.1.1.1
while read a; do

checkvar=$(sudo iptables -S | grep -- $a)
blockit=0
if [[ "$checkvar" == *$a* ]]; then
blockit=1
echo skipping existing rule
fi


if [[ "$blockit" != 1 ]]; then

sudo iptables -I INPUT -s $a -j DROP ;
echo adding rule $a
fi

done < cidr.txt

while read a; do

In der Vergangenheit geblockte IPs landen automatisch in der Datei „/root/blockedcidr.txt“, solltet Ihr diese also automatisch blockieren wollen (z. B. nach einem Neustart) so könntet Ihr die „block.sh“ entsprechend erweitern.

while read b; do

checkvar=$(sudo iptables -S | grep -- $b)
blockit=0
if [[ "$checkvar" == *$b* ]]; then
blockit=1
echo skipping existing rule
fi


if [[ "$blockit" != 1 ]]; then

iptables -I INPUT -s $b -j DROP ;
echo adding rule $b
fi

done < blockedcidr.txt

Anhang – SSH und Telnet Verbindungen in ein CIDR Log schreiben

netstat -ant | egrep '(:22|:23) .*:.*ESTABLISHED' | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sed 's/^[ \t]*//' | sed '/^$/d' | while read a b; do echo $b/32 >> /root/ssh.txt; done;

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.