Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/python3
- import argparse
- import json
- import time
- import subprocess
- import schedule
- import ipaddress
- # Paramètres modifiables par l'utilisateur
- parser = argparse.ArgumentParser()
- parser.add_argument("-f", "--file", help="Chemin d'accès au fichier de log", required=False, default="/srv/adguardhome/workdir/data/querylog.json")
- parser.add_argument("-t", "--type", help="Type de requête à identifier (TXT, A, ALL)", default="TXT")
- parser.add_argument("-s", "--seuil", help="Seuil du nombre de requêtes", type=int, default=4)
- parser.add_argument("-d", "--duree", help="Durée que le nombre de requêtes ne doit pas dépasser en secondes", type=int, default=10)
- parser.add_argument("-b", "--ban", help="Durée du ban en minutes", type=int, default=10)
- parser.add_argument("-n", "--nettoyage", help="Temps avant de nettoyer le dictionnaire en secondes", type=int, default=60)
- args = parser.parse_args()
- # Supprime la table nftables block_subnet si elle existe déjà
- subprocess.run(["nft", "delete", "table", "inet", "block_subnet"], stderr=subprocess.DEVNULL)
- # Création de la table nftables block_subnet
- subprocess.run(["nft", "add", "table", "inet", "block_subnet"])
- # Ajout de la chaîne d'entrée block_subnet
- subprocess.run(["nft", "add", "chain", "inet", "block_subnet", "block_subnet-chain", "{ type filter hook input priority filter -200; }"])
- # Dictionnaire pour stocker les adresses IP et le nombre de requêtes par sous-réseau /20
- ip_count = {}
- # Fonction pour vérifier si un sous-réseau est déjà banni
- def is_banned(subnet):
- output = subprocess.check_output(["nft", "list", "table", "inet", "block_subnet"]).decode()
- return subnet in output
- # Fonction pour supprimer une règle de filtrage après un certain temps
- def remove_rule(subnet):
- subprocess.run(["nft", "delete", "rule", "inet", "block_subnet", "block_subnet-chain", "ip", "protocol", "tcp", "saddr", subnet, "drop"])
- subprocess.run(["nft", "delete", "rule", "inet", "block_subnet", "block_subnet-chain", "ip", "protocol", "tcp", "daddr", subnet, "drop"])
- subprocess.run(["nft", "delete", "rule", "inet", "block_subnet", "block_subnet-chain", "ip", "protocol", "udp", "saddr", subnet, "drop"])
- subprocess.run(["nft", "delete", "rule", "inet", "block_subnet", "block_subnet-chain", "ip", "protocol", "udp", "daddr", subnet, "drop"])
- subprocess.run(["nft", "delete", "rule", "ip", "nat", "prerouting", "ip", "saddr", subnet, "ip", "procotol", "udp", "drop"])
- subprocess.run(["nft", "delete", "rule", "ip", "nat", "prerouting", "ip", "daddr", subnet, "ip", "protocol", "udp", "drop"])
- print(f"Règle de filtrage pour {subnet} supprimée.")
- # Ajoute une règle de filtrage avec un délai de timeout
- def add_rule(subnet, duration):
- subprocess.run(["nft", "add", "rule", "inet", "block_subnet", "block_subnet-chain", "ip", "saddr", subnet, "ip", "protocol", "udp", "drop"])
- subprocess.run(["nft", "add", "rule", "inet", "block_subnet", "block_subnet-chain", "ip", "daddr", subnet, "ip", "protocol", "udp", "drop"])
- subprocess.run(["nft", "add", "rule", "inet", "block_subnet", "block_subnet-chain", "ip", "saddr", subnet, "ip", "protocol", "tcp", "drop"])
- subprocess.run(["nft", "add", "rule", "inet", "block_subnet", "block_subnet-chain", "ip", "daddr", subnet, "ip", "protocol", "tcp", "drop"])
- subprocess.run(["nft", "insert", "rule", "ip", "nat", "prerouting", "ip", "saddr", subnet, "ip", "protocol", "udp", "drop"])
- subprocess.run(["nft", "insert", "rule", "ip", "nat", "prerouting", "ip", "daddr", subnet, "ip", "protocol", "udp", "drop"])
- print(f"Règle de filtrage pour {subnet} ajoutée.")
- # Programme la suppression de la règle après la durée spécifiée
- schedule.every(duration).minutes.do(remove_rule, subnet)
- # Ouvre le fichier en mode lecture et suit les modifications en temps réel
- with open(args.file, "r") as f:
- f.seek(0, 2) # Place le curseur de lecture à la fin du fichier
- while True:
- line = f.readline()
- if not line:
- time.sleep(1) # Attend 1 seconde avant de relire le fichier
- continue
- data = json.loads(line)
- if data["QT"] == args.type:
- ip = ipaddress.IPv4Address(data["IP"])
- subnet = str(ipaddress.IPv4Network(ip.exploded + "/20", strict=False))
- timestamp = time.time()
- if subnet in ip_count:
- if timestamp - ip_count[subnet]["last_time"] < args.duree:
- ip_count[subnet]["count"] += 1
- if ip_count[subnet]["count"] >= args.seuil and not ip_count[subnet].get("alerted", False) and not is_banned(subnet):
- print(f"[{time.strftime('%Y-%m-%d %H:%M:%S')}] Sous-réseau {subnet} a dépassé le seuil de {args.seuil} requêtes de type {args.type} dans les {args.duree} dernières secondes.")
- ip_count[subnet]["alerted"] = True
- add_rule(subnet, args.ban)
- else:
- ip_count[subnet]["count"] = 1
- else:
- ip_count[subnet] = {"count": 1, "last_time": timestamp, "alerted": False}
- ip_count[subnet]["last_time"] = timestamp
- # Nettoie le dictionnaire après un certain temps
- now = time.time()
- ip_count = {k: v for k, v in ip_count.items() if now - v["last_time"] < args.nettoyage}
- # Démarre le programmeur de tâches
- while True:
- schedule.run_pending()
- time.sleep(1)
Advertisement
Add Comment
Please, Sign In to add comment