From 5e93bf9bd3ec66707cb961c851a0ce448be3a02b Mon Sep 17 00:00:00 2001 From: sebres Date: Thu, 23 Mar 2017 15:52:31 +0100 Subject: [PATCH] Introduced new 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. --- config/jail.conf | 12 +++++++---- fail2ban/client/jailreader.py | 1 + fail2ban/protocol.py | 2 ++ fail2ban/server/filter.py | 18 ++++++++++++++++ fail2ban/server/ipdns.py | 36 ++++++++++++++++++++++++++++++++ fail2ban/server/server.py | 6 ++++++ fail2ban/server/transmitter.py | 6 ++++++ fail2ban/tests/filtertestcase.py | 11 ++++++++++ fail2ban/tests/servertestcase.py | 10 +++++++++ 9 files changed, 98 insertions(+), 4 deletions(-) diff --git a/config/jail.conf b/config/jail.conf index c5440b71..7e5cc9b7 100644 --- a/config/jail.conf +++ b/config/jail.conf @@ -44,10 +44,14 @@ before = paths-debian.conf # MISCELLANEOUS OPTIONS # -# "ignoreip" can be an IP address, a CIDR mask or a DNS host. 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 +# "ignorself" specifies whether the local resp. own IP addresses should be ignored +# (default is true). Fail2ban will not ban a host which matches such addresses. +#ignorself = true + +# "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. , # and return true if the IP is to be ignored. False otherwise. diff --git a/fail2ban/client/jailreader.py b/fail2ban/client/jailreader.py index 7f69155f..ca092990 100644 --- a/fail2ban/client/jailreader.py +++ b/fail2ban/client/jailreader.py @@ -110,6 +110,7 @@ class JailReader(ConfigReader): ["string", "failregex", None], ["string", "ignoreregex", None], ["string", "ignorecommand", None], + ["bool", "ignoreself", None], ["string", "ignoreip", None], ["string", "filter", ""], ["string", "datepattern", None], diff --git a/fail2ban/protocol.py b/fail2ban/protocol.py index d1c33d88..3625ec01 100644 --- a/fail2ban/protocol.py +++ b/fail2ban/protocol.py @@ -81,6 +81,7 @@ protocol = [ ["status [FLAVOR]", "gets the current status of , with optional flavor or extended info"], ['', "JAIL CONFIGURATION", ""], ["set idle on|off", "sets the idle state of "], +["set ignoreself true|false", "allows the ignoring of own IP addresses"], ["set addignoreip ", "adds to the ignore list of "], ["set delignoreip ", "removes from the ignore list of "], ["set addlogpath ['tail']", "adds to the monitoring list of , optionally starting at the 'tail' of the file (default 'head')."], @@ -117,6 +118,7 @@ protocol = [ ["get logpath", "gets the list of the monitored files for "], ["get logencoding", "gets the encoding of the log files for "], ["get journalmatch", "gets the journal filter match for "], +["get ignoreself", "gets the current value of the ignoring the own IP addresses"], ["get ignoreip", "gets the list of ignored IP addresses for "], ["get ignorecommand", "gets ignorecommand of "], ["get failregex", "gets the list of regular expressions which matches the failures for "], diff --git a/fail2ban/server/filter.py b/fail2ban/server/filter.py index 72bf47d8..b425060a 100644 --- a/fail2ban/server/filter.py +++ b/fail2ban/server/filter.py @@ -76,6 +76,8 @@ class Filter(JailThread): self.setUseDns(useDns) ## The amount of time to look back. self.__findTime = 600 + ## Ignore own IPs flag: + self.__ignoreSelf = True ## The ignore IP list. self.__ignoreIpList = [] ## Size of line buffer @@ -413,6 +415,17 @@ class Filter(JailThread): 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. # @@ -458,6 +471,11 @@ class Filter(JailThread): def inIgnoreIPList(self, ip, log_ignore=False): if not isinstance(ip, IPAddr): 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: # check if the IP is covered by ignore IP if ip.isInNet(net): diff --git a/fail2ban/server/ipdns.py b/fail2ban/server/ipdns.py index bd3b812d..bda32ae8 100644 --- a/fail2ban/server/ipdns.py +++ b/fail2ban/server/ipdns.py @@ -118,6 +118,42 @@ class DNSUtils: 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. diff --git a/fail2ban/server/server.py b/fail2ban/server/server.py index dfab1e38..facbe393 100644 --- a/fail2ban/server/server.py +++ b/fail2ban/server/server.py @@ -308,6 +308,12 @@ class Server: return self.__jails[name].idle # 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): self.__jails[name].filter.addIgnoreIP(ip) diff --git a/fail2ban/server/transmitter.py b/fail2ban/server/transmitter.py index ad21b851..bc9edd43 100644 --- a/fail2ban/server/transmitter.py +++ b/fail2ban/server/transmitter.py @@ -181,6 +181,10 @@ class Transmitter: raise Exception("Invalid idle option, must be 'on' or 'off'") return self.__server.getIdleJail(name) # Filter + elif command[1] == "ignoreself": + value = command[2] + self.__server.setIgnoreSelf(name, value) + return self.__server.getIgnoreSelf(name) elif command[1] == "addignoreip": value = command[2] self.__server.addIgnoreIP(name, value) @@ -341,6 +345,8 @@ class Transmitter: return self.__server.getLogEncoding(name) elif command[1] == "journalmatch": # pragma: systemd no cover return self.__server.getJournalMatch(name) + elif command[1] == "ignoreself": + return self.__server.getIgnoreSelf(name) elif command[1] == "ignoreip": return self.__server.getIgnoreIP(name) elif command[1] == "ignorecommand": diff --git a/fail2ban/tests/filtertestcase.py b/fail2ban/tests/filtertestcase.py index d3217555..10310a5d 100644 --- a/fail2ban/tests/filtertestcase.py +++ b/fail2ban/tests/filtertestcase.py @@ -325,6 +325,17 @@ class IgnoreIP(LogCaptureTestCase): LogCaptureTestCase.setUp(self) self.jail = DummyJail() 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): ipList = "127.0.0.1", "192.168.0.1", "255.255.255.255", "99.99.99.99" diff --git a/fail2ban/tests/servertestcase.py b/fail2ban/tests/servertestcase.py index 8d1cfa62..51ff8880 100644 --- a/fail2ban/tests/servertestcase.py +++ b/fail2ban/tests/servertestcase.py @@ -449,6 +449,16 @@ class Transmitter(TransmitterBase): self.transm.proceed(["set", self.jailName, "delignoreip", 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): self.setGetTest("ignorecommand", "bin ", jail=self.jailName)