Merge pull request #1732 from sebres/0.10-ignoreself

0.10 `ignoreself` for ignore own IP addresses
pull/1733/head
Serg G. Brester 2017-03-24 10:12:23 +01:00 committed by GitHub
commit b650503f00
13 changed files with 110 additions and 7 deletions

View File

@ -68,6 +68,10 @@ TODO: implementing of options resp. other tasks from PR #1346
* Samples test case factory extended with filter options - dict in JSON to control * Samples test case factory extended with filter options - dict in JSON to control
filter options (e. g. mode, etc.): filter options (e. g. mode, etc.):
# filterOptions: {"mode": "aggressive"} # filterOptions: {"mode": "aggressive"}
* Introduced new jail option "ignoreself", specifies whether the local resp. own IP addresses
should be ignored (default is true). Fail2ban will not ban a host which matches such addresses.
Option "ignoreip" affects additionally to "ignoreself" and don't need to include the DNS
resp. IPs of the host self.
ver. 0.10.0-alpha-1 (2016/07/14) - ipv6-support-etc ver. 0.10.0-alpha-1 (2016/07/14) - ipv6-support-etc

View File

@ -44,10 +44,14 @@ before = paths-debian.conf
# MISCELLANEOUS OPTIONS # MISCELLANEOUS OPTIONS
# #
# "ignoreip" can be an IP address, a CIDR mask or a DNS host. Fail2ban will not # "ignorself" specifies whether the local resp. own IP addresses should be ignored
# ban a host which matches an address in this list. Several addresses can be # (default is true). Fail2ban will not ban a host which matches such addresses.
# defined using space (and/or comma) separator. #ignorself = true
ignoreip = 127.0.0.1/8 ::1
# "ignoreip" can be a list of IP addresses, CIDR masks or DNS hosts. Fail2ban
# will not ban a host which matches an address in this list. Several addresses
# can be defined using space (and/or comma) separator.
#ignoreip = 127.0.0.1/8 ::1
# External command that will take an tagged arguments to ignore, e.g. <ip>, # External command that will take an tagged arguments to ignore, e.g. <ip>,
# and return true if the IP is to be ignored. False otherwise. # and return true if the IP is to be ignored. False otherwise.

View File

@ -110,6 +110,7 @@ class JailReader(ConfigReader):
["string", "failregex", None], ["string", "failregex", None],
["string", "ignoreregex", None], ["string", "ignoreregex", None],
["string", "ignorecommand", None], ["string", "ignorecommand", None],
["bool", "ignoreself", None],
["string", "ignoreip", None], ["string", "ignoreip", None],
["string", "filter", ""], ["string", "filter", ""],
["string", "datepattern", None], ["string", "datepattern", None],

View File

@ -81,6 +81,7 @@ protocol = [
["status <JAIL> [FLAVOR]", "gets the current status of <JAIL>, with optional flavor or extended info"], ["status <JAIL> [FLAVOR]", "gets the current status of <JAIL>, with optional flavor or extended info"],
['', "JAIL CONFIGURATION", ""], ['', "JAIL CONFIGURATION", ""],
["set <JAIL> idle on|off", "sets the idle state of <JAIL>"], ["set <JAIL> idle on|off", "sets the idle state of <JAIL>"],
["set <JAIL> ignoreself true|false", "allows the ignoring of own IP addresses"],
["set <JAIL> addignoreip <IP>", "adds <IP> to the ignore list of <JAIL>"], ["set <JAIL> addignoreip <IP>", "adds <IP> to the ignore list of <JAIL>"],
["set <JAIL> delignoreip <IP>", "removes <IP> from the ignore list of <JAIL>"], ["set <JAIL> delignoreip <IP>", "removes <IP> from the ignore list of <JAIL>"],
["set <JAIL> addlogpath <FILE> ['tail']", "adds <FILE> to the monitoring list of <JAIL>, optionally starting at the 'tail' of the file (default 'head')."], ["set <JAIL> addlogpath <FILE> ['tail']", "adds <FILE> to the monitoring list of <JAIL>, optionally starting at the 'tail' of the file (default 'head')."],
@ -117,6 +118,7 @@ protocol = [
["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>"],
["get <JAIL> ignoreself", "gets the current value of the ignoring the own IP addresses"],
["get <JAIL> ignoreip", "gets the list of ignored IP addresses for <JAIL>"], ["get <JAIL> ignoreip", "gets the list of ignored IP addresses for <JAIL>"],
["get <JAIL> ignorecommand", "gets ignorecommand of <JAIL>"], ["get <JAIL> ignorecommand", "gets ignorecommand of <JAIL>"],
["get <JAIL> failregex", "gets the list of regular expressions which matches the failures for <JAIL>"], ["get <JAIL> failregex", "gets the list of regular expressions which matches the failures for <JAIL>"],

View File

@ -76,6 +76,8 @@ class Filter(JailThread):
self.setUseDns(useDns) self.setUseDns(useDns)
## The amount of time to look back. ## The amount of time to look back.
self.__findTime = 600 self.__findTime = 600
## Ignore own IPs flag:
self.__ignoreSelf = True
## The ignore IP list. ## The ignore IP list.
self.__ignoreIpList = [] self.__ignoreIpList = []
## Size of line buffer ## Size of line buffer
@ -413,6 +415,17 @@ class Filter(JailThread):
return ip return ip
##
# Ignore own IP/DNS.
#
@property
def ignoreSelf(self):
return self.__ignoreSelf
@ignoreSelf.setter
def ignoreSelf(self, value):
self.__ignoreSelf = value
## ##
# Add an IP/DNS to the ignore list. # Add an IP/DNS to the ignore list.
# #
@ -458,6 +471,11 @@ class Filter(JailThread):
def inIgnoreIPList(self, ip, log_ignore=False): def inIgnoreIPList(self, ip, log_ignore=False):
if not isinstance(ip, IPAddr): if not isinstance(ip, IPAddr):
ip = IPAddr(ip) ip = IPAddr(ip)
# check own IPs should be ignored and 'ip' is self IP:
if self.__ignoreSelf and ip in DNSUtils.getSelfIPs():
return True
for net in self.__ignoreIpList: for net in self.__ignoreIpList:
# check if the IP is covered by ignore IP # check if the IP is covered by ignore IP
if ip.isInNet(net): if ip.isInNet(net):

View File

@ -118,6 +118,42 @@ class DNSUtils:
return ipList return ipList
@staticmethod
def getSelfNames():
"""Get own host names of self"""
# try find cached own hostnames (this tuple-key cannot be used elsewhere):
key = ('self','dns')
names = DNSUtils.CACHE_ipToName.get(key)
# get it using different ways (a set with names of localhost, hostname, fully qualified):
if names is None:
names = set(['localhost'])
for hostname in (socket.gethostname, socket.getfqdn):
try:
names |= set([hostname()])
except Exception as e: # pragma: no cover
logSys.warning("Retrieving own hostnames failed: %s", e)
# cache and return :
DNSUtils.CACHE_ipToName.set(key, names)
return names
@staticmethod
def getSelfIPs():
"""Get own IP addresses of self"""
# try find cached own IPs (this tuple-key cannot be used elsewhere):
key = ('self','ips')
ips = DNSUtils.CACHE_nameToIp.get(key)
# get it using different ways (a set with IPs of localhost, hostname, fully qualified):
if ips is None:
ips = set()
for hostname in DNSUtils.getSelfNames():
try:
ips |= set(DNSUtils.textToIp(hostname, 'yes'))
except Exception as e: # pragma: no cover
logSys.warning("Retrieving own IPs of %s failed: %s", hostname, e)
# cache and return :
DNSUtils.CACHE_nameToIp.set(key, ips)
return ips
## ##
# Class for IP address handling. # Class for IP address handling.

View File

@ -308,6 +308,12 @@ class Server:
return self.__jails[name].idle return self.__jails[name].idle
# Filter # Filter
def setIgnoreSelf(self, name, value):
self.__jails[name].filter.ignoreSelf = value
def getIgnoreSelf(self, name):
return self.__jails[name].filter.ignoreSelf
def addIgnoreIP(self, name, ip): def addIgnoreIP(self, name, ip):
self.__jails[name].filter.addIgnoreIP(ip) self.__jails[name].filter.addIgnoreIP(ip)

View File

@ -181,6 +181,10 @@ class Transmitter:
raise Exception("Invalid idle option, must be 'on' or 'off'") raise Exception("Invalid idle option, must be 'on' or 'off'")
return self.__server.getIdleJail(name) return self.__server.getIdleJail(name)
# Filter # Filter
elif command[1] == "ignoreself":
value = command[2]
self.__server.setIgnoreSelf(name, value)
return self.__server.getIgnoreSelf(name)
elif command[1] == "addignoreip": elif command[1] == "addignoreip":
value = command[2] value = command[2]
self.__server.addIgnoreIP(name, value) self.__server.addIgnoreIP(name, value)
@ -341,6 +345,8 @@ class Transmitter:
return self.__server.getLogEncoding(name) return self.__server.getLogEncoding(name)
elif command[1] == "journalmatch": # pragma: systemd no cover elif command[1] == "journalmatch": # pragma: systemd no cover
return self.__server.getJournalMatch(name) return self.__server.getJournalMatch(name)
elif command[1] == "ignoreself":
return self.__server.getIgnoreSelf(name)
elif command[1] == "ignoreip": elif command[1] == "ignoreip":
return self.__server.getIgnoreIP(name) return self.__server.getIgnoreIP(name)
elif command[1] == "ignorecommand": elif command[1] == "ignorecommand":

View File

@ -211,6 +211,7 @@ class Utils():
if retcode is None or tout_kill_tree: # Still going... if retcode is None or tout_kill_tree: # Still going...
os.killpg(pgid, signal.SIGKILL) # Kill the process os.killpg(pgid, signal.SIGKILL) # Kill the process
time.sleep(Utils.DEFAULT_SLEEP_INTERVAL) time.sleep(Utils.DEFAULT_SLEEP_INTERVAL)
if retcode is None: # pragma: no cover - too sporadic
retcode = popen.poll() retcode = popen.poll()
#logSys.debug("%s -- killed %s ", realCmd, retcode) #logSys.debug("%s -- killed %s ", realCmd, retcode)
if retcode is None and not Utils.pid_exists(pgid): # pragma: no cover if retcode is None and not Utils.pid_exists(pgid): # pragma: no cover

View File

@ -780,6 +780,7 @@ class Fail2banServerTest(Fail2banClientServerBase):
"findtime = 10m", "findtime = 10m",
"failregex = ^\s*failure <F-ERRCODE>401|403</F-ERRCODE> from <HOST>", "failregex = ^\s*failure <F-ERRCODE>401|403</F-ERRCODE> from <HOST>",
"datepattern = {^LN-BEG}EPOCH", "datepattern = {^LN-BEG}EPOCH",
"ignoreip = 127.0.0.1/8 ::1", # just to cover ignoreip in jailreader/transmitter
"", "",
"[test-jail1]", "backend = " + backend, "filter =", "[test-jail1]", "backend = " + backend, "filter =",
"action = ", "action = ",

View File

@ -325,6 +325,17 @@ class IgnoreIP(LogCaptureTestCase):
LogCaptureTestCase.setUp(self) LogCaptureTestCase.setUp(self)
self.jail = DummyJail() self.jail = DummyJail()
self.filter = FileFilter(self.jail) self.filter = FileFilter(self.jail)
self.filter.ignoreSelf = False
def testIgnoreSelfIP(self):
ipList = ("127.0.0.1",)
# test ignoreSelf is false:
for ip in ipList:
self.assertFalse(self.filter.inIgnoreIPList(ip))
# test ignoreSelf with true:
self.filter.ignoreSelf = True
for ip in ipList:
self.assertTrue(self.filter.inIgnoreIPList(ip))
def testIgnoreIPOK(self): def testIgnoreIPOK(self):
ipList = "127.0.0.1", "192.168.0.1", "255.255.255.255", "99.99.99.99" ipList = "127.0.0.1", "192.168.0.1", "255.255.255.255", "99.99.99.99"

View File

@ -449,6 +449,16 @@ class Transmitter(TransmitterBase):
self.transm.proceed(["set", self.jailName, "delignoreip", value]), self.transm.proceed(["set", self.jailName, "delignoreip", value]),
(0, [value])) (0, [value]))
self.assertEqual(
self.transm.proceed(["get", self.jailName, "ignoreself"]),
(0, True))
self.assertEqual(
self.transm.proceed(["set", self.jailName, "ignoreself", False]),
(0, False))
self.assertEqual(
self.transm.proceed(["get", self.jailName, "ignoreself"]),
(0, False))
def testJailIgnoreCommand(self): def testJailIgnoreCommand(self):
self.setGetTest("ignorecommand", "bin ", jail=self.jailName) self.setGetTest("ignorecommand", "bin ", jail=self.jailName)

View File

@ -199,11 +199,14 @@ Arguments can be passed to actions to override the default values from the [Init
Values can also be quoted (required when value includes a ","). More that one action can be specified (in separate lines). Values can also be quoted (required when value includes a ","). More that one action can be specified (in separate lines).
.RE .RE
.TP .TP
.B ignoreself
boolean value (default true) indicates the banning of own IP addresses should be prevented
.TP
.B ignoreip .B ignoreip
list of IPs not to ban. They can include a CIDR mask too. list of IPs not to ban. They can include a DNS resp. CIDR mask too. The option affects additionally to \fBignoreself\fR (if true) and don't need to contain own DNS resp. IPs of the running host.
.TP .TP
.B ignorecommand .B ignorecommand
command that is executed to determine if the current candidate IP for banning should not be banned. command that is executed to determine if the current candidate IP for banning (or failure-ID for raw IDs) should not be banned. The option affects additionally to \fBignoreself\fR and \fBignoreip\fR and will be first executed if both don't hit.
.br .br
IP will not be banned if command returns successfully (exit code 0). IP will not be banned if command returns successfully (exit code 0).
Like ACTION FILES, tags like <ip> are can be included in the ignorecommand value and will be substituted before execution. Currently only <ip> is supported however more will be added later. Like ACTION FILES, tags like <ip> are can be included in the ignorecommand value and will be substituted before execution. Currently only <ip> is supported however more will be added later.