XaF / fail2ban-subnets

fail2ban-subnets aims to provide a way to ban subnets of IPs repeatingly banned by fail2ban for multiple offenses.
11 stars 3 forks source link

Code for python 2.4.x? #5

Open cepheid666 opened 5 years ago

cepheid666 commented 5 years ago

It would appear that fail2ban-subnets.py requires python 3, because it uses the bytes type in the isinstance check (line 201). This type is not available in python 2.x. Is there a patch that would make this work in 2.x (specifically 2.4.x) without using the bytes type in that line?

cepheid666 commented 5 years ago

Well, I guess I answered my own question... after a bunch of searching (particularly on stack overflow), I've got a version of the .py working with python 2.4.3 (so it should also work with newer versions, I think).

Diff as follows:

--- fail2ban-subnets.py.old 2018-11-05 21:46:34.000000000 -0500
+++ fail2ban-subnets.py 2018-11-05 21:47:19.000000000 -0500
@@ -28,6 +28,8 @@
 import subprocess
 import time

+strptime = lambda date_string, format: datetime(*(time.strptime(date_string, format)[0:6]))
+
 # Path of logfile to analyze (accepts jokers)
 filepath = '/var/log/fail2ban.log*'

@@ -42,6 +44,7 @@

 # Time format used in fail2ban logs
 timeformat = '%Y-%m-%d %H:%M:%S,%f'
+timeformat_noms = '%Y-%m-%d %H:%M:%S'

 # Whether or not to exclude from report already banned subnets.
 # This prevents the 'already banned' messages in fail2ban logs,
@@ -78,7 +81,7 @@

 ## Initialize logging
 logging.basicConfig(
-    format="%(asctime)s %(name)s: %(levelname)s %(message)s",
+    format="%(asctime)s %(name)s[%(process)d]: %(levelname)s %(message)s",
     level=logging.INFO,
     filename=logfile)

@@ -162,6 +165,29 @@
     return (a << 24) + (b << 16) + (c << 8) + d

+## Backport bin() to python 2.4
+def bin(x):
+    """
+    bin(number) -> string
+
+    Stringifies an int or long in base 2.
+    """
+    if x < 0: 
+        return '-' + bin(-x)
+    out = []
+    if x == 0: 
+        out.append('0')
+    while x > 0:
+        out.append('01'[x & 1])
+        x >>= 1
+        pass
+    try: 
+        return '0b' + ''.join(reversed(out))
+    except NameError, ne2: 
+        out.reverse()
+    return '0b' + ''.join(out)
+
+
 ## Calculate the subnet to use
 def get_subnet(iplist):
     splittedlist = []
@@ -198,7 +224,7 @@
         fh = open(f, 'rb')

     for l in fh:
-        if isinstance(l, bytes):
+        if isinstance(l, str):
             l = l.decode()

         m = lineregex.match(l)
@@ -206,8 +232,9 @@
         if not m:
             continue

-        dt = datetime.strptime(m.group('TIME'), timeformat)
-        fdt = float(dt.strftime('%s.%f'))
+        (dt, mSecs) = m.group('TIME').strip().split(",")
+        dt = strptime(dt, timeformat_noms)
+        fdt = float(dt.strftime('%s')) + int(mSecs)/1000.0
         if fdt < mintime:
             continue
XaF commented 5 years ago

Mmh pretty sure part of your changes are not compatible with Python 3. I've always used the script with Python 2 in the past, but Python 2.7, for which bytes is recognized as an alias of str. Is there a reason why you need support for Python 2.4 ? Seems to be far backwards, and Python 2 in its entirety will not be supported anymore in 2020.

cepheid666 commented 5 years ago

I'm tied to Python 2.4.3 on an ancient machine that I cannot retire at the moment. It will be retired in the next year or so, but no rigid schedule yet.

What parts won't work for Python 3? The backporting of bin could be done by a conditional definition, so I could modify that. I think the strptime should work in all versions. So then the only question is about bytes versus str, in which case we can do that conditionally as well... if bytes is defined, use it, otherwise str.

Thanks!