mirror of https://github.com/fail2ban/fail2ban
Merge pull request #1569 from sebres/_0.10/fix-fakegooglebot
fixes deprecated DNSUtils.IsValidIP in fakegooglebot ignore commandpull/1571/head
commit
733d0ef596
|
@ -5,31 +5,34 @@
|
||||||
# presence of host and cut commands
|
# presence of host and cut commands
|
||||||
#
|
#
|
||||||
import sys
|
import sys
|
||||||
|
from fail2ban.server.ipdns import DNSUtils, IPAddr
|
||||||
|
|
||||||
def process_args(argv):
|
def process_args(argv):
|
||||||
if len(argv) != 2:
|
if len(argv) != 2:
|
||||||
sys.stderr.write("Please provide a single IP as an argument. Got: %s\n"
|
raise ValueError("Please provide a single IP as an argument. Got: %s\n"
|
||||||
% (argv[1:]))
|
% (argv[1:]))
|
||||||
sys.exit(2)
|
|
||||||
|
|
||||||
ip = argv[1]
|
ip = argv[1]
|
||||||
|
|
||||||
from fail2ban.server.ipdns import DNSUtils
|
if not IPAddr(ip).isValid:
|
||||||
if not DNSUtils.isValidIP(ip):
|
raise ValueError("Argument must be a single valid IP. Got: %s\n"
|
||||||
sys.stderr.write("Argument must be a single valid IP. Got: %s\n"
|
|
||||||
% ip)
|
% ip)
|
||||||
sys.exit(3)
|
|
||||||
return ip
|
return ip
|
||||||
|
|
||||||
|
google_ips = None
|
||||||
|
|
||||||
def is_googlebot(ip):
|
def is_googlebot(ip):
|
||||||
import re
|
import re
|
||||||
from fail2ban.server.ipdns import DNSUtils
|
|
||||||
|
|
||||||
host = DNSUtils.ipToName(ip)
|
host = DNSUtils.ipToName(ip)
|
||||||
if not host or not re.match('.*\.google(bot)?\.com$', host):
|
if not host or not re.match('.*\.google(bot)?\.com$', host):
|
||||||
sys.exit(1)
|
return False
|
||||||
host_ips = DNSUtils.dnsToIp(host)
|
host_ips = DNSUtils.dnsToIp(host)
|
||||||
sys.exit(0 if ip in host_ips else 1)
|
return (ip in host_ips)
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__': # pragma: no cover
|
||||||
is_googlebot(process_args(sys.argv))
|
try:
|
||||||
|
ret = is_googlebot(process_args(sys.argv))
|
||||||
|
except ValueError as e:
|
||||||
|
sys.stderr.write(str(e))
|
||||||
|
sys.exit(2)
|
||||||
|
sys.exit(0 if ret else 1)
|
||||||
|
|
|
@ -28,10 +28,6 @@ import logging
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
if sys.version_info >= (3, 3):
|
|
||||||
import importlib.machinery
|
|
||||||
else:
|
|
||||||
import imp
|
|
||||||
from collections import Mapping
|
from collections import Mapping
|
||||||
try:
|
try:
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
|
@ -87,18 +83,11 @@ class Actions(JailThread, Mapping):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _load_python_module(pythonModule):
|
def _load_python_module(pythonModule):
|
||||||
pythonModuleName = os.path.splitext(
|
mod = Utils.load_python_module(pythonModule)
|
||||||
os.path.basename(pythonModule))[0]
|
if not hasattr(mod, "Action"): # pragma: no cover
|
||||||
if sys.version_info >= (3, 3):
|
|
||||||
mod = importlib.machinery.SourceFileLoader(
|
|
||||||
pythonModuleName, pythonModule).load_module()
|
|
||||||
else:
|
|
||||||
mod = imp.load_source(
|
|
||||||
pythonModuleName, pythonModule)
|
|
||||||
if not hasattr(mod, "Action"):
|
|
||||||
raise RuntimeError(
|
raise RuntimeError(
|
||||||
"%s module does not have 'Action' class" % pythonModule)
|
"%s module does not have 'Action' class" % pythonModule)
|
||||||
elif not issubclass(mod.Action, ActionBase):
|
elif not issubclass(mod.Action, ActionBase): # pragma: no cover
|
||||||
raise RuntimeError(
|
raise RuntimeError(
|
||||||
"%s module %s does not implement required methods" % (
|
"%s module %s does not implement required methods" % (
|
||||||
pythonModule, mod.Action.__name__))
|
pythonModule, mod.Action.__name__))
|
||||||
|
|
|
@ -30,6 +30,11 @@ import sys
|
||||||
import time
|
import time
|
||||||
from ..helpers import getLogger, uni_decode
|
from ..helpers import getLogger, uni_decode
|
||||||
|
|
||||||
|
if sys.version_info >= (3, 3):
|
||||||
|
import importlib.machinery
|
||||||
|
else:
|
||||||
|
import imp
|
||||||
|
|
||||||
# Gets the instance of the logger.
|
# Gets the instance of the logger.
|
||||||
logSys = getLogger(__name__)
|
logSys = getLogger(__name__)
|
||||||
|
|
||||||
|
@ -290,3 +295,15 @@ class Utils():
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def load_python_module(pythonModule):
|
||||||
|
pythonModuleName = os.path.splitext(
|
||||||
|
os.path.basename(pythonModule))[0]
|
||||||
|
if sys.version_info >= (3, 3):
|
||||||
|
mod = importlib.machinery.SourceFileLoader(
|
||||||
|
pythonModuleName, pythonModule).load_module()
|
||||||
|
else:
|
||||||
|
mod = imp.load_source(
|
||||||
|
pythonModuleName, pythonModule)
|
||||||
|
return mod
|
||||||
|
|
|
@ -48,6 +48,9 @@ from .dummyjail import DummyJail
|
||||||
|
|
||||||
TEST_FILES_DIR = os.path.join(os.path.dirname(__file__), "files")
|
TEST_FILES_DIR = os.path.join(os.path.dirname(__file__), "files")
|
||||||
|
|
||||||
|
STOCK_CONF_DIR = "config"
|
||||||
|
STOCK = os.path.exists(os.path.join(STOCK_CONF_DIR, 'fail2ban.conf'))
|
||||||
|
|
||||||
|
|
||||||
# yoh: per Steven Hiscocks's insight while troubleshooting
|
# yoh: per Steven Hiscocks's insight while troubleshooting
|
||||||
# https://github.com/fail2ban/fail2ban/issues/103#issuecomment-15542836
|
# https://github.com/fail2ban/fail2ban/issues/103#issuecomment-15542836
|
||||||
|
@ -409,6 +412,33 @@ class IgnoreIPDNS(LogCaptureTestCase):
|
||||||
self.assertFalse(self.filter.inIgnoreIPList("128.178.50.11"))
|
self.assertFalse(self.filter.inIgnoreIPList("128.178.50.11"))
|
||||||
self.assertFalse(self.filter.inIgnoreIPList("128.178.50.13"))
|
self.assertFalse(self.filter.inIgnoreIPList("128.178.50.13"))
|
||||||
|
|
||||||
|
def testIgnoreCmdApacheFakegooglebot(self):
|
||||||
|
if not STOCK: # pragma: no cover
|
||||||
|
raise unittest.SkipTest('Skip test because of no STOCK config')
|
||||||
|
cmd = os.path.join(STOCK_CONF_DIR, "filter.d/ignorecommands/apache-fakegooglebot")
|
||||||
|
## below test direct as python module:
|
||||||
|
mod = Utils.load_python_module(cmd)
|
||||||
|
self.assertFalse(mod.is_googlebot(mod.process_args([cmd, "128.178.50.12"])))
|
||||||
|
self.assertFalse(mod.is_googlebot(mod.process_args([cmd, "192.0.2.1"])))
|
||||||
|
bot_ips = ['66.249.66.1']
|
||||||
|
for ip in bot_ips:
|
||||||
|
self.assertTrue(mod.is_googlebot(mod.process_args([cmd, str(ip)])), "test of googlebot ip %s failed" % ip)
|
||||||
|
self.assertRaises(ValueError, lambda: mod.is_googlebot(mod.process_args([cmd])))
|
||||||
|
self.assertRaises(ValueError, lambda: mod.is_googlebot(mod.process_args([cmd, "192.0"])))
|
||||||
|
## via command:
|
||||||
|
self.filter.setIgnoreCommand(cmd + " <ip>")
|
||||||
|
for ip in bot_ips:
|
||||||
|
self.assertTrue(self.filter.inIgnoreIPList(str(ip)), "test of googlebot ip %s failed" % ip)
|
||||||
|
self.assertLogged('-- returned successfully')
|
||||||
|
self.pruneLog()
|
||||||
|
self.assertFalse(self.filter.inIgnoreIPList("192.0"))
|
||||||
|
self.assertLogged('Argument must be a single valid IP.')
|
||||||
|
self.pruneLog()
|
||||||
|
self.filter.setIgnoreCommand(cmd + " bad arguments <ip>")
|
||||||
|
self.assertFalse(self.filter.inIgnoreIPList("192.0"))
|
||||||
|
self.assertLogged('Please provide a single IP as an argument.')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class LogFile(LogCaptureTestCase):
|
class LogFile(LogCaptureTestCase):
|
||||||
|
|
||||||
|
|
2
setup.py
2
setup.py
|
@ -205,7 +205,7 @@ setup(
|
||||||
glob("config/filter.d/*.conf")
|
glob("config/filter.d/*.conf")
|
||||||
),
|
),
|
||||||
('/etc/fail2ban/filter.d/ignorecommands',
|
('/etc/fail2ban/filter.d/ignorecommands',
|
||||||
glob("config/filter.d/ignorecommands/*")
|
[p for p in glob("config/filter.d/ignorecommands/*") if isfile(p)]
|
||||||
),
|
),
|
||||||
('/etc/fail2ban/action.d',
|
('/etc/fail2ban/action.d',
|
||||||
glob("config/action.d/*.conf") +
|
glob("config/action.d/*.conf") +
|
||||||
|
|
Loading…
Reference in New Issue