mirror of https://github.com/fail2ban/fail2ban
Merge pull request #1732 from sebres/0.10-ignoreself
0.10 `ignoreself` for ignore own IP addressespull/1733/head
commit
b650503f00
|
@ -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
|
||||
filter options (e. g. mode, etc.):
|
||||
# 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
|
||||
|
|
|
@ -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. <ip>,
|
||||
# and return true if the IP is to be ignored. False otherwise.
|
||||
|
|
|
@ -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],
|
||||
|
|
|
@ -81,6 +81,7 @@ protocol = [
|
|||
["status <JAIL> [FLAVOR]", "gets the current status of <JAIL>, with optional flavor or extended info"],
|
||||
['', "JAIL CONFIGURATION", ""],
|
||||
["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> 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')."],
|
||||
|
@ -117,6 +118,7 @@ protocol = [
|
|||
["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>"],
|
||||
["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> ignorecommand", "gets ignorecommand of <JAIL>"],
|
||||
["get <JAIL> failregex", "gets the list of regular expressions which matches the failures for <JAIL>"],
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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":
|
||||
|
|
|
@ -211,7 +211,8 @@ class Utils():
|
|||
if retcode is None or tout_kill_tree: # Still going...
|
||||
os.killpg(pgid, signal.SIGKILL) # Kill the process
|
||||
time.sleep(Utils.DEFAULT_SLEEP_INTERVAL)
|
||||
retcode = popen.poll()
|
||||
if retcode is None: # pragma: no cover - too sporadic
|
||||
retcode = popen.poll()
|
||||
#logSys.debug("%s -- killed %s ", realCmd, retcode)
|
||||
if retcode is None and not Utils.pid_exists(pgid): # pragma: no cover
|
||||
retcode = signal.SIGKILL
|
||||
|
|
|
@ -780,6 +780,7 @@ class Fail2banServerTest(Fail2banClientServerBase):
|
|||
"findtime = 10m",
|
||||
"failregex = ^\s*failure <F-ERRCODE>401|403</F-ERRCODE> from <HOST>",
|
||||
"datepattern = {^LN-BEG}EPOCH",
|
||||
"ignoreip = 127.0.0.1/8 ::1", # just to cover ignoreip in jailreader/transmitter
|
||||
"",
|
||||
"[test-jail1]", "backend = " + backend, "filter =",
|
||||
"action = ",
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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).
|
||||
.RE
|
||||
.TP
|
||||
.B ignoreself
|
||||
boolean value (default true) indicates the banning of own IP addresses should be prevented
|
||||
.TP
|
||||
.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
|
||||
.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
|
||||
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.
|
||||
|
|
Loading…
Reference in New Issue