mirror of https://github.com/fail2ban/fail2ban
extends protocol/client with banned status (retrieve information whether an IP is banned and/or in which jails), implements FR gh-2725
parent
0ae2ef68be
commit
54b2208690
|
@ -55,6 +55,8 @@ protocol = [
|
||||||
["stop", "stops all jails and terminate the server"],
|
["stop", "stops all jails and terminate the server"],
|
||||||
["unban --all", "unbans all IP addresses (in all jails and database)"],
|
["unban --all", "unbans all IP addresses (in all jails and database)"],
|
||||||
["unban <IP> ... <IP>", "unbans <IP> (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"],
|
["status", "gets the current status of the server"],
|
||||||
["ping", "tests if the server is alive"],
|
["ping", "tests if the server is alive"],
|
||||||
["echo", "for internal usage, returns back and outputs a given string"],
|
["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> <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>"],
|
["set <JAIL> action <ACT> <METHOD>[ <JSONKWARGS>]", "calls the <METHOD> with <JSONKWARGS> for the action <ACT> for <JAIL>"],
|
||||||
['', "JAIL INFORMATION", ""],
|
['', "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> logpath", "gets the list of the monitored files for <JAIL>"],
|
||||||
["get <JAIL> logencoding", "gets the encoding of the log 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>"],
|
["get <JAIL> journalmatch", "gets the journal filter match for <JAIL>"],
|
||||||
|
|
|
@ -210,6 +210,14 @@ class Actions(JailThread, Mapping):
|
||||||
def getBanTime(self):
|
def getBanTime(self):
|
||||||
return self.__banManager.getBanTime()
|
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):
|
def addBannedIP(self, ip):
|
||||||
"""Ban an IP or list of IPs."""
|
"""Ban an IP or list of IPs."""
|
||||||
unixTime = MyTime.time()
|
unixTime = MyTime.time()
|
||||||
|
|
|
@ -521,6 +521,32 @@ class Server:
|
||||||
cnt += jail.actions.removeBannedIP(value, ifexists=ifexists)
|
cnt += jail.actions.removeBannedIP(value, ifexists=ifexists)
|
||||||
return cnt
|
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):
|
def getBanTime(self, name):
|
||||||
return self.__jails[name].actions.getBanTime()
|
return self.__jails[name].actions.getBanTime()
|
||||||
|
|
||||||
|
|
|
@ -118,6 +118,9 @@ class Transmitter:
|
||||||
if len(value) == 1 and value[0] == "--all":
|
if len(value) == 1 and value[0] == "--all":
|
||||||
return self.__server.setUnbanIP()
|
return self.__server.setUnbanIP()
|
||||||
return self.__server.setUnbanIP(None, value)
|
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":
|
elif name == "echo":
|
||||||
return command[1:]
|
return command[1:]
|
||||||
elif name == "server-status":
|
elif name == "server-status":
|
||||||
|
@ -424,7 +427,10 @@ class Transmitter:
|
||||||
return None
|
return None
|
||||||
else:
|
else:
|
||||||
return db.purgeage
|
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":
|
elif command[1] == "logpath":
|
||||||
return self.__server.getLogPath(name)
|
return self.__server.getLogPath(name)
|
||||||
elif command[1] == "logencoding":
|
elif command[1] == "logencoding":
|
||||||
|
|
|
@ -37,7 +37,7 @@ from threading import Thread
|
||||||
|
|
||||||
from ..client import fail2banclient, fail2banserver, fail2bancmdline
|
from ..client import fail2banclient, fail2banserver, fail2bancmdline
|
||||||
from ..client.fail2bancmdline import 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 ..client.fail2banserver import Fail2banServer, exec_command_line as _exec_server
|
||||||
from .. import protocol
|
from .. import protocol
|
||||||
from ..server import server
|
from ..server import server
|
||||||
|
@ -421,6 +421,14 @@ class Fail2banClientServerBase(LogCaptureTestCase):
|
||||||
self.assertRaises(exitType, self.exec_command_line[0],
|
self.assertRaises(exitType, self.exec_command_line[0],
|
||||||
(self.exec_command_line[1:] + startparams + args))
|
(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
|
# Common tests
|
||||||
#
|
#
|
||||||
|
@ -1007,6 +1015,30 @@ class Fail2banServerTest(Fail2banClientServerBase):
|
||||||
"[test-jail2] Found 192.0.2.3",
|
"[test-jail2] Found 192.0.2.3",
|
||||||
"[test-jail2] Ban 192.0.2.3",
|
"[test-jail2] Ban 192.0.2.3",
|
||||||
all=True)
|
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:
|
# rotate logs:
|
||||||
_write_file(test1log, "w+")
|
_write_file(test1log, "w+")
|
||||||
|
|
|
@ -111,6 +111,14 @@ jails and database)
|
||||||
unbans <IP> (in all jails and
|
unbans <IP> (in all jails and
|
||||||
database)
|
database)
|
||||||
.TP
|
.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
|
\fBstatus\fR
|
||||||
gets the current status of the
|
gets the current status of the
|
||||||
server
|
server
|
||||||
|
@ -356,6 +364,14 @@ for <JAIL>
|
||||||
.IP
|
.IP
|
||||||
JAIL INFORMATION
|
JAIL INFORMATION
|
||||||
.TP
|
.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
|
\fBget <JAIL> logpath\fR
|
||||||
gets the list of the monitored
|
gets the list of the monitored
|
||||||
files for <JAIL>
|
files for <JAIL>
|
||||||
|
|
Loading…
Reference in New Issue