mirror of https://github.com/fail2ban/fail2ban
Merge branch '0.10-extend-proto-banned' into 0.10
commit
b8e2b77265
|
@ -55,6 +55,8 @@ protocol = [
|
|||
["stop", "stops all jails and terminate the server"],
|
||||
["unban --all", "unbans all IP addresses (in all jails and database)"],
|
||||
["unban <IP> ... <IP>", "unbans <IP> (in all jails and database)"],
|
||||
["banned", "return jails with banned IPs as dictionary"],
|
||||
["banned <IP> ... <IP>]", "return list(s) of jails where given IP(s) are banned"],
|
||||
["status", "gets the current status of the server"],
|
||||
["ping", "tests if the server is alive"],
|
||||
["echo", "for internal usage, returns back and outputs a given string"],
|
||||
|
@ -120,6 +122,8 @@ protocol = [
|
|||
["set <JAIL> action <ACT> <PROPERTY> <VALUE>", "sets the <VALUE> of <PROPERTY> for the action <ACT> for <JAIL>"],
|
||||
["set <JAIL> action <ACT> <METHOD>[ <JSONKWARGS>]", "calls the <METHOD> with <JSONKWARGS> for the action <ACT> for <JAIL>"],
|
||||
['', "JAIL INFORMATION", ""],
|
||||
["get <JAIL> banned", "return banned IPs of <JAIL>"],
|
||||
["get <JAIL> banned <IP> ... <IP>]", "return 1 if IP is banned in <JAIL> otherwise 0, or a list of 1/0 for multiple IPs"],
|
||||
["get <JAIL> logpath", "gets the list of the monitored files for <JAIL>"],
|
||||
["get <JAIL> logencoding", "gets the encoding of the log files for <JAIL>"],
|
||||
["get <JAIL> journalmatch", "gets the journal filter match for <JAIL>"],
|
||||
|
|
|
@ -210,6 +210,14 @@ class Actions(JailThread, Mapping):
|
|||
def getBanTime(self):
|
||||
return self.__banManager.getBanTime()
|
||||
|
||||
def getBanned(self, ids):
|
||||
lst = self.__banManager.getBanList()
|
||||
if not ids:
|
||||
return lst
|
||||
if len(ids) == 1:
|
||||
return 1 if ids[0] in lst else 0
|
||||
return map(lambda ip: 1 if ip in lst else 0, ids)
|
||||
|
||||
def addBannedIP(self, ip):
|
||||
"""Ban an IP or list of IPs."""
|
||||
unixTime = MyTime.time()
|
||||
|
|
|
@ -521,6 +521,32 @@ class Server:
|
|||
cnt += jail.actions.removeBannedIP(value, ifexists=ifexists)
|
||||
return cnt
|
||||
|
||||
def banned(self, name=None, ids=None):
|
||||
if name is not None:
|
||||
# single jail:
|
||||
jails = [self.__jails[name]]
|
||||
else:
|
||||
# in all jails:
|
||||
jails = self.__jails.values()
|
||||
# check banned ids:
|
||||
res = []
|
||||
if name is None and ids:
|
||||
for ip in ids:
|
||||
ret = []
|
||||
for jail in jails:
|
||||
if jail.actions.getBanned([ip]):
|
||||
ret.append(jail.name)
|
||||
res.append(ret)
|
||||
else:
|
||||
for jail in jails:
|
||||
ret = jail.actions.getBanned(ids)
|
||||
if name is not None:
|
||||
return ret
|
||||
res.append(ret)
|
||||
else:
|
||||
res.append({jail.name: ret})
|
||||
return res
|
||||
|
||||
def getBanTime(self, name):
|
||||
return self.__jails[name].actions.getBanTime()
|
||||
|
||||
|
|
|
@ -118,6 +118,9 @@ class Transmitter:
|
|||
if len(value) == 1 and value[0] == "--all":
|
||||
return self.__server.setUnbanIP()
|
||||
return self.__server.setUnbanIP(None, value)
|
||||
elif name == "banned":
|
||||
# check IP is banned in all jails:
|
||||
return self.__server.banned(None, command[1:])
|
||||
elif name == "echo":
|
||||
return command[1:]
|
||||
elif name == "server-status":
|
||||
|
@ -424,7 +427,10 @@ class Transmitter:
|
|||
return None
|
||||
else:
|
||||
return db.purgeage
|
||||
# Filter
|
||||
# Jail, Filter
|
||||
elif command[1] == "banned":
|
||||
# check IP is banned in all jails:
|
||||
return self.__server.banned(name, command[2:])
|
||||
elif command[1] == "logpath":
|
||||
return self.__server.getLogPath(name)
|
||||
elif command[1] == "logencoding":
|
||||
|
|
|
@ -37,7 +37,7 @@ from threading import Thread
|
|||
|
||||
from ..client import fail2banclient, fail2banserver, fail2bancmdline
|
||||
from ..client.fail2bancmdline import Fail2banCmdLine
|
||||
from ..client.fail2banclient import exec_command_line as _exec_client, VisualWait
|
||||
from ..client.fail2banclient import exec_command_line as _exec_client, CSocket, VisualWait
|
||||
from ..client.fail2banserver import Fail2banServer, exec_command_line as _exec_server
|
||||
from .. import protocol
|
||||
from ..server import server
|
||||
|
@ -421,6 +421,14 @@ class Fail2banClientServerBase(LogCaptureTestCase):
|
|||
self.assertRaises(exitType, self.exec_command_line[0],
|
||||
(self.exec_command_line[1:] + startparams + args))
|
||||
|
||||
def execCmdDirect(self, startparams, *args):
|
||||
sock = startparams[startparams.index('-s')+1]
|
||||
s = CSocket(sock)
|
||||
try:
|
||||
return s.send(args)
|
||||
finally:
|
||||
s.close()
|
||||
|
||||
#
|
||||
# Common tests
|
||||
#
|
||||
|
@ -1007,6 +1015,30 @@ class Fail2banServerTest(Fail2banClientServerBase):
|
|||
"[test-jail2] Found 192.0.2.3",
|
||||
"[test-jail2] Ban 192.0.2.3",
|
||||
all=True)
|
||||
# test banned command:
|
||||
self.assertSortedEqual(self.execCmdDirect(startparams,
|
||||
'banned'), (0, [
|
||||
{'test-jail1': ['192.0.2.4', '192.0.2.1', '192.0.2.8', '192.0.2.3', '192.0.2.2']},
|
||||
{'test-jail2': ['192.0.2.4', '192.0.2.9', '192.0.2.8']}
|
||||
]
|
||||
))
|
||||
self.assertSortedEqual(self.execCmdDirect(startparams,
|
||||
'banned', '192.0.2.1', '192.0.2.4', '192.0.2.222'), (0, [
|
||||
['test-jail1'], ['test-jail1', 'test-jail2'], []
|
||||
]
|
||||
))
|
||||
self.assertSortedEqual(self.execCmdDirect(startparams,
|
||||
'get', 'test-jail1', 'banned')[1], [
|
||||
'192.0.2.4', '192.0.2.1', '192.0.2.8', '192.0.2.3', '192.0.2.2'])
|
||||
self.assertSortedEqual(self.execCmdDirect(startparams,
|
||||
'get', 'test-jail2', 'banned')[1], [
|
||||
'192.0.2.4', '192.0.2.9', '192.0.2.8'])
|
||||
self.assertEqual(self.execCmdDirect(startparams,
|
||||
'get', 'test-jail1', 'banned', '192.0.2.3')[1], 1)
|
||||
self.assertEqual(self.execCmdDirect(startparams,
|
||||
'get', 'test-jail1', 'banned', '192.0.2.9')[1], 0)
|
||||
self.assertEqual(self.execCmdDirect(startparams,
|
||||
'get', 'test-jail1', 'banned', '192.0.2.3', '192.0.2.9')[1], [1, 0])
|
||||
|
||||
# rotate logs:
|
||||
_write_file(test1log, "w+")
|
||||
|
|
|
@ -390,7 +390,15 @@ class TestsUtilsTest(LogCaptureTestCase):
|
|||
self.assertSortedEqual(['Z', {'A': ['B', 'C'], 'B': ['E', 'F']}], [{'B': ['F', 'E'], 'A': ['C', 'B']}, 'Z'],
|
||||
level=-1)
|
||||
self.assertRaises(AssertionError, lambda: self.assertSortedEqual(
|
||||
['Z', {'A': ['B', 'C'], 'B': ['E', 'F']}], [{'B': ['F', 'E'], 'A': ['C', 'B']}, 'Z']))
|
||||
['Z', {'A': ['B', 'C'], 'B': ['E', 'F']}], [{'B': ['F', 'E'], 'A': ['C', 'B']}, 'Z'],
|
||||
nestedOnly=True))
|
||||
self.assertSortedEqual(
|
||||
(0, [['A1'], ['A2', 'A1'], []]),
|
||||
(0, [['A1'], ['A1', 'A2'], []]),
|
||||
)
|
||||
self.assertSortedEqual(list('ABC'), list('CBA'))
|
||||
self.assertRaises(AssertionError, self.assertSortedEqual, ['ABC'], ['CBA'])
|
||||
self.assertRaises(AssertionError, self.assertSortedEqual, [['ABC']], [['CBA']])
|
||||
self._testAssertionErrorRE(r"\['A'\] != \['C', 'B'\]",
|
||||
self.assertSortedEqual, ['A'], ['C', 'B'])
|
||||
self._testAssertionErrorRE(r"\['A', 'B'\] != \['B', 'C'\]",
|
||||
|
|
|
@ -556,7 +556,7 @@ if not hasattr(unittest.TestCase, 'assertDictEqual'):
|
|||
self.fail(msg)
|
||||
unittest.TestCase.assertDictEqual = assertDictEqual
|
||||
|
||||
def assertSortedEqual(self, a, b, level=1, nestedOnly=True, key=repr, msg=None):
|
||||
def assertSortedEqual(self, a, b, level=1, nestedOnly=False, key=repr, msg=None):
|
||||
"""Compare complex elements (like dict, list or tuple) in sorted order until
|
||||
level 0 not reached (initial level = -1 meant all levels),
|
||||
or if nestedOnly set to True and some of the objects still contains nested lists or dicts.
|
||||
|
@ -566,6 +566,13 @@ def assertSortedEqual(self, a, b, level=1, nestedOnly=True, key=repr, msg=None):
|
|||
if isinstance(v, dict):
|
||||
return any(isinstance(v, (dict, list, tuple)) for v in v.itervalues())
|
||||
return any(isinstance(v, (dict, list, tuple)) for v in v)
|
||||
if nestedOnly:
|
||||
_nest_sorted = sorted
|
||||
else:
|
||||
def _nest_sorted(v, key=key):
|
||||
if isinstance(v, (set, list, tuple)):
|
||||
return sorted(list(_nest_sorted(v, key) for v in v), key=key)
|
||||
return v
|
||||
# level comparison routine:
|
||||
def _assertSortedEqual(a, b, level, nestedOnly, key):
|
||||
# first the lengths:
|
||||
|
@ -584,8 +591,8 @@ def assertSortedEqual(self, a, b, level=1, nestedOnly=True, key=repr, msg=None):
|
|||
elif v1 != v2:
|
||||
raise ValueError('%r != %r' % (a, b))
|
||||
else: # list, tuple, something iterable:
|
||||
a = sorted(a, key=key)
|
||||
b = sorted(b, key=key)
|
||||
a = _nest_sorted(a, key=key)
|
||||
b = _nest_sorted(b, key=key)
|
||||
for v1, v2 in zip(a, b):
|
||||
if isinstance(v1, (dict, list, tuple)) and isinstance(v2, (dict, list, tuple)):
|
||||
_assertSortedEqual(v1, v2, level-1 if level != 0 else 0, nestedOnly, key)
|
||||
|
|
|
@ -111,6 +111,14 @@ jails and database)
|
|||
unbans <IP> (in all jails and
|
||||
database)
|
||||
.TP
|
||||
\fBbanned\fR
|
||||
return jails with banned IPs as
|
||||
dictionary
|
||||
.TP
|
||||
\fBbanned <IP> ... <IP>]\fR
|
||||
return list(s) of jails where
|
||||
given IP(s) are banned
|
||||
.TP
|
||||
\fBstatus\fR
|
||||
gets the current status of the
|
||||
server
|
||||
|
@ -356,6 +364,14 @@ for <JAIL>
|
|||
.IP
|
||||
JAIL INFORMATION
|
||||
.TP
|
||||
\fBget <JAIL> banned\fR
|
||||
return banned IPs of <JAIL>
|
||||
.TP
|
||||
\fBget <JAIL> banned <IP> ... <IP>]\fR
|
||||
return 1 if IP is banned in <JAIL>
|
||||
otherwise 0, or a list of 1/0 for
|
||||
multiple IPs
|
||||
.TP
|
||||
\fBget <JAIL> logpath\fR
|
||||
gets the list of the monitored
|
||||
files for <JAIL>
|
||||
|
|
Loading…
Reference in New Issue