mirror of https://github.com/fail2ban/fail2ban
BF: usedns=no was not working at all
it was not adding any detected address, IP or not to the list of failed attempts This commit also adds appropriate unittestpull/43/merge
parent
971406f722
commit
3989d24967
|
@ -54,7 +54,7 @@ class Filter(JailThread):
|
||||||
# Initialize the filter object with default values.
|
# Initialize the filter object with default values.
|
||||||
# @param jail the jail object
|
# @param jail the jail object
|
||||||
|
|
||||||
def __init__(self, jail):
|
def __init__(self, jail, useDns='warn'):
|
||||||
JailThread.__init__(self)
|
JailThread.__init__(self)
|
||||||
## The jail which contains this filter.
|
## The jail which contains this filter.
|
||||||
self.jail = jail
|
self.jail = jail
|
||||||
|
@ -65,7 +65,7 @@ class Filter(JailThread):
|
||||||
## The regular expression list with expressions to ignore.
|
## The regular expression list with expressions to ignore.
|
||||||
self.__ignoreRegex = list()
|
self.__ignoreRegex = list()
|
||||||
## Use DNS setting
|
## Use DNS setting
|
||||||
self.__useDns = "warn"
|
self.setUseDns(useDns)
|
||||||
## The amount of time to look back.
|
## The amount of time to look back.
|
||||||
self.__findTime = 6000
|
self.__findTime = 6000
|
||||||
## The ignore IP list.
|
## The ignore IP list.
|
||||||
|
@ -149,6 +149,13 @@ class Filter(JailThread):
|
||||||
# @param value the usedns mode
|
# @param value the usedns mode
|
||||||
|
|
||||||
def setUseDns(self, value):
|
def setUseDns(self, value):
|
||||||
|
if isinstance(value, bool):
|
||||||
|
value = {True: 'yes', False: 'no'}[value]
|
||||||
|
value = value.lower() # must be a string by now
|
||||||
|
if not (value in ('yes', 'no', 'warn')):
|
||||||
|
logSys.error("Incorrect value %r specified for usedns. "
|
||||||
|
"Using safe 'no'" % (value,))
|
||||||
|
value = 'no'
|
||||||
logSys.debug("Setting usedns = %s for %s" % (value, self))
|
logSys.debug("Setting usedns = %s for %s" % (value, self))
|
||||||
self.__useDns = value
|
self.__useDns = value
|
||||||
|
|
||||||
|
@ -373,8 +380,8 @@ class Filter(JailThread):
|
||||||
|
|
||||||
class FileFilter(Filter):
|
class FileFilter(Filter):
|
||||||
|
|
||||||
def __init__(self, jail):
|
def __init__(self, jail, **kwargs):
|
||||||
Filter.__init__(self, jail)
|
Filter.__init__(self, jail, **kwargs)
|
||||||
## The log file path.
|
## The log file path.
|
||||||
self.__logPath = []
|
self.__logPath = []
|
||||||
|
|
||||||
|
@ -589,25 +596,24 @@ class DNSUtils:
|
||||||
def textToIp(text, useDns):
|
def textToIp(text, useDns):
|
||||||
""" Return the IP of DNS found in a given text.
|
""" Return the IP of DNS found in a given text.
|
||||||
"""
|
"""
|
||||||
if useDns == "no":
|
ipList = list()
|
||||||
return None
|
# Search for plain IP
|
||||||
else:
|
plainIP = DNSUtils.searchIP(text)
|
||||||
ipList = list()
|
if not plainIP is None:
|
||||||
# Search for plain IP
|
plainIPStr = plainIP.group(0)
|
||||||
plainIP = DNSUtils.searchIP(text)
|
if DNSUtils.isValidIP(plainIPStr):
|
||||||
if not plainIP is None:
|
ipList.append(plainIPStr)
|
||||||
plainIPStr = plainIP.group(0)
|
|
||||||
if DNSUtils.isValidIP(plainIPStr):
|
# If we are allowed to resolve -- give it a try if nothing was found
|
||||||
ipList.append(plainIPStr)
|
if useDns in ("yes", "warn") and not ipList:
|
||||||
if not ipList:
|
# Try to get IP from possible DNS
|
||||||
# Try to get IP from possible DNS
|
ip = DNSUtils.dnsToIp(text)
|
||||||
ip = DNSUtils.dnsToIp(text)
|
ipList.extend(ip)
|
||||||
for e in ip:
|
if ip and useDns == "warn":
|
||||||
ipList.append(e)
|
logSys.warning("Determined IP using DNS Reverse Lookup: %s = %s",
|
||||||
if useDns == "warn":
|
text, ipList)
|
||||||
logSys.warning("Determined IP using DNS Reverse Lookup: %s = %s",
|
|
||||||
text, ipList)
|
return ipList
|
||||||
return ipList
|
|
||||||
textToIp = staticmethod(textToIp)
|
textToIp = staticmethod(textToIp)
|
||||||
|
|
||||||
#@staticmethod
|
#@staticmethod
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
Aug 14 11:54:59 i60p295 sshd[12365]: Failed publickey for roehl from example.com port 51332 ssh2
|
||||||
|
Aug 14 11:58:59 i60p295 sshd[12365]: Failed publickey for roehl from ::ffff:192.0.43.10 port 51332 ssh2
|
|
@ -84,14 +84,11 @@ class GetFailures(unittest.TestCase):
|
||||||
FILENAME_02 = "testcases/files/testcase02.log"
|
FILENAME_02 = "testcases/files/testcase02.log"
|
||||||
FILENAME_03 = "testcases/files/testcase03.log"
|
FILENAME_03 = "testcases/files/testcase03.log"
|
||||||
FILENAME_04 = "testcases/files/testcase04.log"
|
FILENAME_04 = "testcases/files/testcase04.log"
|
||||||
|
FILENAME_USEDNS = "testcases/files/testcase-usedns.log"
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
"""Call before every test case."""
|
"""Call before every test case."""
|
||||||
# TODO: RF tests so we could do parametric testing easily.
|
self.__filter = FileFilter(None)
|
||||||
# useDns='warn' and useDns='yes'
|
|
||||||
# both must be tested appropriately but ATM more
|
|
||||||
# critical is to assure correct behavior of 'no'
|
|
||||||
self.__filter = FileFilter(None, useDns='warn')
|
|
||||||
self.__filter.setActive(True)
|
self.__filter.setActive(True)
|
||||||
# TODO Test this
|
# TODO Test this
|
||||||
#self.__filter.setTimeRegex("\S{3}\s{1,2}\d{1,2} \d{2}:\d{2}:\d{2}")
|
#self.__filter.setTimeRegex("\S{3}\s{1,2}\d{1,2} \d{2}:\d{2}:\d{2}")
|
||||||
|
@ -111,14 +108,14 @@ class GetFailures(unittest.TestCase):
|
||||||
time.localtime(output[2])
|
time.localtime(output[2])
|
||||||
self.assertEqual(found_time, output_time)
|
self.assertEqual(found_time, output_time)
|
||||||
if len(output) > 3: # match matches
|
if len(output) > 3: # match matches
|
||||||
self.assertEqual(found[3], output[3])
|
self.assertEqual(repr(found[3]), repr(output[3]))
|
||||||
|
|
||||||
def _assertCorrectLastAtempt(self, output):
|
def _assertCorrectLastAtempt(self, filter_, output):
|
||||||
"""Additional helper to wrap most common test case
|
"""Additional helper to wrap most common test case
|
||||||
|
|
||||||
Test current filter to contain target ticket
|
Test filter to contain target ticket
|
||||||
"""
|
"""
|
||||||
ticket = self.__filter.failManager.toBan()
|
ticket = filter_.failManager.toBan()
|
||||||
|
|
||||||
attempts = ticket.getAttempt()
|
attempts = ticket.getAttempt()
|
||||||
date = ticket.getTime()
|
date = ticket.getTime()
|
||||||
|
@ -136,7 +133,7 @@ class GetFailures(unittest.TestCase):
|
||||||
self.__filter.addLogPath(GetFailures.FILENAME_01)
|
self.__filter.addLogPath(GetFailures.FILENAME_01)
|
||||||
self.__filter.addFailRegex("(?:(?:Authentication failure|Failed [-/\w+]+) for(?: [iI](?:llegal|nvalid) user)?|[Ii](?:llegal|nvalid) user|ROOT LOGIN REFUSED) .*(?: from|FROM) <HOST>")
|
self.__filter.addFailRegex("(?:(?:Authentication failure|Failed [-/\w+]+) for(?: [iI](?:llegal|nvalid) user)?|[Ii](?:llegal|nvalid) user|ROOT LOGIN REFUSED) .*(?: from|FROM) <HOST>")
|
||||||
self.__filter.getFailures(GetFailures.FILENAME_01)
|
self.__filter.getFailures(GetFailures.FILENAME_01)
|
||||||
self._assertCorrectLastAtempt(output)
|
self._assertCorrectLastAtempt(self.__filter, output)
|
||||||
|
|
||||||
|
|
||||||
def testGetFailures02(self):
|
def testGetFailures02(self):
|
||||||
|
@ -147,7 +144,7 @@ class GetFailures(unittest.TestCase):
|
||||||
self.__filter.addLogPath(GetFailures.FILENAME_02)
|
self.__filter.addLogPath(GetFailures.FILENAME_02)
|
||||||
self.__filter.addFailRegex("Failed .* from <HOST>")
|
self.__filter.addFailRegex("Failed .* from <HOST>")
|
||||||
self.__filter.getFailures(GetFailures.FILENAME_02)
|
self.__filter.getFailures(GetFailures.FILENAME_02)
|
||||||
self._assertCorrectLastAtempt(output)
|
self._assertCorrectLastAtempt(self.__filter, output)
|
||||||
|
|
||||||
def testGetFailures03(self):
|
def testGetFailures03(self):
|
||||||
output = ('203.162.223.135', 6, 1124013544.0)
|
output = ('203.162.223.135', 6, 1124013544.0)
|
||||||
|
@ -155,7 +152,7 @@ class GetFailures(unittest.TestCase):
|
||||||
self.__filter.addLogPath(GetFailures.FILENAME_03)
|
self.__filter.addLogPath(GetFailures.FILENAME_03)
|
||||||
self.__filter.addFailRegex("error,relay=<HOST>,.*550 User unknown")
|
self.__filter.addFailRegex("error,relay=<HOST>,.*550 User unknown")
|
||||||
self.__filter.getFailures(GetFailures.FILENAME_03)
|
self.__filter.getFailures(GetFailures.FILENAME_03)
|
||||||
self._assertCorrectLastAtempt(output)
|
self._assertCorrectLastAtempt(self.__filter, output)
|
||||||
|
|
||||||
def testGetFailures04(self):
|
def testGetFailures04(self):
|
||||||
output = [('212.41.96.186', 4, 1124013600.0),
|
output = [('212.41.96.186', 4, 1124013600.0),
|
||||||
|
@ -167,10 +164,37 @@ class GetFailures(unittest.TestCase):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
for i, out in enumerate(output):
|
for i, out in enumerate(output):
|
||||||
self._assertCorrectLastAtempt(out)
|
self._assertCorrectLastAtempt(self.__filter, out)
|
||||||
except FailManagerEmpty:
|
except FailManagerEmpty:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def testGetFailuresUseDNS(self):
|
||||||
|
# We should still catch failures with usedns = no ;-)
|
||||||
|
output_yes = ('192.0.43.10', 2, 1124013539.0,
|
||||||
|
['Aug 14 11:54:59 i60p295 sshd[12365]: Failed publickey for roehl from example.com port 51332 ssh2\n',
|
||||||
|
'Aug 14 11:58:59 i60p295 sshd[12365]: Failed publickey for roehl from ::ffff:192.0.43.10 port 51332 ssh2\n'])
|
||||||
|
|
||||||
|
output_no = ('192.0.43.10', 1, 1124013539.0,
|
||||||
|
['Aug 14 11:58:59 i60p295 sshd[12365]: Failed publickey for roehl from ::ffff:192.0.43.10 port 51332 ssh2\n'])
|
||||||
|
|
||||||
|
# Actually no exception would be raised -- it will be just set to 'no'
|
||||||
|
#self.assertRaises(ValueError,
|
||||||
|
# FileFilter, None, useDns='wrong_value_for_useDns')
|
||||||
|
|
||||||
|
for useDns, output in (('yes', output_yes),
|
||||||
|
('no', output_no),
|
||||||
|
('warn', output_yes)):
|
||||||
|
filter_ = FileFilter(None, useDns=useDns)
|
||||||
|
filter_.setActive(True)
|
||||||
|
filter_.failManager.setMaxRetry(1) # we might have just few failures
|
||||||
|
|
||||||
|
filter_.addLogPath(GetFailures.FILENAME_USEDNS)
|
||||||
|
filter_.addFailRegex("Failed .* from <HOST>")
|
||||||
|
filter_.getFailures(GetFailures.FILENAME_USEDNS)
|
||||||
|
self._assertCorrectLastAtempt(filter_, output)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def testGetFailuresMultiRegex(self):
|
def testGetFailuresMultiRegex(self):
|
||||||
output = ('141.3.81.106', 8, 1124013541.0)
|
output = ('141.3.81.106', 8, 1124013541.0)
|
||||||
|
|
||||||
|
@ -178,7 +202,7 @@ class GetFailures(unittest.TestCase):
|
||||||
self.__filter.addFailRegex("Failed .* from <HOST>")
|
self.__filter.addFailRegex("Failed .* from <HOST>")
|
||||||
self.__filter.addFailRegex("Accepted .* from <HOST>")
|
self.__filter.addFailRegex("Accepted .* from <HOST>")
|
||||||
self.__filter.getFailures(GetFailures.FILENAME_02)
|
self.__filter.getFailures(GetFailures.FILENAME_02)
|
||||||
self._assertCorrectLastAtempt(output)
|
self._assertCorrectLastAtempt(self.__filter, output)
|
||||||
|
|
||||||
def testGetFailuresIgnoreRegex(self):
|
def testGetFailuresIgnoreRegex(self):
|
||||||
output = ('141.3.81.106', 8, 1124013541.0)
|
output = ('141.3.81.106', 8, 1124013541.0)
|
||||||
|
@ -196,7 +220,7 @@ class DNSUtilsTests(unittest.TestCase):
|
||||||
|
|
||||||
def testUseDns(self):
|
def testUseDns(self):
|
||||||
res = DNSUtils.textToIp('www.example.com', 'no')
|
res = DNSUtils.textToIp('www.example.com', 'no')
|
||||||
self.assertEqual(res, None)
|
self.assertEqual(res, [])
|
||||||
res = DNSUtils.textToIp('www.example.com', 'warn')
|
res = DNSUtils.textToIp('www.example.com', 'warn')
|
||||||
self.assertEqual(res, ['192.0.43.10'])
|
self.assertEqual(res, ['192.0.43.10'])
|
||||||
res = DNSUtils.textToIp('www.example.com', 'yes')
|
res = DNSUtils.textToIp('www.example.com', 'yes')
|
||||||
|
|
Loading…
Reference in New Issue