Utilisation de la base de données des journaux Mikrotik pour supprimer la force brute

Bon après-midi

Dans une publication précédente , j'ai expliqué comment, facilement et naturellement, vous pouvez configurer la collecte de métadonnées de trafic réseau sur les routeurs Mikrotik dans une base de données.

Il est maintenant temps d'apprendre à notre serveur à faire une analyse élémentaire des données reçues et à renvoyer des commandes.

Objectif: Contrôle dynamique des règles de pare-feu Mikrotik pour supprimer les attaques réseau avec devinette de mot de passe.

Moyens: nouvelle distribution Linux avec rsyslogd v8, crond, SGBD mariadb et le routeur Mikrotik lui-mĂŞme.

Mécanique: à l' aide de la tâche assignée, une requête SQL est exécutée dans la base de données avec des données de trafic accumulées et mises à jour et renvoie une liste d'adresses IP sortantes, le script bash lancé par la couronne génère des commandes Mikrotik et, à l'aide d'une connexion ssh, reconstitue la liste d'adresses pour les règles de blocage existantes.

Il s'agira de protéger les ports TCP ouverts. Il peut s'agir de ports entrant dans Mikrotik et transmis au réseau local.

Pour commencer, nous indiquons oĂą il peut y avoir des faiblesses:

  • Protocoles de contrĂ´le de ssh, telnet, web, routeur winbox
  • Services de messagerie smtp, pop, imap
  • Tous les services Web fournis Ă  l'extĂ©rieur
  • Bureau Ă  distance MS RDP, VNC, etc.
  • Autre chose Ă  votre discrĂ©tion

Écriture d'une requête SQL pour rechercher la force brute

Notre organisation dispose de serveurs de terminaux ouverts sur l'extérieur via des ports non prioritaires.
Dans DNAT Mikrotik, j'ai activé l'enregistrement des règles nécessaires en ajoutant le préfixe RDP_DNAT. Par ce préfixe, nous rechercherons:

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) 

Cette demande indique l'adresse IP (d'où provient l'attaque), le port vers lequel la connexion est établie (le numéro de port est modifié) et le nombre de tentatives de connexion, avec un regroupement préliminaire par src et une sélection de lignes, avec un nombre de tentatives supérieur à 50 par le passé, à partir de l'heure actuelle, le jour.

Dans mon cas, ces adresses peuvent être interdites en toute sécurité, car le nombre de connexions avec de "bons" clients est moindre, pas plus de 5 à 10 par jour à partir d'une seule IP.

La demande fonctionne bien, rapidement, mais elle est un peu longue. Pour une utilisation ultérieure, je propose de faire une vue, qui copierait moins à l'avenir:

 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) 

VĂ©rifions le fonctionnement de la vue:

 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) 

Super.

Nous ajoutons l'utilisateur Mikrotik avec autorisation par clé dsa

Dans la console linux, nous générons la clé dsa, sous l'utilisateur pour le compte duquel la tâche planifiée sera lancée, j'ai fait depuis root:

 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. ... 

La phrase de passe n'est pas nécessaire. Nous copions la clé publique /root/.ssh/id_dsa.pub dans Mikrotik de toutes les manières possibles. Je l'ai sorti avec la commande cat, copié le texte de la fenêtre de mastic dans un fichier texte, l'ai enregistré et glissé dans la fenêtre des fichiers winbox.

Je ne sais pas pourquoi, mais au cours des opérations suivantes via l'interface Winbox, quelque chose s'est mal passé. Lors de la connexion depuis le serveur via ssh, Mikrotik m'a également demandé un mot de passe. Après avoir supprimé l'utilisateur créé et effectué toutes les opérations via la console, la connexion dsa a fonctionné. A fait approximativement comme décrit ici .

En général, j'ai reçu l'entrée de bienvenue sans mot de passe à l'aide de la clé dsa et j'ai exécuté la commande de vérification:

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

Bon.

Écrire un script bash

Le script n'était pas compliqué:

 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 

Afin de transférer toutes les commandes dans la même connexion ssh, j'avais besoin de décrire la fonction mikrotik_cmd_list (), dans laquelle une requête est d'abord effectuée avec la sauvegarde des adresses ip dans la variable brute_src_list, puis dans la boucle cette variable génère séquentiellement des commandes pour Mikrotik. Après avoir appelé la fonction, la sortie est acheminée via le canal vers ssh.

N'oubliez pas de fermer les droits d'accès au script à tout le monde sauf root et de rendre le fichier exécutable.
La commande que le script génère ajoutera l'adresse IP à rdp_banlist pendant 1 jour, après cette heure, elle sera supprimée de la liste elle-même. Si vous souhaitez le laisser indéfiniment, supprimez l'option de délai d'expiration.

Ajouter une règle au pare-feu

J'ai trouvé deux options pour utiliser la liste rdp_banlist:

Option 1: ajoutez la rdp_banlist avec un point d'exclamation aux règles NAT avec le préfixe RDP_DNAT.

 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 

Quelque chose comme ça. Autrement dit, nous dnat tout, sauf ce qui est dans rdp_banlist.

Dans cette option, il y a un plus et un moins.

Le plus est que les connexions s'arrêteront immédiatement.

L'inconvénient est que cette adresse IP n'entrera plus dans la base de données traflog et après un jour, lorsque le délai de stockage dans la liste noire est passé, il recommencera à chier.

Option deux: ajoutez le rdp_banlist avec un point d'exclamation à la règle de pare-feu de la chaîne directe, où nous autorisons le trafic à passer par TCP 3389, de la même manière que dans la première méthode.

 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 

Quelque chose comme ça. Nous autorisons tout sauf celui dans la liste d'interdiction.

Il y a aussi un plus et un moins.

De plus. Les journaux avec le préfixe RDP_DNAT continueront d'être diffusés dans la base de données traflog, par laquelle nous déterminons le signe de l'attaque. Par conséquent, lorsque le délai d'expiration d'un hôte spécifique qui poursuit ses tentatives de force brute expire, il sera à nouveau ajouté à la liste d'interdiction après le prochain lancement de tâche planifiée.

L'inconvénient est qu'il continue de chier dans la table DSTNAT, créant un nouvel enregistrement avec chaque connexion, bien que temporaire.

En général, la décision vous appartient, j'ai choisi les deux :) (en fait, seule la première fonctionne dans ce cas), car la seconde a été activée plus tôt et la mécanique y était différente, en fonction des entrées séquentielles dans les listes étape1, étape2, étape3, banlist ... eh bien, vous obtenez le point. Une astuce ancienne et peu fiable, elle peut facilement bannir les «bons» clients et en même temps ignorer les «mauvais» qui ont poliment calculé le timeout1.

Crontab de travaux planifiés

Reste à ajouter la tâche assignée à la crontab:

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

Un tel enregistrement exécutera le script toutes les heures en 12 minutes.

Je dois admettre que je viens de terminer le travail sur cette mécanique aujourd'hui et avec une forte probabilité, quelque chose pourrait mal tourner. Selon les circonstances, je compléterai et corrigerai les erreurs. Je veux boire pour dormir profondément pendant les vacances du Nouvel An, c'est pourquoi je suis pressé de terminer.
C'est probablement tout.

Merci à tous pour votre attention et bonne année!

Références:

Documentation mysql
Documentation du pare-feu Mikrotik
Merci Ă  Andrey Smirnov pour l' article sur la connexion dsa.

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


All Articles