iptables - Regeln nicht als root hinzufügen

3

Einer unserer Server wird täglich von einer großen Anzahl von Spam-Bots getroffen. Sie können zwar keinen Spam posten, versuchen aber trotzdem, den Server für echte Benutzer zu verlangsamen.

Um dem entgegenzuwirken, muss auf der Site ein PHP-Skript ausgeführt werden, das ihre IP-Adressen erkennt. Ich möchte jedoch, dass dieses Skript diese IP-Adressen automatisch zur Firewall hinzufügt (anstatt dass ich das manuell vornehmen muss). Laufen so etwas:

iptables -I INPUT -j DROP -s 123.123.123.123

Es sieht jedoch so aus iptables Befehle können nur als root ausgeführt werden. Irgendein Weg um dieses herum? Ich vermute, ich könnte die Befehle zu einer Datei hinzufügen lassen root Läuft über cron, möchte aber nicht wirklich zwischen dem PHP-Skript und dem Hinzufügen eines IP-Verbots warten.

Ross McLellan
quelle
1
Warum führen Sie das PHP-Skript nicht als root aus?
terdon
Das Skript wird am Ende des Ladens der Seite vom Webserver ausgeführt. Es macht verschiedene Logik, um herauszufinden, ob das Laden der Seite durch einen Spam-Bot erfolgte oder nicht.
Ross McLellan
1
Ein Suid-Root-Shell-Skript erstellen, das an iptables ruft? Stellen Sie sicher, dass Sie Ihre Eingaben desinfizieren sehr vorsichtig. So etwas wie s/[^0-9.:]// auf der IP-Adresse und nichts anderes als Eingabe akzeptieren. Ich würde es in einem solchen Szenario noch enger machen.
a CVn

Antworten:

2

Lassen Sie Ihr PHP-Skript die fehlerhaften IP-Adressen in eine Protokolldatei schreiben. Als nächstes installieren Fail2Ban und konfigurieren Sie es, um Ihre Protokolldatei zu lesen.

George P. Burdell
quelle
1
Vielen Dank. Ich gebe diese Methode erst einmal aus. Ich ziehe es vor, mich nicht auf Skripte von Drittanbietern zu verlassen, wenn ein einfaches benutzerdefiniertes Skript die Aufgabe erfüllt, aber fail2ban scheint eine Menge nützlicher Fähigkeiten zu besitzen, wie etwa das Unbanning nach einer bestimmten Zeit. War ein bisschen mühsam, sich einzurichten und scheint für einige Bits keine Dokumentation zu haben, scheint aber jetzt wie gewünscht zu laufen. Ich werde nur sehen, wie es beim nächsten Angriff klappt.
Ross McLellan
4

Der einfachste Weg wäre, wie Sie vorschlagen, dass das Skript die störenden IPs in eine Protokolldatei schreibt. Sie können dann ein anderes Skript (als root) in einer Schleife ausführen, die die Datei liest und die Datei sendet iptables Befehl. So etwas wie:

#!/bin/bash
while true
do
  while read IP
  do
      ## Check if this IP is already banned
      if ! iptables -L INPUT -v -n | grep $IP >/dev/null
      then
      ## If it is not banned, ban it
         iptables -I INPUT -j DROP -s $IP
      fi
  done < $1
  ## Sleeping to avoid spamming, if even a one second
  ## delay is too slow for you(!) adjust as needed.
  sleep 1
done

Sie können dieses Skript dann beim Start als root ausführen, entweder als Dienst oder indem Sie diese Crontab für root erstellen:

@reboot /path/to/banips.sh logfile.txt

Ich nehme an, die Verzögerung, um die Sie sich Sorgen machen, ist mindestens eine Minute. Da das Skript in einer Endlosschleife ausgeführt wird, müssen Sie es nicht jede Minute mit cron ausführen, und die Verzögerung liegt bei Ihnen. So wie es aussieht, liest das Skript jede Sekunde die Logdatei.

terdon
quelle
Es gibt bewährte Lösungen für das Problem, warum das Rad neu erfunden wird?
0xC0000022L
1
@ 0xC0000022L, weil in diesem Fall das Rad einfach zu erfinden ist, weil Softwareempfehlungen als Thema betrachtet werden und dies eine Lösung ist, für die keine Drittanbietersoftware erforderlich ist, und weil ich persönlich lieber kleine Skripte erledigen möchte, da ich ihr Verhalten perfekt steuern kann.
terdon
Ich habe sogar schon in meiner eigenen Antwort Ihr Skript erwähnt. Angenommen, Sie haben einen Punkt :)
0xC0000022L
Danke, @terdon, ich hatte nicht gemerkt, dass ein Cron-Job in einer while-Schleife so laufen könnte. Momentan versuche ich fail2ban, werde diese Methode aber wahrscheinlich auch einmal ausprobieren, auch wenn es nur um zu sehen, wie es funktioniert.
Ross McLellan
3

Als Alternative zu den vorhandenen Antworten und Hinzufügungen sshguard (nicht so bekannt wegen seines Umfangs, als der Name es vermuten lässt) zu dem erwähnten Fail2Ban, den ich Ihnen vorschlagen möchte sudo.

Die Datei /etc/sudoers kann so konfiguriert werden, dass genau kontrolliert wird, wer was von wem und von welcher Maschine ausführen kann. Daher können Sie einen kleinen Wrapper ähnlich wie in schreiben Terdon Antwort und dann chown root: es und stellen Sie sicher, dass seine Berechtigungen eng festgelegt sind. Werfen Sie es in einen Ordner wie /usr/sbin und erlaube es als ausgeführt zu werden root von welchem ​​Benutzerkonto aus Ihr PHP-Skript ausgeführt wird. Stellen Sie sicher, dass das Skript innerhalb der Chroot-Datei ausgeführt wird, wenn Ihr Skript im Kontext des Webservers ausgeführt wird und die Chroot-Funktion aktiviert ist. Denken Sie daran, dass dies verwendet werden könnte, um das chroot-Gefängnis zu gefährden, wenn Ihr Skript schlecht geschrieben ist. Eine Beispielzeile in /etc/sudoers könnte sein:

www-data   ALL= (root) NOPASSWD: /usr/sbin/yourscript.sh

die Benutzer erlaubt www-data zu rennen /usr/sbin/yourscript.sh wie root ohne ein Passwort auf allen Maschinen anzugeben ( sudoers kann eine zentrale für alle Maschinen in einem Netzwerk sein, deshalb ...).

sudo gilt als sicherer als die Einstellung suid etwas in Ihrem Skript, aber ich nehme an, dass es gute Gründe gibt, diese Alternative zu verwenden, z. wenn nein sudo ist verfügbar.

Sie können auch auschecken diese Antwort Ich gab auf der Schwester-SE-Website askubuntu.com auf.

0xC0000022L
quelle
Vielen Dank. Ich war etwas ungern darauf, meinen Webserverbenutzer alle iptables-Befehle ausführen zu lassen. Ich wusste, Sudoers konnte die Befehle einschränken, die Sie ausführen können, aber ich wusste nicht, dass ich es auf eine bestimmte .sh-Datei beschränken könnte (eine, die die spezifische ausführt.) iptables-Befehl).
Ross McLellan
0

Eine sehr einfache Methode ...

Ich habe ein PHP-Skript geschrieben, das die unerwünschte IP-Adresse in jeder Textzeile in eine Textdatei schreibt (wo immer nötig)

$banlist = file_get_contents( '/var/www/banlist.txt' );
$remoteip = $_SERVER['REMOTE_ADDR'];
if( strpos( $banlist, $remoteip ) === false ){
    file_put_contents( '/var/www/banlist.txt', $remoteip."\n", FILE_APPEND );
}

Dann habe ich eine eigene iptables-Kette erstellt und es genannt Banliste "(nenne es was du willst) mit dem Befehl ...

sudo iptables --new-chain banlist

Auch die Installation von iptables-persistent mit ...

sudo apt-get install iptables-persistent

Zuletzt mit dem Befehl ...

sudo crontab -e

Ich habe diese Zeile wie folgt zum Root Cronjob hinzugefügt, um alle 5 Minuten zu laufen (ändern Sie Ihre Zeit), um jede IP zu lesen, sie der iptable-Kette hinzuzufügen, die ich mit einem DROP-Ziel erstellt habe, und dann die Textdatei zu löschen ...

*/5 * * * * while read in; do sudo iptables -A banlist -s "$in" -j DROP; done < /var/www/banlist.txt && > /var/www/banlist.txt

Ich habe diese Zeile auch hinzugefügt, um sicherzustellen, dass die Regeln alle 5 Minuten gespeichert werden ...

*/5 * * * * iptables-save > /etc/iptables/rules.v4 && ip6tables-save > /etc/iptables/rules.v6

Das ist es! Süß und einfach, testen Sie es, indem Sie der Textdatei eine zufällige IP-Adresse (oder jede IP-Adresse in einer neuen Zeile) hinzufügen und darauf warten, dass Ihr Cronjob in dem von Ihnen gewählten Intervall ausgeführt wird ... Achten Sie darauf, sich nicht selbst zu verbieten, indem Sie das PHP-Skript von Ihrem eigenen Netzwerk aus testen.

Hinweis: Um alle IP-Adressen in der iptables-Kette zu löschen, können Sie " sudo iptables -F banlist "

JxAxMxIxN
quelle