Guest User

Untitled

a guest
May 27th, 2018
776
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.25 KB | None | 0 0
  1. #!/usr/bin/env python
  2.  
  3. __author__ = 'Imam Omar Mochtar <iomarmochtar@gmail.com>'
  4.  
  5. """
  6. this script assume zimbra smtp and mailbox service in same server with original ip (oip) is logged
  7. the attempted/blocked IP will listed in AUDITWATCH chain. for applying block to it add rule in INPUT filter.
  8. Example:
  9. # iptables -t filter -I INPUT -j AUDITWATCH
  10. """
  11.  
  12. import re
  13. import sys
  14. import subprocess
  15. import smtplib
  16. from email.mime.multipart import MIMEMultipart
  17. from email.mime.text import MIMEText
  18. from email.utils import COMMASPACE, formatdate
  19. from pprint import pprint
  20.  
  21. ### VARIABLES BEGIN
  22. AUDIT_FILE = '/opt/zimbra/log/audit.log'
  23. CHAIN = 'AUDITWATCH'
  24. MAX_ATTEMPT = 5
  25.  
  26. # define white list here
  27. WHITELIST = re.compile( '(%s)' % '|'.join( map(lambda x: x.replace('.', '\.'), [
  28. '192.100'
  29. ])))
  30.  
  31. # list of blocked IP
  32. BLOCKED = set()
  33.  
  34. # this var will hold parsing result
  35. FAILED_IP = {}
  36.  
  37. ## SMTP
  38. REPORT_FROM = 'admin@mail.com'
  39. REPORT_TO = ['system.support@mail.com', 'iomarmochtar@gmail.com']
  40. REPORT_SUBJECT = 'Authentication Attempt Report'
  41. REPORT_SMTP = '127.0.0.1'
  42.  
  43. ### VARIABLES END
  44.  
  45.  
  46. def run_cmd(command):
  47. return subprocess.Popen(
  48. command, universal_newlines=True, shell=True,
  49. stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
  50.  
  51. # make sure chain are exists
  52. run_cmd("/sbin/iptables -nL {0} || /sbin/iptables -N {0}".format(CHAIN))
  53.  
  54. # grab listed of blocked IP
  55. output, err = run_cmd("/sbin/iptables -nL {0}".format(CHAIN))
  56. for txt in output.splitlines():
  57.  
  58. if txt.startswith('DROP'):
  59. brk = txt.split()
  60. if len(brk) != 5:
  61. continue
  62. BLOCKED.add(brk[3])
  63. continue
  64.  
  65. oip_parser = re.compile(r'oip=(?P<oip>.*?);.*?for\s+\[(?P<username>.*?)\],\s+invalid password;$')
  66.  
  67. # loop trough audit file to parse any failed authentication, capture OIP params
  68. for line in open(AUDIT_FILE, 'r').readlines():
  69. oip = oip_parser.search(line)
  70. if not oip:
  71. continue
  72.  
  73. data = oip.groupdict()
  74. ip = data['oip']
  75.  
  76. # if the IP was listed in existing block and ignore list then skip it
  77. if ip in BLOCKED or WHITELIST.search(ip):
  78. continue
  79.  
  80. if not FAILED_IP.has_key(ip):
  81. FAILED_IP[ip] = {'users': set(), 'attempt': 0}
  82.  
  83. FAILED_IP[ip]['users'].add(data['username'])
  84. FAILED_IP[ip]['attempt'] += 1
  85.  
  86. # input IP in CHAIN if has reach maximum var
  87. is_report = False
  88. text = "<h3><b>List of auth attempt</b></h3> <br/><br/><br/>"
  89. f_cmd = "/sbin/iptables -I {0} -p tcp -s {1} -j DROP"
  90. for ip, data in FAILED_IP.items():
  91. if data['attempt'] <= MAX_ATTEMPT:
  92. continue
  93. is_report = True
  94. cmd = f_cmd.format(CHAIN, ip)
  95. print("IP {0} has reach max attempt {1} ({2})".format(ip, MAX_ATTEMPT, data['attempt']))
  96. run_cmd(cmd)
  97. text += "<b><u>{0} for {1} times</u></b> <br/><ul>".format(ip, data['attempt'])
  98. for user in data['users']:
  99. text += "<li>{0}</li>".format(user)
  100. text += "</ul>"
  101.  
  102.  
  103. if not is_report:
  104. sys.exit(0)
  105.  
  106. print("sending report")
  107. msg = MIMEMultipart()
  108. msg['From'] = REPORT_FROM
  109. msg['To'] = COMMASPACE.join(REPORT_TO)
  110. msg['Date'] = formatdate(localtime=True)
  111. msg['Subject'] = REPORT_SUBJECT
  112.  
  113. msg.attach(MIMEText(text, 'html'))
  114. msg.attach(MIMEText("Please see this email as HTML", 'plain'))
  115.  
  116. smtp = smtplib.SMTP(REPORT_SMTP)
  117. smtp.sendmail(REPORT_FROM, REPORT_TO, msg.as_string())
  118. smtp.close()
Add Comment
Please, Sign In to add comment