From 3d477d229d169a3dedcb7144bb24f4ea08d93c02 Mon Sep 17 00:00:00 2001 From: SP Date: Thu, 3 Jan 2019 22:47:24 +0300 Subject: [PATCH] ENH: added new command `fail2ban-client get banip` to get the banned ip addresses (gh-1916) --- ChangeLog | 1 + fail2ban/client/beautifier.py | 2 ++ fail2ban/server/actions.py | 10 +++++++ fail2ban/server/server.py | 15 ++++++++++ fail2ban/server/transmitter.py | 2 ++ fail2ban/tests/servertestcase.py | 50 ++++++++++++++++++++++++++++++++ man/fail2ban-client.1 | 4 +++ 7 files changed, 84 insertions(+) diff --git a/ChangeLog b/ChangeLog index b9efbc10..8f12b49a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -56,6 +56,7 @@ ver. 0.11.0-dev-0 (20??/??/??) - development nightly edition end of ban) of the ticket with ban-time of jail (as maximum), for all tickets with ban-time greater (or persistent); not affected if ban-time of the jail is unchanged between stop/start. * added new setup-option `--without-tests` to skip building and installing of tests files (gh-2287). +* added new command `fail2ban-client get banip` to get the banned ip addresses (gh-1916). ver. 0.10.4-dev-1 (20??/??/??) - development edition diff --git a/fail2ban/client/beautifier.py b/fail2ban/client/beautifier.py index 4d9e549f..607c0ade 100644 --- a/fail2ban/client/beautifier.py +++ b/fail2ban/client/beautifier.py @@ -180,6 +180,8 @@ class Beautifier: msg = "The jail %s action %s has the following " \ "methods:\n" % (inC[1], inC[3]) msg += ", ".join(response) + elif inC[2] == "banip" and inC[0] == "get": + msg = " ".join(response) except Exception: logSys.warning("Beautifier error. Please report the error") logSys.error("Beautify %r with %r failed", response, self.__inputCmd, diff --git a/fail2ban/server/actions.py b/fail2ban/server/actions.py index 3d862275..11a905be 100644 --- a/fail2ban/server/actions.py +++ b/fail2ban/server/actions.py @@ -204,6 +204,16 @@ class Actions(JailThread, Mapping): def getBanTime(self): return self.__banManager.getBanTime() + def getBanList(self): + """Returns the list of banned IP addresses. + + Returns + ------- + list + The list of banned IP addresses. + """ + return self.__banManager.getBanList() + def removeBannedIP(self, ip=None, db=True, ifexists=False): """Removes banned IP calling actions' unban method diff --git a/fail2ban/server/server.py b/fail2ban/server/server.py index dfbbd5d7..5370808c 100644 --- a/fail2ban/server/server.py +++ b/fail2ban/server/server.py @@ -510,6 +510,21 @@ class Server: def getBanTime(self, name): return self.__jails[name].actions.getBanTime() + def getBanList(self, name): + """Returns the list of banned IP addresses for a jail. + + Parameters + ---------- + name : str + The name of a jail. + + Returns + ------- + list + The list of banned IP addresses. + """ + return self.__jails[name].actions.getBanList() + def setBanTimeExtra(self, name, opt, value): self.__jails[name].setBanTimeExtra(opt, value) diff --git a/fail2ban/server/transmitter.py b/fail2ban/server/transmitter.py index c24408c4..e3e05eb6 100644 --- a/fail2ban/server/transmitter.py +++ b/fail2ban/server/transmitter.py @@ -390,6 +390,8 @@ class Transmitter: # Action elif command[1] == "bantime": return self.__server.getBanTime(name) + elif command[1] == "banip": + return self.__server.getBanList(name) elif command[1].startswith("bantime."): opt = command[1][len("bantime."):] return self.__server.getBanTimeExtra(name, opt) diff --git a/fail2ban/tests/servertestcase.py b/fail2ban/tests/servertestcase.py index 8b616abc..14905b76 100644 --- a/fail2ban/tests/servertestcase.py +++ b/fail2ban/tests/servertestcase.py @@ -103,6 +103,34 @@ class TransmitterBase(LogCaptureTestCase): # if we expected to get it set without problem, check new value self.assertEqual(v(self.transm.proceed(getCmd)), v((0, outValue))) + def getBanListTest(self, jail, banip=None, unbanip=None, outList=None): + """Process set banip/set unbanip commands and compare the list of + banned IP addresses with outList.""" + def v(value): + """Prepare value for comparison.""" + if value[1] is None: + tmp = [] + else: + tmp = map(str, value[1]) + return (value[0], sorted(tmp)) + + # Ban IP address + if banip is not None: + self.assertEqual( + self.transm.proceed(["set", jail, "banip", banip]), + (0, banip)) + time.sleep(Utils.DEFAULT_SLEEP_TIME) # Give chance to ban + # Unban IP address + if unbanip is not None: + self.assertEqual( + self.transm.proceed(["set", jail, "unbanip", unbanip]), + (0, unbanip)) + time.sleep(Utils.DEFAULT_SLEEP_TIME) # Give chance to unban + # Compare the list of banned IP addresses with outList + self.assertEqual( + v(self.transm.proceed(["get", jail, "banip"])), + v((0, outList))) + def setGetTestNOK(self, cmd, inValue, jail=None): setCmd = ["set", cmd, inValue] getCmd = ["get", cmd] @@ -347,6 +375,28 @@ class Transmitter(TransmitterBase): self.transm.proceed( ["set", self.jailName, "unbanip", "192.168.1.1"])[0],1) + def testJailBanList(self): + jail = "TestJailBanList" + self.server.addJail(jail, FAST_BACKEND) + self.server.startJail(jail) + + self.getBanListTest(jail) + self.getBanListTest( + jail, banip="127.0.0.1", outList=["127.0.0.1"]) + self.getBanListTest( + jail, banip="192.168.0.1", + outList=["127.0.0.1", "192.168.0.1"]) + self.getBanListTest( + jail, banip="192.168.1.10", + outList=["127.0.0.1", "192.168.0.1", "192.168.1.10"]) + self.getBanListTest( + jail, unbanip="127.0.0.1", + outList=["192.168.0.1", "192.168.1.10"]) + self.getBanListTest( + jail, unbanip="192.168.1.10", outList=["192.168.0.1"]) + self.getBanListTest(jail, unbanip="192.168.0.1", outList=[]) + self.getBanListTest(jail) + def testJailMaxRetry(self): self.setGetTest("maxretry", "5", 5, jail=self.jailName) self.setGetTest("maxretry", "2", 2, jail=self.jailName) diff --git a/man/fail2ban-client.1 b/man/fail2ban-client.1 index d1226d56..81883ce2 100644 --- a/man/fail2ban-client.1 +++ b/man/fail2ban-client.1 @@ -379,6 +379,10 @@ will look back for failures for gets the time a host is banned for .TP +\fBget banip\fR +gets the list of banned IP +addresses for +.TP \fBget datepattern\fR gets the patern used to match date/times for