Guest User

Untitled

a guest
Aug 5th, 2024
95
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.46 KB | None | 0 0
  1. #!/usr/bin/python3
  2.  
  3. import argparse
  4. import json
  5. import time
  6. import subprocess
  7. import schedule
  8. import ipaddress
  9.  
  10. # Paramètres modifiables par l'utilisateur
  11. parser = argparse.ArgumentParser()
  12. parser.add_argument("-f", "--file", help="Chemin d'accès au fichier de log", required=False, default="/srv/adguardhome/workdir/data/querylog.json")
  13. parser.add_argument("-t", "--type", help="Type de requête à identifier (TXT, A, ALL)", default="TXT")
  14. parser.add_argument("-s", "--seuil", help="Seuil du nombre de requêtes", type=int, default=4)
  15. 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)
  16. parser.add_argument("-b", "--ban", help="Durée du ban en minutes", type=int, default=10)
  17. parser.add_argument("-n", "--nettoyage", help="Temps avant de nettoyer le dictionnaire en secondes", type=int, default=60)
  18. args = parser.parse_args()
  19.  
  20. # Supprime la table nftables block_subnet si elle existe déjà
  21. subprocess.run(["nft", "delete", "table", "inet", "block_subnet"], stderr=subprocess.DEVNULL)
  22.  
  23. # Création de la table nftables block_subnet
  24. subprocess.run(["nft", "add", "table", "inet", "block_subnet"])
  25.  
  26. # Ajout de la chaîne d'entrée block_subnet
  27. subprocess.run(["nft", "add", "chain", "inet", "block_subnet", "block_subnet-chain", "{ type filter hook input priority filter -200; }"])
  28.  
  29. # Dictionnaire pour stocker les adresses IP et le nombre de requêtes par sous-réseau /20
  30. ip_count = {}
  31.  
  32. # Fonction pour vérifier si un sous-réseau est déjà banni
  33. def is_banned(subnet):
  34. output = subprocess.check_output(["nft", "list", "table", "inet", "block_subnet"]).decode()
  35. return subnet in output
  36.  
  37. # Fonction pour supprimer une règle de filtrage après un certain temps
  38. def remove_rule(subnet):
  39. subprocess.run(["nft", "delete", "rule", "inet", "block_subnet", "block_subnet-chain", "ip", "protocol", "tcp", "saddr", subnet, "drop"])
  40. subprocess.run(["nft", "delete", "rule", "inet", "block_subnet", "block_subnet-chain", "ip", "protocol", "tcp", "daddr", subnet, "drop"])
  41. subprocess.run(["nft", "delete", "rule", "inet", "block_subnet", "block_subnet-chain", "ip", "protocol", "udp", "saddr", subnet, "drop"])
  42. subprocess.run(["nft", "delete", "rule", "inet", "block_subnet", "block_subnet-chain", "ip", "protocol", "udp", "daddr", subnet, "drop"])
  43.  
  44. subprocess.run(["nft", "delete", "rule", "ip", "nat", "prerouting", "ip", "saddr", subnet, "ip", "procotol", "udp", "drop"])
  45. subprocess.run(["nft", "delete", "rule", "ip", "nat", "prerouting", "ip", "daddr", subnet, "ip", "protocol", "udp", "drop"])
  46. print(f"Règle de filtrage pour {subnet} supprimée.")
  47.  
  48. # Ajoute une règle de filtrage avec un délai de timeout
  49. def add_rule(subnet, duration):
  50. subprocess.run(["nft", "add", "rule", "inet", "block_subnet", "block_subnet-chain", "ip", "saddr", subnet, "ip", "protocol", "udp", "drop"])
  51. subprocess.run(["nft", "add", "rule", "inet", "block_subnet", "block_subnet-chain", "ip", "daddr", subnet, "ip", "protocol", "udp", "drop"])
  52. subprocess.run(["nft", "add", "rule", "inet", "block_subnet", "block_subnet-chain", "ip", "saddr", subnet, "ip", "protocol", "tcp", "drop"])
  53. subprocess.run(["nft", "add", "rule", "inet", "block_subnet", "block_subnet-chain", "ip", "daddr", subnet, "ip", "protocol", "tcp", "drop"])
  54.  
  55. subprocess.run(["nft", "insert", "rule", "ip", "nat", "prerouting", "ip", "saddr", subnet, "ip", "protocol", "udp", "drop"])
  56. subprocess.run(["nft", "insert", "rule", "ip", "nat", "prerouting", "ip", "daddr", subnet, "ip", "protocol", "udp", "drop"])
  57. print(f"Règle de filtrage pour {subnet} ajoutée.")
  58. # Programme la suppression de la règle après la durée spécifiée
  59. schedule.every(duration).minutes.do(remove_rule, subnet)
  60.  
  61. # Ouvre le fichier en mode lecture et suit les modifications en temps réel
  62. with open(args.file, "r") as f:
  63. f.seek(0, 2) # Place le curseur de lecture à la fin du fichier
  64. while True:
  65. line = f.readline()
  66. if not line:
  67. time.sleep(1) # Attend 1 seconde avant de relire le fichier
  68. continue
  69. data = json.loads(line)
  70. if data["QT"] == args.type:
  71. ip = ipaddress.IPv4Address(data["IP"])
  72. subnet = str(ipaddress.IPv4Network(ip.exploded + "/20", strict=False))
  73. timestamp = time.time()
  74. if subnet in ip_count:
  75. if timestamp - ip_count[subnet]["last_time"] < args.duree:
  76. ip_count[subnet]["count"] += 1
  77. if ip_count[subnet]["count"] >= args.seuil and not ip_count[subnet].get("alerted", False) and not is_banned(subnet):
  78. 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.")
  79. ip_count[subnet]["alerted"] = True
  80. add_rule(subnet, args.ban)
  81. else:
  82. ip_count[subnet]["count"] = 1
  83. else:
  84. ip_count[subnet] = {"count": 1, "last_time": timestamp, "alerted": False}
  85. ip_count[subnet]["last_time"] = timestamp
  86.  
  87. # Nettoie le dictionnaire après un certain temps
  88. now = time.time()
  89. ip_count = {k: v for k, v in ip_count.items() if now - v["last_time"] < args.nettoyage}
  90.  
  91. # Démarre le programmeur de tâches
  92. while True:
  93. schedule.run_pending()
  94. time.sleep(1)
  95.  
Advertisement
Add Comment
Please, Sign In to add comment