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
|
* 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
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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],
|
||||||
|
|
|
@ -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>"],
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -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":
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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 = ",
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -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.
|
||||||
|
|
Loading…
Reference in New Issue