Verwenden der Mikrotik-Protokolldatenbank zur Unterdrückung von Brute Force

Guten Tag.

In einer früheren Veröffentlichung habe ich darüber gesprochen, wie Sie auf einfache und natürliche Weise die Erfassung von Netzwerkverkehrsmetadaten auf Mikrotik-Routern in einer Datenbank konfigurieren können.

Jetzt ist es an der Zeit, unserem Server beizubringen, eine elementare Analyse der empfangenen Daten durchzuführen und Befehle zurückzusenden.

Zweck: Dynamische Steuerung der Mikrotik-Firewall-Regeln zur Unterdrückung von Netzwerkangriffen durch Erraten von Kennwörtern.

Mittel: Neue Linux-Distribution mit rsyslogd v8, crond, mariadb DBMS und dem Mikrotik-Router selbst.

Mechanik: Unter Verwendung der zugewiesenen Aufgabe wird eine SQL-Abfrage in der Datenbank mit den gesammelten und aufgefüllten Verkehrsdaten ausgeführt und gibt eine Liste der ausgehenden IP-Adressen zurück. Das von der Krone gestartete Bash-Skript generiert Mikrotik-Befehle und füllt mithilfe einer SSH-Verbindung die Adressliste für vorhandene Blockierungsregeln auf.

Es geht darum, offene TCP-Ports zu schützen. Dies können Ports sein, die in Mikrotik eintreten und an das lokale Netzwerk weitergeleitet werden.

Zunächst geben wir an, wo es Schwächen geben kann:

  • Steuerprotokolle von SSH-, Telnet-, Web- und Winbox-Routern
  • Mail-Dienste SMTP, Pop, IMAP
  • Alle außerhalb bereitgestellten Webdienste
  • Remotedesktop MS RDP, VNC usw.
  • Alles andere nach Ihrem Ermessen

Schreiben einer SQL-Abfrage zur Suche nach Brute Force

Unsere Organisation verfügt über Terminalserver, die über nicht priorisierte Ports nach außen geöffnet sind.
In DNAT Mikrotik habe ich die Protokollierung der erforderlichen Regeln durch Hinzufügen des Präfixes RDP_DNAT aktiviert. Nach diesem Präfix suchen wir:

MariaDB [traflog]> select src,dport,count(dport) as ' ' from traffic where datetime>now() - interval 1 day and logpref='RDP_DNAT' group by src having count(dport)>50; +-----------------+-------+---------------------------------------+ | src | dport |   | +-----------------+-------+---------------------------------------+ | 185.156.177.58 | 12345 | 118 | | 185.156.177.59 | 12345 | 267 | | 193.238.46.12 | 12345 | 318 | | 193.238.46.13 | 12345 | 319 | | 193.238.46.99 | 12345 | 342 | | 194.113.106.150 | 12345 | 67 | | 194.113.106.152 | 12345 | 167 | | 194.113.106.153 | 12345 | 190 | | 194.113.106.154 | 12345 | 192 | | 194.113.106.155 | 12345 | 190 | | 194.113.106.156 | 12345 | 216 | | 194.113.106.158 | 12345 | 124 | +-----------------+-------+---------------------------------------+ 12 rows in set (0.06 sec) 

Diese Anforderung zeigt die IP-Adresse (von der der Angriff ausgeht), den Port, zu dem die Verbindung hergestellt wird (die Portnummer wird geändert) und die Anzahl der Verbindungsversuche mit vorläufiger Gruppierung nach src und Auswahl von Leitungen, wobei die Anzahl der Versuche in der Vergangenheit ab dem aktuellen Zeitpunkt am Tag mehr als 50 beträgt.

In meinem Fall können diese Adressen sicher gesperrt werden, da die Anzahl der Verbindungen mit "guten" Clients geringer ist, nicht mehr als 5-10 pro Tag von einer IP.

Die Anfrage funktioniert gut, schnell, ist aber etwas lang. Zur weiteren Verwendung schlage ich vor, eine Ansicht zu machen, die in Zukunft weniger kopieren würde:

 MariaDB [traflog]> create or replace view rdp_brute_day as select src, dport, count(dport) from traffic where datetime>now() - interval 1 day and logpref='RDP_DNAT' group by src having count(dport)>50; Query OK, 0 rows affected (0.23 sec) 

Lassen Sie uns überprüfen, wie die Ansicht funktioniert:

 MariaDB [traflog]> select src,count(dport) from rdp_brute_day; +----------------+--------------+ | src | count(dport) | +----------------+--------------+ | 185.156.177.58 | 11 | +----------------+--------------+ 1 row in set (0.09 sec) 

Großartig.

Wir fügen den Benutzer Mikrotik mit Autorisierung per dsa key hinzu

In der Linux-Konsole generieren wir den dsa-Schlüssel, unter dessen Benutzer die geplante Aufgabe gestartet wird, die ich aus root erstellt habe:

 root@monix:~# ssh-keygen -t dsa Generating public/private dsa key pair. Enter file in which to save the key (/root/.ssh/id_dsa): Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in /root/.ssh/id_dsa. Your public key has been saved in /root/.ssh/id_dsa.pub. ... 

Eine Passphrase ist nicht erforderlich. Wir kopieren den öffentlichen Schlüssel /root/.ssh/id_dsa.pub auf jede mögliche Weise nach Mikrotik. Ich brachte es mit dem Befehl cat heraus, kopierte den Text aus dem Kittfenster in eine Textdatei, speicherte ihn und zog ihn in das Fenster mit den Winbox-Dateien.

Ich weiß nicht warum, aber während der folgenden Vorgänge über die Winbox-Oberfläche ist ein Fehler aufgetreten. Bei der Verbindung vom Server über ssh hat Mikrotik auch ein Passwort von mir angefordert. Nachdem ich den erstellten Benutzer gelöscht und alle Vorgänge über die Konsole ausgeführt hatte, funktionierte die dsa-Verbindung. Hat ungefähr wie hier beschrieben.

Im Allgemeinen erhielt ich den Begrüßungseintrag ohne Kennwort mit dem dsa-Schlüssel und führte den Überprüfungsbefehl aus:

 root@monix:/# ssh rsyslogger@192.168.0.230 /system resource print uptime: 2w1d5h22m43s version: 6.43.2 (stable) ... 

Gut.

Ein Bash-Skript schreiben

Das Skript war nicht kompliziert:

 mikrotik_cmd_list(){ brute_src_list=$(mysql --skip-column-names traflog -e 'select src from rdp_brute_day') for src in $brute_src_list do echo "ip firewall address-list add address=$src list=rdp_banlist timeout=1d" done } mikrotik_cmd_list | ssh -T rsyslogger@192.168.0.230 

Um alle Befehle innerhalb derselben ssh-Verbindung zu übertragen, musste ich die Funktion mikrotik_cmd_list () beschreiben, bei der zuerst eine Anforderung mit dem Speichern von IP-Adressen in der Variablen brute_src_list ausgeführt wird. Anschließend generiert diese Variable in der Schleife nacheinander Befehle für Mikrotik. Nach dem Aufruf der Funktion wird die Ausgabe über die Pipe an ssh weitergeleitet.

Vergessen Sie nicht, die Skriptzugriffsrechte für alle außer root zu schließen und die Datei ausführbar zu machen.
Der vom Skript generierte Befehl fügt die IP-Adresse 1 Tag lang zu rdp_banlist hinzu. Nach dieser Zeit wird sie aus der Liste selbst entfernt. Wenn Sie es für immer verlassen möchten, entfernen Sie die Timeout-Option.

Fügen Sie der Firewall eine Regel hinzu

Ich habe mir zwei Optionen für die Verwendung der rdp_banlist ausgedacht:

Option eins: Fügen Sie die rdp_banlist mit einem Ausrufezeichen zu den NAT-Regeln mit dem Präfix RDP_DNAT hinzu.

 add action=dst-nat chain=dstnat comment="..." dst-address=1.2.3.4 dst-port=12345 log=yes log-prefix=RDP_DNAT protocol=tcp src-address-list=\ !rdp_banlist to-addresses=192.168.200.181 to-ports=3389 

Ungefähr so. Das heißt, wir dnat alles, außer was in rdp_banlist ist.

Bei dieser Option gibt es ein Plus und ein Minus.

Das Plus ist, dass die Verbindungen sofort beendet werden.

Der Nachteil ist, dass diese IP nicht mehr in die Traflog-Datenbank gelangt und nach einem Tag, wenn das Speicherzeitlimit in der Blacklist abgelaufen ist, wieder zu scheißen beginnt.

Option 2: Fügen Sie die rdp_banlist mit einem Ausrufezeichen zur Firewall-Regel der Weiterleitungskette hinzu, in der der Datenverkehr ähnlich wie bei der ersten Methode über TCP 3389 geleitet wird.

 add action=accept chain=forward comment="..." dst-port=3389 log=yes log-prefix=ACCEPT_RDP protocol=tcp src-address-list=\ !rdp_banlist to-ports=3389 

Ungefähr so. Wir erlauben alles außer dem in der Banlist.

Es gibt auch ein Plus und ein Minus.

Plus. Protokolle mit dem Präfix RDP_DNAT werden weiterhin in der Traflog-Datenbank gestreamt, anhand derer wir das Anzeichen eines Angriffs bestimmen. Wenn das Sperrzeitlimit für einen bestimmten Host, der Brute-Force-Versuche fortsetzt, abläuft, wird es nach dem nächsten geplanten Taskstart erneut zur Sperrliste hinzugefügt.

Der Nachteil ist, dass es weiterhin in der DSTNAT-Tabelle Mist macht und mit jeder Verbindung einen neuen Datensatz erstellt, wenn auch einen temporären.

Im Allgemeinen liegt die Entscheidung bei Ihnen, ich habe beide gewählt :) (tatsächlich funktioniert in diesem Fall nur die erste), da die zweite früher eingeschaltet wurde und die Mechanik dort unterschiedlich war, basierend auf sequentiellen Einträgen in den Listen Stage1, Stage2, Stage3, Banlist ... nun, Sie verstehen. Ein alter und nicht sehr zuverlässiger Trick, der leicht "gute" Kunden verbieten und gleichzeitig die "schlechten" Kunden überspringen kann, die die Timeout-Phase höflich berechnet haben1.

Geplante Job-Crontab

Die zugewiesene Aufgabe muss noch der Crontab hinzugefügt werden:

 root@monix:/root# echo '12 * * * * root /usr/share/traflog/scripts/rdp_brute.sh >/dev/null 2>&1' >> /etc/crontab 

Ein solcher Datensatz führt das Skript jede Stunde in 12 Minuten aus.

Ich muss zugeben, ich habe gerade die Arbeit an dieser Mechanik beendet und mit hoher Wahrscheinlichkeit könnte etwas schief gehen. Je nach den Umständen werde ich Fehler ergänzen und korrigieren. Ich möchte trinken, um in den Neujahrsferien tief und fest zu schlafen, deshalb habe ich es eilig, fertig zu werden.
Das ist wahrscheinlich alles.

Vielen Dank für Ihre Aufmerksamkeit und ein gutes neues Jahr!

Referenzliste:

MySQL-Dokumentation
Dokumentation zur Mikrotik-Firewall
Vielen Dank an Andrey Smirnov für den Artikel über dsa connection.

Source: https://habr.com/ru/post/de434736/


All Articles