
Ich verwende Linux Debian Bookworm.
Problem
Ich möchte alle eingehenden Verbindungen zu meinem Server aus bestimmten Ländern blockieren.
Bearbeiten
Wie jemand in den Kommentaren anmerkte, sollte ich das eigentlich nicht mit iptables machen, da das meinen Server zum Stillstand bringt, sobald die Liste der blockierten IP-Adressen eine unüberschaubare Größe erreicht (etwa Tausende von IP-Adressen). Stattdessen sollte ich ipset
(zum Blockieren ganzer Bereiche) verwenden. Das Problem dabei ist, dass es von Listen abhängt, die ich regelmäßig herunterladen muss. Ich möchte etwas, das ich (vorzugsweise) einmal einstelle.
Wie kann ich Verbindungen aus bestimmten Ländern stoppen?Der Datenverkehr (und manchmal auch Brute-Force-Angriffe) aus China und Russland gerät außer Kontrolle. Sie bringen meinen Server regelmäßig in die Knie. Sie halten sich nicht an die robots.txt-Datei und crawlen die Site sehr aggressiv (mit Hunderten, manchmal Tausenden von Verbindungen gleichzeitig). Das muss ich wirklich stoppen. Ich schätze, dass weit über 90 % des gesamten Datenverkehrs, den mein Server verarbeitet, bösartig/fehlerhaft ist.
Bearbeiten 2
Ich habe einige Online-Tutorials gefunden (wie dieser) wie das geht, aber diese Tutorials scheinen ziemlich alt zu sein. Außerdem müssen einige Module heruntergeladen und kompiliert/installiert werden. Ich befürchte, dass dies in Zukunft nicht mehr funktionieren könnte (beim Aktualisieren/Upgraden anderer Pakete oder sogar der Distribution) oder in Zukunft ein Sicherheitsrisiko darstellen könnte. Ich halte meinen Server auf dem neuesten Stand (indem ich regelmäßig apt-get update / apt-get upgrade / apt-get dist-upgrade ausführe).
originale Nachricht
Ich habe online ein Skript gefunden, das (kurz gesagt) jede Sekunde eine Liste der IP-Adressen der hergestellten Verbindungen abruft und dann Geoiplookup verwendet, um das Land der IP-Adresse zu ermitteln. Wenn das Land auf der Liste der Länder steht, die Sie blockieren möchten, fügt es die IP-Adresse mithilfe von iptables zu Ihrem Firewall-Filter hinzu. Ich habe ein paar kleine Änderungen am Skript vorgenommen (um es lesbarer zu machen und weil ich kein Interesse daran hatte, dass mir dieses Skript jedes Mal eine E-Mail schickt, wenn es eine IP-Adresse blockiert). Dieses Skript wird dann jede Minute über crontab ausgeführt:
#!/bin/bash
# Script found on lautenbacher.io"
end=$((SECONDS+55))
while [ $SECONDS -lt $end ]; do
echo $SECONDS
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 > "0" ]]; then
bGF1dGVuYmFjaGVyLmlv=$(geoiplookup $d | awk -v ip="$d" '{FS=" "} {if($4 == "RU," || $4 == "CN," || $4 == "BLR,") {print 1}}')
if [[ $bGF1dGVuYmFjaGVyLmlv = "1" ]]; then
echo "running geolookup"
echo checking ip $d
geoiplookup $d
isCloudflare=0
# The original script made an exception for CLOUDFLARE. I don't want that exception
# bGF1dGVuYmFjaGVyLmlX=$(whois $d)
# if [[ "$bGF1dGVuYmFjaGVyLmlX" == *"CLOUDFLARE "* ]]; then
# isCloudflare=1
# echo Cloudflare detected
# fi
if [[ "$isCloudflare" != 1 ]]; then
echo try to add ip $d to blocklist
sudo iptables -I INPUT -s $d -j DROP
### I would like to sever the connection here ###
fi
fi
fi
done < testcc.txt
sleep 1
:
done
Übrigens habe ich keine Ahnung, warum der Autor des Skripts so seltsame Variablennamen verwendet („bGF1dGVuYmFjaGVyLmlv“).
Wie auch immer, das Problem ist, dass, wenn es eine Verbindung mit einer IP-Adresse aus einem verbotenen Land findet, es läuft
sudo iptables -I INPUT -s $d -j DROP
auf der IP-Adresse. Das ist alles in Ordnung, aber die meisten dieser Verbindungen sind einigermaßen persistent, d. h. eine Sekunde später wird dieselbe IP-Adresse gefunden und erneut mithilfe von iptables hinzugefügt. Ich bin nicht sicher, was passiert (erstellt es doppelte Regeln?), aber ich möchte die Verbindung sofort trennen, nachdem die IP-Adresse mit iptables hinzugefügt wurde.
Also kurz gesagt: Wie kann ich eine(n) Verbindung(en) mit einer IP-Adresse beenden?
Antwort1
Seit einigen Jahren verfügt der Linux-Kernel über eine API, mit der bestehende IP-Sockets unabhängig von ihrem Status zwangsweise beendet werden können. Dies kann mit demss
Befehl und seine Filtersyntax:
-K
,--kill
Versucht, Sockets zwangsweise zu schließen. Diese Option zeigt erfolgreich geschlossene Sockets an und überspringt stillschweigend Sockets, deren Schließen der Kernel nicht unterstützt. Unterstützt werden nur IPv4- und IPv6-Sockets.
Sie können ersetzen:
### I would like to sever the connection here ###
mit:
ss --kill -n dst = "$d"
DerFilter( dst = ...
) ist erforderlich, da der Befehl jeden Socket beendet, der angezeigt wird. Ohne Filter wäre das mehr als verlangt. Der lokale Prozess könnte einen ansonsten seltenen Fehler auf seinem Socket erhalten, wie z . B. ECONNABORTED
. Der Remote-Knoten wird wahrscheinlich mit einem TCP RST benachrichtigt, sofern nicht (vorübergehend) eine OUTPUT-Regel hinzugefügt wird, um dies zu verhindern.
Siehe auch diese Frage und Antwort (wo ich eine Antwort gegeben habe):Beenden Sie ALLE TCP-Verbindungen (HERGESTELLT, VERWANDTE) in Ubuntu, wo OP versucht, vor Angriffen mit einem zu schützenipset(und hat auch Probleme mit veralteten Verbindungen und Stateful Firewalling).