Advertisement
Blizzardo1

Untitled

Oct 12th, 2024
76
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 6.20 KB | Source Code | 0 0
  1. import os
  2. import re
  3. import requests
  4. import json
  5. import sqlite3
  6.  
  7. from pylog import PyLog
  8. from datetime import datetime
  9. from sys import argv
  10.  
  11. database = 'abuseip.db'
  12. conn = sqlite3.connect(database)
  13. myIp = "0.0.0.0"
  14. base_url = 'https://api.abuseipdb.com/api/v2/'
  15. api_key = (
  16.     'YOUR_API_KEY_HERE'
  17. )
  18.  
  19. log = PyLog('abuseip.log')
  20. whitelist = ['0.0.0.0']  # White list of IP addresses
  21. force_report = False
  22.  
  23.  
  24. def close():
  25.     conn.close()
  26.  
  27.  
  28. def write_to_db(ip, confidence, categories, timestamp):
  29.     c = conn.cursor()
  30.     c.execute(
  31.         'CREATE TABLE IF NOT EXISTS ip_reports ('
  32.         'ip TEXT, confidence INTEGER, categories TEXT, timestamp TEXT)'
  33.     )
  34.     # print(f"Writing to db: {ip}, {confidence}, {categories}, {timestamp}")
  35.     c.execute(
  36.         'INSERT INTO ip_reports VALUES (?, ?, ?, ?)',
  37.         (ip, confidence, categories, timestamp)
  38.     )
  39.     conn.commit()
  40.  
  41.  
  42. def read_from_db(ip):
  43.     c = conn.cursor()
  44.     c.execute('SELECT * FROM ip_reports WHERE ip = ?', (ip,))
  45.     return c.fetchall()
  46.  
  47.  
  48. def check(ip):
  49.     if (ip in whitelist):
  50.         log.warning(f'IP address: {ip} is whitelisted.')
  51.         return (False, None, 0)
  52.  
  53.     url = base_url + 'check'
  54.     querystring = {
  55.         'ipAddress': ip,
  56.         'maxAgeInDays': '365'
  57.     }
  58.  
  59.     headers = {
  60.         'Accept': 'application/json',
  61.         'Key': api_key
  62.     }
  63.  
  64.     response = requests.get(url, headers=headers, params=querystring)
  65.     decoded_response = json.loads(response.text)
  66.     ipAddress = decoded_response['data']['ipAddress']
  67.     totalReports = decoded_response['data']['totalReports']
  68.     confidence = decoded_response['data']['abuseConfidenceScore']
  69.  
  70.     if totalReports > 0 and confidence > 0:
  71.         log.warning(
  72.             f'The IP address: {ipAddress} has previous reports on '
  73.             f'file, and a confidence score of {confidence}.'
  74.         )
  75.         return (
  76.             True,
  77.             decoded_response['data']['abuseConfidenceScore'],
  78.             totalReports
  79.         )
  80.     elif totalReports > 0 and confidence == 0:
  81.         log.normal(
  82.             f'The IP address: {ipAddress} is suspicious as it has been '
  83.             f'reported, but appears legitimate, so sayeth AbuseIPDB.'
  84.         )
  85.     else:
  86.         log.info(f'No abuse reports found for IP address: {ip}')
  87.     return (False, None, 0)
  88.  
  89.  
  90. def ban(ip, categories, timestamp, comment):
  91.     url = base_url + 'report'
  92.     params = {
  93.         'ip': ip,
  94.         'categories': categories,
  95.         'timestamp': timestamp,
  96.         'comment': comment
  97.     }
  98.     headers = {
  99.         'Accept': 'application/json',
  100.         'Key': api_key
  101.     }
  102.     response = requests.post(url, headers=headers, params=params)
  103.     decoded_response = json.loads(response.text)
  104.     if 'errors' in decoded_response.keys():
  105.         error = decoded_response['errors'][0]['detail']
  106.         log.error(f'Error: {error}')
  107.         return
  108.     ipAddress = decoded_response['data']['ipAddress']
  109.     confidence = decoded_response['data']['abuseConfidenceScore']
  110.     log.success(
  111.         f'You\'ve successfully reported the IP address: {ipAddress}! '
  112.         f'Confidence score: {confidence}'
  113.     )
  114.  
  115.  
  116. def parse_nginx_log(file_path):
  117.     with open(file_path, 'r') as file:
  118.         for line in file:
  119.             match = re.match(r'(\d+\.\d+\.\d+\.\d+) - - \[(.*?)\] "(.*?)"',
  120.                              line)
  121.             if match:
  122.                 ip = match.group(1)
  123.                 if ip == myIp:  # Skip this IP address
  124.                     continue
  125.                 if 'ip_messages' not in locals():
  126.                     ip_messages = {}
  127.                 timestamp = match.group(2)
  128.                 # Convert timestamp to Atom format
  129.                 timestamp_format = (
  130.                     "%d/%b/%Y:%H:%M:%S %z"
  131.                 )
  132.                 timestamp_obj = datetime.strptime(timestamp,
  133.                                                   timestamp_format)
  134.                 atom_timestamp = timestamp_obj.isoformat()
  135.                 message = match.group(3)
  136.                 try:
  137.                     lst = read_from_db(ip)
  138.                     if (not force_report):
  139.                         if (len(lst) > 0 and lst[0][3] == timestamp):
  140.                             log.warning(
  141.                                 f'IP: {ip} has been reported before.'
  142.                             )
  143.                         else:
  144.                             log.warning(
  145.                                 f'IP: {ip} has been reported before, '
  146.                                 f'but not at this time.'
  147.                             )
  148.                         continue
  149.                 except Exception as e:
  150.                     log.error(f'Error: {e}')
  151.                 if ip in ip_messages:
  152.                     ip_messages[ip] += f" | {message}"
  153.                 else:
  154.                     ip_messages[ip] = message
  155.  
  156.         for ip, message in ip_messages.items():
  157.             # print(f"IP: {ip}, Message: {message}")
  158.             message = (message[:1020] + '...') if len(
  159.                         message) > 1024 else message
  160.             c = check(ip)
  161.             if c[0]:
  162.                 cats = '18'
  163.                 if (message.find('Custom-AsyncHttpClient') != -1):
  164.                     cats += ',15'
  165.                 if (message.find('GET /robots.txt') != -1):
  166.                     cats += ',19'
  167.                 if (message.find('GET /wp-admin') != -1 or
  168.                         message.find('GET /wp-login.php') != -1 or
  169.                         message.find('GET /wp-content') != -1):
  170.                     cats += ',21'
  171.                 ban(ip, cats, atom_timestamp, message)
  172.                 write_to_db(ip, c[1], cats, atom_timestamp)
  173.     return len(ip_messages)
  174.  
  175.  
  176. if __name__ == "__main__":
  177.     if len(argv) < 2:
  178.         log.usage("Usage: python abuseip.py <nginx_log_file> [force_report]")
  179.         exit(1)
  180.  
  181.     log_file_path = argv[1]
  182.     if (len(argv) == 3 and argv[2] == "force_report"):
  183.         log.info("Force report mode enabled.")
  184.         force_report = True
  185.  
  186.     if not os.path.exists(log_file_path):
  187.         log.error(f"Error: File {log_file_path} not found.")
  188.         exit(1)
  189.  
  190.     count = parse_nginx_log(log_file_path)
  191.     log.info(f"Total unique IP addresses: {count}")
  192.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement