From 85b895178b8a6dd9ce7c9086c8c451b72efdb4c1 Mon Sep 17 00:00:00 2001 From: Alexander Koeppe Date: Wed, 2 Mar 2016 06:56:57 +0100 Subject: [PATCH] change IP address string to object handling part 1 # Conflicts: # fail2ban/server/filter.py --- fail2ban/server/actions.py | 9 ++++++--- fail2ban/server/banmanager.py | 6 +++--- fail2ban/server/database.py | 16 ++++++++++------ fail2ban/server/filter.py | 18 ++++++++++++------ fail2ban/server/ticket.py | 3 --- 5 files changed, 31 insertions(+), 21 deletions(-) diff --git a/fail2ban/server/actions.py b/fail2ban/server/actions.py index 5469722f..428d1ccf 100644 --- a/fail2ban/server/actions.py +++ b/fail2ban/server/actions.py @@ -42,6 +42,7 @@ from .banmanager import BanManager from .jailthread import JailThread from .action import ActionBase, CommandAction, CallingMap from .mytime import MyTime +from .filter import IPAddr from .utils import Utils from ..helpers import getLogger @@ -180,7 +181,7 @@ class Actions(JailThread, Mapping): def getBanTime(self): return self.__banManager.getBanTime() - def removeBannedIP(self, ip): + def removeBannedIP(self, ipstr): """Removes banned IP calling actions' unban method Remove a banned IP now, rather than waiting for it to expire, @@ -188,14 +189,16 @@ class Actions(JailThread, Mapping): Parameters ---------- - ip : str - The IP address to unban + ipstr : str + The IP address string to unban Raises ------ ValueError If `ip` is not banned """ + # Create new IPAddr object from IP string + ip = IPAddr(ipstr) # Always delete ip from database (also if currently not banned) if self._jail.database is not None: self._jail.database.delBan(self._jail, ip) diff --git a/fail2ban/server/banmanager.py b/fail2ban/server/banmanager.py index 0ee028ef..67ae1b71 100644 --- a/fail2ban/server/banmanager.py +++ b/fail2ban/server/banmanager.py @@ -152,9 +152,9 @@ class BanManager: for banData in self.__banList: ip = banData.getIP() # Reference: http://www.team-cymru.org/Services/ip-to-asn.html#dns - # TODO: IPv6 compatibility - reversed_ip = ".".join(reversed(ip.split("."))) - question = "%s.origin.asn.cymru.com" % reversed_ip + question = ip.getPTR("origin.asn.cymru.com" if ip.isIPv4() + else "origin6.asn.cymru.com" + ) try: answers = dns.resolver.query(question, "TXT") for rdata in answers: diff --git a/fail2ban/server/database.py b/fail2ban/server/database.py index b7fd4d47..e5e51992 100644 --- a/fail2ban/server/database.py +++ b/fail2ban/server/database.py @@ -32,6 +32,7 @@ from threading import RLock from .mytime import MyTime from .ticket import FailTicket +from .filter import IPAddr from ..helpers import getLogger # Gets the instance of the logger. @@ -422,7 +423,7 @@ class Fail2BanDb(object): #TODO: Implement data parts once arbitrary match keys completed cur.execute( "INSERT INTO bans(jail, ip, timeofban, data) VALUES(?, ?, ?, ?)", - (jail.name, ticket.getIP(), int(round(ticket.getTime())), + (jail.name, ticket.getIP().ntoa(), int(round(ticket.getTime())), ticket.getData())) @commitandrollback @@ -436,7 +437,7 @@ class Fail2BanDb(object): ip : str IP to be removed. """ - queryArgs = (jail.name, ip); + queryArgs = (jail.name, ip.ntoa()); cur.execute( "DELETE FROM bans WHERE jail = ? AND ip = ?", queryArgs); @@ -454,7 +455,7 @@ class Fail2BanDb(object): queryArgs.append(MyTime.time() - bantime) if ip is not None: query += " AND ip=?" - queryArgs.append(ip) + queryArgs.append(ip.ntoa()) query += " ORDER BY ip, timeofban desc" return cur.execute(query, queryArgs) @@ -470,7 +471,7 @@ class Fail2BanDb(object): Ban time in seconds, such that bans returned would still be valid now. Negative values are equivalent to `None`. Default `None`; no limit. - ip : str + ip : IPAddr object IP Address to filter bans by. Default `None`; all IPs. Returns @@ -479,7 +480,8 @@ class Fail2BanDb(object): List of `Ticket`s for bans stored in database. """ tickets = [] - for ip, timeofban, data in self._getBans(**kwargs): + for ipstr, timeofban, data in self._getBans(**kwargs): + ip = IPAddr(ipstr) #TODO: Implement data parts once arbitrary match keys completed tickets.append(FailTicket(ip, timeofban)) tickets[-1].setData(data) @@ -499,7 +501,7 @@ class Fail2BanDb(object): Ban time in seconds, such that bans returned would still be valid now. Negative values are equivalent to `None`. Default `None`; no limit. - ip : str + ip : IPAddr object IP Address to filter bans by. Default `None`; all IPs. Returns @@ -520,6 +522,8 @@ class Fail2BanDb(object): ticket = None results = list(self._getBans(ip=ip, jail=jail, bantime=bantime)) + # Convert IP strings to IPAddr objects + results = map(lambda i:(IPAddr(i[0]),)+i[1:], results) if results: prev_banip = results[0][0] matches = [] diff --git a/fail2ban/server/filter.py b/fail2ban/server/filter.py index 3682125c..371a13d7 100644 --- a/fail2ban/server/filter.py +++ b/fail2ban/server/filter.py @@ -306,13 +306,19 @@ class Filter(JailThread): def getIgnoreCommand(self): return self.__ignoreCommand + ## + # create new IPAddr object from IP address string + def newIP(self, ipstr): + return IPAddr(ipstr) + ## # Ban an IP - http://blogs.buanzo.com.ar/2009/04/fail2ban-patch-ban-ip-address-manually.html # Arturo 'Buanzo' Busleiman # # to enable banip fail2ban-client BAN command - def addBannedIP(self, ip): + def addBannedIP(self, ipstr): + ip = IPAddr(ipstr) if self.inIgnoreIPList(ip): logSys.warning('Requested to manually ban an ignored IP %s. User knows best. Proceeding to ban it.' % ip) @@ -540,11 +546,11 @@ class Filter(JailThread): if not checkAllRegex: break else: - ipMatch = DNSUtils.textToIp(host, self.__useDns) - if ipMatch: - for ip in ipMatch: - failList.append([failRegexIndex, ip, date, - failRegex.getMatchedLines()]) + ips = DNSUtils.textToIp(host, self.__useDns) + if ips: + for ip in ips: + failList.append([failRegexIndex, ip, + date, failRegex.getMatchedLines()]) if not checkAllRegex: break except RegexException, e: # pragma: no cover - unsure if reachable diff --git a/fail2ban/server/ticket.py b/fail2ban/server/ticket.py index b3eea052..7b7eb908 100644 --- a/fail2ban/server/ticket.py +++ b/fail2ban/server/ticket.py @@ -72,9 +72,6 @@ class Ticket: return False def setIP(self, value): - if isinstance(value, basestring): - # guarantee using regular str instead of unicode for the IP - value = str(value) self.__ip = value def getIP(self):