mirror of https://github.com/fail2ban/fail2ban
- Changed Fail2Ban in order to handle several log files
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@50 a942ae1a-1317-0410-a47c-b1dcaea8d6050.6
parent
2c778a9b76
commit
2e5bfe5bb6
|
@ -4,9 +4,15 @@
|
|||
|_| \__,_|_|_/___|_.__/\__,_|_||_|
|
||||
|
||||
=============================================================
|
||||
Fail2Ban (version 0.1.2) 11/21/2004
|
||||
Fail2Ban (version 0.3.0) 02/??/2005
|
||||
=============================================================
|
||||
|
||||
ver. 0.3.0 (02/??/2005) - alpha
|
||||
----------
|
||||
- Re-writting of parts of the code in order to handle several
|
||||
log files with different rules
|
||||
- Removed sshd.py because it is no more needed
|
||||
|
||||
ver. 0.1.2 (11/21/2004) - beta
|
||||
----------
|
||||
- Add ipfw and ipfwadm support. The rules are taken from
|
||||
|
|
3
MANIFEST
3
MANIFEST
|
@ -12,5 +12,6 @@ firewall/ipfwadm.py
|
|||
logreader/__init__.py
|
||||
logreader/logreader.py
|
||||
logreader/parser.py
|
||||
logreader/sshd.py
|
||||
confreader/__init__.py
|
||||
confreader/configreader.py
|
||||
config/fail2ban.conf.default
|
||||
|
|
2
README
2
README
|
@ -79,7 +79,7 @@ options:
|
|||
-b start fail2ban in background
|
||||
-d start fail2ban in debug mode
|
||||
-e <INTF> ban IP on the INTF interface
|
||||
-f <FILE> read password failure from FILE
|
||||
-c <FILE> read configuration file FILE
|
||||
-h display this help message
|
||||
-i <IP(s)> IP(s) to ignore
|
||||
-l <FILE> log message in FILE
|
||||
|
|
|
@ -16,10 +16,6 @@ background = false
|
|||
# and bypass root user test.
|
||||
debug = false
|
||||
|
||||
# pwdfailfile: the path of the file which contains the
|
||||
# password failure log.
|
||||
pwdfailfile = /var/log/pwdfail/current
|
||||
|
||||
# logfile: the path of the file for logging messages of
|
||||
# fail2ban.
|
||||
logfile = /var/log/fail2ban.log
|
||||
|
@ -44,3 +40,40 @@ interface = eth0
|
|||
# log file). 1 is a good value.
|
||||
polltime = 1
|
||||
|
||||
# You can define a new section for each log file to check for
|
||||
# password failure.
|
||||
|
||||
[Apache]
|
||||
# logfile: file to monitor.
|
||||
logfile = log-test/apache
|
||||
|
||||
# timeregex: regular expression which have to match the
|
||||
# timestamp of an Apache log event.
|
||||
# [Wed Jan 05 15:08:01 2005]
|
||||
timeregex = \S{3} \S{3} \d{2} \d{2}:\d{2}:\d{2} \d{4}
|
||||
|
||||
# timepattern: indicates the "timeregex" fields signification.
|
||||
# See syntax here: http://rgruet.free.fr/PQR2.3.html#timeModule
|
||||
timepattern = %%a %%b %%d %%H:%%M:%%S %%Y
|
||||
|
||||
# failregex: regular expression which have to match the
|
||||
# message written in the log file in case of password failure.
|
||||
failregex = authentication failure
|
||||
|
||||
[SSH]
|
||||
# logfile: file to monitor.
|
||||
logfile = log-test/current
|
||||
|
||||
# timeregex: regular expression which have to match the
|
||||
# timestamp of an Apache log event.
|
||||
# Mar 7 17:53:28
|
||||
timeregex = \S{3}\s{1,2}\d{1,2} \d{2}:\d{2}:\d{2}
|
||||
|
||||
# timepattern: indicates the "timeregex" fields signification.
|
||||
# See syntax here: http://rgruet.free.fr/PQR2.3.html#timeModule
|
||||
timepattern = %%b %%d %%H:%%M:%%S
|
||||
|
||||
# failregex: regular expression which have to match the
|
||||
# message written in the log file in case of password failure.
|
||||
failregex = Authentication failure
|
||||
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
# This file is part of Fail2Ban.
|
||||
#
|
||||
# Fail2Ban is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Fail2Ban is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Fail2Ban; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
# Author: Cyril Jaquier
|
||||
#
|
||||
# $Revision$
|
||||
|
||||
__author__ = "Cyril Jaquier"
|
||||
__version__ = "$Revision$"
|
||||
__date__ = "$Date$"
|
||||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
||||
__license__ = "GPL"
|
|
@ -24,32 +24,34 @@ __date__ = "$Date$"
|
|||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
||||
__license__ = "GPL"
|
||||
|
||||
from parser import Parser
|
||||
import os, sys, time
|
||||
|
||||
class Sshd(Parser):
|
||||
""" OpenSSH daemon log parser. Contains specific code for sshd.
|
||||
from ConfigParser import *
|
||||
|
||||
class ConfigReader:
|
||||
""" Reads a log file and reports information about IP that make password
|
||||
failure, bad user or anything else that is considered as doubtful login
|
||||
attempt.
|
||||
"""
|
||||
|
||||
_instance = None
|
||||
# This is the pattern to look for.
|
||||
pattern = "Failed password|Illegal user"
|
||||
optionValues = ("logfile", "timeregex", "timepattern", "failregex")
|
||||
|
||||
def __init__(self, confPath):
|
||||
self.confPath = confPath
|
||||
self.configParser = SafeConfigParser()
|
||||
|
||||
def openConf(self):
|
||||
self.configParser.read(self.confPath)
|
||||
|
||||
def getSections(self):
|
||||
return self.configParser.sections()
|
||||
|
||||
def getLogOptions(self, sec):
|
||||
values = dict()
|
||||
for option in self.optionValues:
|
||||
v = self.configParser.get(sec, option)
|
||||
values[option] = v
|
||||
return values
|
||||
|
||||
|
||||
def getInstance():
|
||||
""" We use a singleton.
|
||||
"""
|
||||
if not Sshd._instance:
|
||||
Sshd._instance = Sshd()
|
||||
return Sshd._instance
|
||||
|
||||
getInstance = staticmethod(getInstance)
|
||||
|
||||
def parseLogLine(self, line):
|
||||
""" Matches sshd bad login attempt. Returns the IP and the
|
||||
log time.
|
||||
"""
|
||||
if self.getLogMatch(self.pattern, line):
|
||||
matchIP = self.getLogIP(line)
|
||||
if matchIP:
|
||||
return [matchIP, self.getLogTime(line)]
|
||||
else:
|
||||
return False
|
77
fail2ban.py
77
fail2ban.py
|
@ -44,6 +44,7 @@ from firewall.ipfw import Ipfw
|
|||
from firewall.ipfwadm import Ipfwadm
|
||||
from logreader.logreader import LogReader
|
||||
from version import version
|
||||
from confreader.configreader import ConfigReader
|
||||
|
||||
def usage():
|
||||
print "Usage: fail2ban.py [OPTIONS]"
|
||||
|
@ -54,7 +55,7 @@ def usage():
|
|||
print " -b start fail2ban in background"
|
||||
print " -d start fail2ban in debug mode"
|
||||
print " -e <INTF> ban IP on the INTF interface"
|
||||
print " -f <FILE> read password failure from FILE"
|
||||
print " -c <FILE> read configuration file FILE"
|
||||
print " -h display this help message"
|
||||
print " -i <IP(s)> IP(s) to ignore"
|
||||
print " -l <FILE> log message in FILE"
|
||||
|
@ -167,15 +168,12 @@ if __name__ == "__main__":
|
|||
logSys = log4py.Logger().get_instance()
|
||||
logSys.set_formatstring("%T %L %M")
|
||||
|
||||
# Config file
|
||||
configParser = SafeConfigParser()
|
||||
configParser.read("/etc/fail2ban.conf")
|
||||
|
||||
conf = dict()
|
||||
conf["verbose"] = False
|
||||
conf["background"] = False
|
||||
conf["debug"] = False
|
||||
conf["pwdfailfile"] = "/var/log/pwdfail/current"
|
||||
conf["conffile"] = "/etc/fail2ban.conf"
|
||||
conf["apachefile"] = "log-test/current"
|
||||
conf["logging"] = False
|
||||
conf["logfile"] = "/var/log/fail2ban.log"
|
||||
conf["maxretry"] = 3
|
||||
|
@ -185,6 +183,21 @@ if __name__ == "__main__":
|
|||
conf["firewall"] = "iptables"
|
||||
conf["polltime"] = 1
|
||||
|
||||
# Reads the command line options.
|
||||
try:
|
||||
optList, args = getopt.getopt(sys.argv[1:], 'hvbdc:l:t:i:r:e:w:')
|
||||
except getopt.GetoptError:
|
||||
usage()
|
||||
|
||||
# Pre-parsing of command line options for the -c option
|
||||
for opt in optList:
|
||||
if opt[0] == "-c":
|
||||
conf["conffile"] = opt[1]
|
||||
|
||||
# Config file
|
||||
configParser = SafeConfigParser()
|
||||
configParser.read(conf["conffile"])
|
||||
|
||||
# background
|
||||
try:
|
||||
conf["background"] = configParser.getboolean("DEFAULT", "background")
|
||||
|
@ -204,16 +217,6 @@ if __name__ == "__main__":
|
|||
except NoOptionError:
|
||||
logSys.warn("debug option not in config file")
|
||||
logSys.warn("Using default value")
|
||||
|
||||
# pwdfailfile
|
||||
try:
|
||||
conf["pwdfailfile"] = configParser.get("DEFAULT", "pwdfailfile")
|
||||
except ValueError:
|
||||
logSys.warn("pwdfailfile option should be a string")
|
||||
logSys.warn("Using default value")
|
||||
except NoOptionError:
|
||||
logSys.warn("pwdfailfile option not in config file")
|
||||
logSys.warn("Using default value")
|
||||
|
||||
# logfile
|
||||
try:
|
||||
|
@ -265,7 +268,7 @@ if __name__ == "__main__":
|
|||
logSys.warn("interface option not in config file")
|
||||
logSys.warn("Using default value")
|
||||
|
||||
# interface
|
||||
# firewall
|
||||
try:
|
||||
conf["firewall"] = configParser.get("DEFAULT", "firewall")
|
||||
except ValueError:
|
||||
|
@ -285,12 +288,6 @@ if __name__ == "__main__":
|
|||
logSys.warn("polltime option not in config file")
|
||||
logSys.warn("Using default value")
|
||||
|
||||
# Reads the command line options.
|
||||
try:
|
||||
optList, args = getopt.getopt(sys.argv[1:], 'hvbdf:l:t:i:r:e:w:')
|
||||
except getopt.GetoptError:
|
||||
usage()
|
||||
|
||||
for opt in optList:
|
||||
if opt[0] == "-h":
|
||||
usage()
|
||||
|
@ -302,8 +299,6 @@ if __name__ == "__main__":
|
|||
conf["debug"] = True
|
||||
if opt[0] == "-e":
|
||||
conf["interface"] = opt[1]
|
||||
if opt[0] == "-f":
|
||||
conf["pwdfailfile"] = opt[1]
|
||||
if opt[0] == "-l":
|
||||
conf["logging"] = True
|
||||
conf["logfile"] = opt[1]
|
||||
|
@ -359,22 +354,35 @@ if __name__ == "__main__":
|
|||
if not conf["debug"]:
|
||||
sys.exit(-1)
|
||||
|
||||
logSys.debug("logFilePath is "+conf["pwdfailfile"])
|
||||
logSys.debug("ConfFile is "+conf["conffile"])
|
||||
logSys.debug("BanTime is "+`conf["bantime"]`)
|
||||
logSys.debug("retryAllowed is "+`conf["maxretry"]`)
|
||||
|
||||
# Reads the config file and create a LogReader instance for
|
||||
# each log file to check.
|
||||
confReader = ConfigReader(conf["conffile"]);
|
||||
confReader.openConf()
|
||||
logList = list()
|
||||
for t in confReader.getSections():
|
||||
l = confReader.getLogOptions(t)
|
||||
lObj = LogReader(logSys, l["logfile"], l["timeregex"],
|
||||
l["timepattern"], l["failregex"])
|
||||
lObj.openLogFile()
|
||||
logList.append(lObj)
|
||||
|
||||
# Creates one instance of Iptables (thanks to Pyhton dynamic
|
||||
# features) and one of LogReader.
|
||||
fireWallObj = eval(fireWallName)
|
||||
fireWall = fireWallObj(conf["bantime"], logSys, conf["interface"])
|
||||
logFile = LogReader(conf["pwdfailfile"], logSys, conf["bantime"])
|
||||
|
||||
# We add 127.0.0.1 to the ignore list has we do not want
|
||||
# to be ban ourself.
|
||||
logFile.addIgnoreIP("127.0.0.1")
|
||||
for element in logList:
|
||||
element.addIgnoreIP("127.0.0.1")
|
||||
while len(ignoreIPList) > 0:
|
||||
ip = ignoreIPList.pop()
|
||||
logFile.addIgnoreIP(ip)
|
||||
for element in logList:
|
||||
element.addIgnoreIP(ip)
|
||||
|
||||
logSys.info("Fail2Ban v"+version+" is running")
|
||||
# Main loop
|
||||
|
@ -390,12 +398,19 @@ if __name__ == "__main__":
|
|||
# If the log file has not been modified since the
|
||||
# last time, we sleep for 1 second. This is active
|
||||
# polling so not very effective.
|
||||
if not logFile.isModified():
|
||||
isModified = False
|
||||
for element in logList:
|
||||
if element.isModified():
|
||||
isModified = True
|
||||
|
||||
if not isModified:
|
||||
time.sleep(conf["polltime"])
|
||||
continue
|
||||
|
||||
# Gets the failure list from the log file.
|
||||
failList = logFile.getPwdFailure()
|
||||
failList = dict()
|
||||
for element in logList:
|
||||
failList.update(element.getFailures())
|
||||
|
||||
# We iterate the failure list and ban IP that make
|
||||
# *retryAllowed* login failures.
|
||||
|
|
|
@ -0,0 +1,102 @@
|
|||
[Mon Jan 03 05:02:15 2005] [error] [client 81.83.248.17] File does not exist: /var/www/jaquier.dyndns.org/htdocs/msadc
|
||||
[Mon Jan 03 05:02:20 2005] [error] [client 81.83.248.17] File does not exist: /var/www/jaquier.dyndns.org/htdocs/msadc
|
||||
[Mon Jan 03 05:02:20 2005] [error] [client 81.83.248.17] File does not exist: /var/www/jaquier.dyndns.org/htdocs/msadc
|
||||
[Mon Jan 03 05:02:21 2005] [error] [client 81.83.248.17] File does not exist: /var/www/jaquier.dyndns.org/htdocs/msadc
|
||||
[Mon Jan 03 05:02:22 2005] [error] [client 81.83.248.17] File does not exist: /var/www/jaquier.dyndns.org/htdocs/msadc
|
||||
[Mon Jan 03 05:02:22 2005] [error] [client 81.83.248.17] File does not exist: /var/www/jaquier.dyndns.org/htdocs/msadc
|
||||
[Mon Jan 03 05:02:22 2005] [error] [client 81.83.248.17] File does not exist: /var/www/jaquier.dyndns.org/htdocs/msadc
|
||||
[Mon Jan 03 05:02:22 2005] [error] [client 81.83.248.17] File does not exist: /var/www/jaquier.dyndns.org/htdocs/\xe0
|
||||
[Mon Jan 03 05:02:23 2005] [error] [client 81.83.248.17] File does not exist: /var/www/jaquier.dyndns.org/htdocs/msdac
|
||||
[Mon Jan 03 05:02:23 2005] [error] [client 81.83.248.17] File does not exist: /var/www/jaquier.dyndns.org/htdocs/msdac
|
||||
[Mon Jan 03 05:02:24 2005] [error] [client 81.83.248.17] File does not exist: /var/www/jaquier.dyndns.org/htdocs/PBServer
|
||||
[Mon Jan 03 05:02:24 2005] [error] [client 81.83.248.17] File does not exist: /var/www/jaquier.dyndns.org/htdocs/PBServer
|
||||
[Mon Jan 03 05:02:27 2005] [error] [client 81.83.248.17] File does not exist: /var/www/jaquier.dyndns.org/htdocs/Rpc
|
||||
[Mon Jan 03 05:02:27 2005] [error] [client 81.83.248.17] File does not exist: /var/www/jaquier.dyndns.org/htdocs/Rpc
|
||||
[Mon Jan 03 05:02:27 2005] [error] [client 81.83.248.17] File does not exist: /var/www/jaquier.dyndns.org/htdocs/samples
|
||||
[Mon Jan 03 05:02:27 2005] [error] [client 81.83.248.17] File does not exist: /var/www/jaquier.dyndns.org/htdocs/samples
|
||||
[Mon Jan 03 05:02:28 2005] [error] [client 81.83.248.17] File does not exist: /var/www/jaquier.dyndns.org/htdocs/scripts..\xc1\x9c..
|
||||
[Mon Jan 03 05:02:28 2005] [error] [client 81.83.248.17] File does not exist: /var/www/jaquier.dyndns.org/htdocs/scripts
|
||||
[Mon Jan 03 05:02:28 2005] [error] [client 81.83.248.17] File does not exist: /var/www/jaquier.dyndns.org/htdocs/scripts
|
||||
[Mon Jan 03 05:02:28 2005] [error] [client 81.83.248.17] File does not exist: /var/www/jaquier.dyndns.org/htdocs/scripts
|
||||
[Mon Jan 03 05:02:32 2005] [error] [client 81.83.248.17] File does not exist: /var/www/jaquier.dyndns.org/htdocs/scripts
|
||||
[Mon Jan 03 05:02:32 2005] [error] [client 81.83.248.17] File does not exist: /var/www/jaquier.dyndns.org/htdocs/scripts
|
||||
[Mon Jan 03 05:02:33 2005] [error] [client 81.83.248.17] File does not exist: /var/www/jaquier.dyndns.org/htdocs/scripts
|
||||
[Mon Jan 03 05:02:33 2005] [error] [client 81.83.248.17] File does not exist: /var/www/jaquier.dyndns.org/htdocs/scripts
|
||||
[Mon Jan 03 05:02:33 2005] [error] [client 81.83.248.17] File does not exist: /var/www/jaquier.dyndns.org/htdocs/scripts
|
||||
[Mon Jan 03 05:02:34 2005] [error] [client 81.83.248.17] File does not exist: /var/www/jaquier.dyndns.org/htdocs/scripts
|
||||
[Mon Jan 03 05:02:34 2005] [error] [client 81.83.248.17] File does not exist: /var/www/jaquier.dyndns.org/htdocs/scripts
|
||||
[Mon Jan 03 05:02:38 2005] [error] [client 81.83.248.17] File does not exist: /var/www/jaquier.dyndns.org/htdocs/scripts
|
||||
[Mon Jan 03 05:02:38 2005] [error] [client 81.83.248.17] File does not exist: /var/www/jaquier.dyndns.org/htdocs/scripts
|
||||
[Mon Jan 03 05:02:38 2005] [error] [client 81.83.248.17] File does not exist: /var/www/jaquier.dyndns.org/htdocs/scripts
|
||||
[Mon Jan 03 05:02:38 2005] [error] [client 81.83.248.17] File does not exist: /var/www/jaquier.dyndns.org/htdocs/scripts
|
||||
[Mon Jan 03 05:02:39 2005] [error] [client 81.83.248.17] File does not exist: /var/www/jaquier.dyndns.org/htdocs/scripts
|
||||
[Mon Jan 03 05:02:39 2005] [error] [client 81.83.248.17] File does not exist: /var/www/jaquier.dyndns.org/htdocs/scripts
|
||||
[Mon Jan 03 11:08:29 2005] [error] [client 128.178.150.127] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
|
||||
[Mon Jan 03 20:08:52 2005] [error] [client 83.76.202.195] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
|
||||
[Tue Jan 04 15:19:50 2005] [error] [client 213.221.138.70] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
|
||||
[Tue Jan 04 15:19:55 2005] [error] [client 213.221.138.70] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
|
||||
[Tue Jan 04 15:20:01 2005] [error] [client 213.221.138.70] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
|
||||
[Tue Jan 04 15:20:05 2005] [error] [client 213.221.138.70] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
|
||||
[Tue Jan 04 15:20:08 2005] [error] [client 213.221.138.70] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
|
||||
[Tue Jan 04 15:20:12 2005] [error] [client 213.221.138.70] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
|
||||
[Tue Jan 04 15:20:16 2005] [error] [client 213.221.138.70] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
|
||||
[Tue Jan 04 15:20:22 2005] [error] [client 213.221.138.70] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
|
||||
[Tue Jan 04 15:20:26 2005] [error] [client 213.221.138.70] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
|
||||
[Tue Jan 04 15:20:28 2005] [error] [client 213.221.138.70] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
|
||||
[Tue Jan 04 15:20:38 2005] [error] [client 213.221.138.70] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
|
||||
[Tue Jan 04 20:54:59 2005] [error] [client 192.168.0.129] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
|
||||
[Tue Jan 04 20:55:04 2005] [error] [client 192.168.0.129] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
|
||||
[Tue Jan 04 20:55:29 2005] [error] [client 192.168.0.129] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
|
||||
[Tue Jan 04 21:34:29 2005] [error] [client 81.63.51.202] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
|
||||
[Tue Jan 04 21:34:32 2005] [error] [client 81.63.51.202] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
|
||||
[Wed Jan 05 00:17:41 2005] [error] [client 217.251.126.37] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
|
||||
[Wed Jan 05 00:18:03 2005] [error] [client 217.251.126.37] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
|
||||
[Wed Jan 05 00:18:12 2005] [error] [client 217.251.126.37] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
|
||||
[Wed Jan 05 01:24:38 2005] [error] [client 81.63.51.202] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
|
||||
[Wed Jan 05 01:24:40 2005] [error] [client 81.63.51.202] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
|
||||
[Wed Jan 05 01:24:46 2005] [error] [client 81.63.51.202] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
|
||||
[Wed Jan 05 01:24:48 2005] [error] [client 81.63.51.202] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
|
||||
[Wed Jan 05 01:25:58 2005] [error] [client 81.63.51.202] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
|
||||
[Wed Jan 05 01:26:34 2005] [error] [client 81.63.51.202] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
|
||||
[Wed Jan 05 01:26:37 2005] [error] [client 81.63.51.202] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
|
||||
[Wed Jan 05 10:13:02 2005] [error] [client 192.168.0.129] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
|
||||
[Wed Jan 05 10:13:07 2005] [error] [client 192.168.0.129] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
|
||||
[Wed Jan 05 10:13:10 2005] [error] [client 192.168.0.129] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
|
||||
[Wed Jan 05 10:17:07 2005] [error] [client 192.168.0.129] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
|
||||
[Wed Jan 05 14:41:40 2005] [error] [client 192.168.0.129] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
|
||||
[Wed Jan 05 14:41:45 2005] [error] [client 192.168.0.129] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
|
||||
[Wed Jan 05 14:41:47 2005] [error] [client 192.168.0.129] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
|
||||
[Wed Jan 05 14:41:51 2005] [error] [client 192.168.0.129] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
|
||||
[Wed Jan 05 14:55:30 2005] [error] [client 212.101.4.200] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
|
||||
[Wed Jan 05 15:03:44 2005] [error] [client 192.168.0.129] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
|
||||
[Wed Jan 05 15:03:48 2005] [error] [client 192.168.0.129] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
|
||||
[Wed Jan 05 15:03:52 2005] [error] [client 192.168.0.129] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
|
||||
[Wed Jan 05 15:03:57 2005] [error] [client 192.168.0.129] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
|
||||
[Wed Jan 05 15:06:45 2005] [error] [client 212.101.4.200] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
|
||||
[Wed Mar 05 15:07:28 2005] [error] [client 192.168.0.128] user cyril: authentication failure for "/phpinfo": Password Mismatch
|
||||
[Wed Jan 05 15:08:01 2005] [error] [client 192.168.0.128] user not found: /phpinfo
|
||||
[Wed Jan 05 15:10:45 2005] [crit] [client 192.168.0.128] (13)Permission denied: /var/www/jaquier.dyndns.org/htdocs/css/.htaccess pcfg_openfile: unable to check htaccess file, ensure it is readable, referer: http://earth/phpinfo
|
||||
[Wed Jan 05 15:10:45 2005] [crit] [client 192.168.0.128] (13)Permission denied: /var/www/jaquier.dyndns.org/htdocs/images/.htaccess pcfg_openfile: unable to check htaccess file, ensure it is readable, referer: http://earth/phpinfo
|
||||
[Wed Jan 05 15:10:45 2005] [error] [client 192.168.0.128] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
|
||||
[Wed Jan 05 15:11:09 2005] [error] [client 192.168.0.128] user test not found: /phpinfo
|
||||
[Wed Jan 05 15:11:10 2005] [error] [client 192.168.0.128] user test not found: /phpinfo
|
||||
[Wed Jan 06 15:11:11 2005] [error] [client 192.168.0.128] user test not found: /phpinfo
|
||||
[Wed Jan 06 15:11:13 2005] [error] [client 192.168.0.128] user test not found: /phpinfo
|
||||
[Wed Jan 06 15:11:14 2005] [error] [client 192.168.0.128] user test not found: /phpinfo
|
||||
[Wed Jan 05 15:11:15 2005] [crit] [client 192.168.0.128] (13)Permission denied: /var/www/jaquier.dyndns.org/htdocs/css/.htaccess pcfg_openfile: unable to check htaccess file, ensure it is readable, referer: http://earth/phpinfo
|
||||
[Wed Jan 05 15:11:15 2005] [crit] [client 192.168.0.128] (13)Permission denied: /var/www/jaquier.dyndns.org/htdocs/images/.htaccess pcfg_openfile: unable to check htaccess file, ensure it is readable, referer: http://earth/phpinfo
|
||||
[Wed Jan 05 15:11:15 2005] [error] [client 192.168.0.128] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
|
||||
[Wed Jan 05 15:12:32 2005] [error] [client 212.101.4.200] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
|
||||
[Wed Jan 05 15:13:48 2005] [error] [client 192.168.0.129] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
|
||||
[Wed Jan 05 15:13:51 2005] [error] [client 192.168.0.129] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
|
||||
[Wed Jan 05 15:13:52 2005] [error] [client 192.168.0.129] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
|
||||
[Wed Jan 05 15:13:52 2005] [error] [client 192.168.0.129] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
|
||||
[Wed Jan 05 15:13:54 2005] [error] [client 192.168.0.129] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
|
||||
[Wed Jan 05 15:13:56 2005] [error] [client 192.168.0.129] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
|
||||
[Wed Jan 05 15:13:59 2005] [error] [client 192.168.0.129] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
|
||||
[Wed Jan 05 15:14:20 2005] [error] [client 192.168.0.129] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
|
||||
[Wed Jan 05 15:14:24 2005] [error] [client 192.168.0.129] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
|
||||
[Wed Jan 05 15:14:29 2005] [error] [client 192.168.0.129] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
|
||||
[Wed Jan 05 15:14:34 2005] [error] [client 192.168.0.129] File does not exist: /var/www/jaquier.dyndns.org/htdocs/favicon.ico
|
||||
[Wed Mar 05 15:08:28 2005] [error] [client 192.168.0.128] user cyril: authentication failure for "/phpinfo": Password Mismatch
|
||||
[Wed Mar 05 15:09:28 2005] [error] [client 192.168.0.128] user cyril: authentication failure for "/phpinfo": Password Mismatch
|
|
@ -1,4 +1,5 @@
|
|||
- Last output repeated 2 times -
|
||||
Oct 7 11:47:08 [sshd] Failed password for illegal user test from 69.182.27.122 port 34015 ssh2
|
||||
Oct 7 11:47:09 [sshd] Failed password for illegal user guest from 69.182.27.122 port 34068 ssh2
|
||||
Oct 7 11:47:11 [sshd] Failed password for illegal user admin from 69.182.27.122 port 34127 ssh2
|
||||
Jan 7 17:53:15 [sshd] (pam_unix) 2 more authentication failures; logname= uid=0 euid=0 tty=ssh ruser= rhost=62.220.137.36 user=kevin
|
||||
Jan 7 17:53:26 [sshd] (pam_unix) authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=62.220.137.36 user=kevin
|
||||
Mar 7 17:53:28 [sshd] error: PAM: Authentication failure for kevin from 62.220.137.36
|
||||
Mar 7 17:55:28 [sshd] error: PAM: Authentication failure for kevin from 62.220.137.36
|
||||
Mar 7 17:57:28 [sshd] error: PAM: Authentication failure for kevin from 62.220.137.36
|
||||
|
|
|
@ -425,7 +425,8 @@ Oct 7 01:03:12 [sshd] Failed password for illegal user tata from 128.178.164.52
|
|||
- Last output repeated 2 times -
|
||||
Oct 7 01:03:20 [sshd] Failed password for illegal user tata from 128.178.164.52 port 37187 ssh2
|
||||
- Last output repeated 2 times -
|
||||
Oct 11 11:47:08 [sshd] Failed password for illegal user test from 69.182.27.122 port 34015 ssh2
|
||||
Oct 11 11:47:09 [sshd] Failed password for illegal user guest from 69.182.27.122 port 34068 ssh2
|
||||
Oct 11 11:47:11 [sshd] Failed password for illegal user admin from 69.182.27.122 port 34127 ssh2
|
||||
Oct 12 21:54:11 yellow sshd[16069]: Failed password for cyril from 212.41.79.210 port 29404 ssh2
|
||||
Nov 14 11:47:08 [sshd] Failed password for illegal user test from 69.182.27.122 port 34015 ssh2
|
||||
Nov 14 11:47:09 [sshd] Failed password for illegal user guest from 69.182.27.122 port 34068 ssh2
|
||||
Nov 14 11:47:11 [sshd] Failed password for illegal user admin from 69.182.27.122 port 34127 ssh2
|
||||
Nov 15 11:12:11 yellow sshd[16069]: Failed password for cyril from 212.41.79.210 port 29404 ssh2
|
||||
Nov 15 21:54:11 yellow sshd[16069]: Illegal user for cyril from 212.41.79.210 port 29404 ssh2
|
||||
|
|
|
@ -24,9 +24,7 @@ __date__ = "$Date$"
|
|||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
||||
__license__ = "GPL"
|
||||
|
||||
import os, sys, time
|
||||
|
||||
from sshd import Sshd
|
||||
import os, sys, time, re
|
||||
|
||||
class LogReader:
|
||||
""" Reads a log file and reports information about IP that make password
|
||||
|
@ -34,13 +32,15 @@ class LogReader:
|
|||
attempt.
|
||||
"""
|
||||
|
||||
def __init__(self, logPath, logSys, findTime = 3600):
|
||||
def __init__(self, logSys, logPath, timeregex, timepattern, failregex, findTime = 3600):
|
||||
self.logPath = logPath
|
||||
self.timeregex = timeregex
|
||||
self.timepattern = timepattern
|
||||
self.failregex = failregex
|
||||
self.findTime = findTime
|
||||
self.ignoreIpList = []
|
||||
self.lastModTime = 0
|
||||
self.logSys = logSys
|
||||
self.parserList = ["Sshd"]
|
||||
|
||||
def addIgnoreIP(self, ip):
|
||||
""" Adds an IP to the ignore list.
|
||||
|
@ -79,30 +79,14 @@ class LogReader:
|
|||
self.lastModTime = logStats.st_mtime
|
||||
return True
|
||||
|
||||
def matchLine(self, line):
|
||||
""" Checks if the line contains a pattern. It does this for all
|
||||
classes specified in *parserList*. We use a singleton to avoid
|
||||
creating/destroying objects too much.
|
||||
|
||||
Return a dict with the IP and number of retries.
|
||||
"""
|
||||
for i in self.parserList:
|
||||
match = eval(i).getInstance().parseLogLine(line)
|
||||
if match:
|
||||
return match
|
||||
return None
|
||||
|
||||
def getFailInfo(self, findTime):
|
||||
""" Gets the failed login attempt. Returns a dict() which contains
|
||||
IP and the number of retries.
|
||||
"""
|
||||
def getFailures(self):
|
||||
ipList = dict()
|
||||
logFile = self.openLogFile()
|
||||
for line in logFile.readlines():
|
||||
match = self.matchLine(line)
|
||||
if match:
|
||||
ip = match[0]
|
||||
unixTime = match[1]
|
||||
value = self.findFailure(line)
|
||||
if value:
|
||||
ip = value[0]
|
||||
unixTime = value[1]
|
||||
if unixTime < time.time()-self.findTime:
|
||||
continue
|
||||
if self.inIgnoreIPList(ip):
|
||||
|
@ -115,9 +99,35 @@ class LogReader:
|
|||
ipList[ip] = (1, unixTime)
|
||||
logFile.close()
|
||||
return ipList
|
||||
|
||||
def findFailure(self, line):
|
||||
match = self.matchLine(line, self.failregex)
|
||||
if match:
|
||||
timeMatch = self.matchLine(match.string, self.timeregex)
|
||||
if timeMatch:
|
||||
date = self.getUnixTime(timeMatch.group(), self.timepattern)
|
||||
ipMatch = self.matchAddress(match.string)
|
||||
if ipMatch:
|
||||
ip = ipMatch.group()
|
||||
return [ip, date]
|
||||
return None
|
||||
|
||||
def getUnixTime(self, value, pattern):
|
||||
date = list(time.strptime(value, pattern))
|
||||
if date[0] < 2000:
|
||||
date[0] = time.gmtime()[0]
|
||||
unixTime = time.mktime(date)
|
||||
return unixTime
|
||||
|
||||
def getPwdFailure(self):
|
||||
""" Executes the getFailInfo method. Not very usefull...
|
||||
def matchLine(self, line, pattern):
|
||||
""" Checks if the line contains a pattern. It does this for all
|
||||
classes specified in *parserList*. We use a singleton to avoid
|
||||
creating/destroying objects too much.
|
||||
|
||||
Return a dict with the IP and number of retries.
|
||||
"""
|
||||
failList = self.getFailInfo(self.findTime)
|
||||
return failList
|
||||
return re.search(pattern, line)
|
||||
|
||||
def matchAddress(self, line):
|
||||
return re.search("(?:\d{1,3}\.){3}\d{1,3}", line)
|
||||
|
|
@ -1,67 +0,0 @@
|
|||
# This file is part of Fail2Ban.
|
||||
#
|
||||
# Fail2Ban is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Fail2Ban is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Fail2Ban; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
# Author: Cyril Jaquier
|
||||
#
|
||||
# $Revision$
|
||||
|
||||
__author__ = "Cyril Jaquier"
|
||||
__version__ = "$Revision$"
|
||||
__date__ = "$Date$"
|
||||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
||||
__license__ = "GPL"
|
||||
|
||||
import time, re
|
||||
|
||||
class Parser:
|
||||
""" This class is the main log parser class. It should be inherited
|
||||
by all the service specific classes.
|
||||
"""
|
||||
|
||||
def getLogMatch(self, pattern, line):
|
||||
""" Returns a match if pattern is found in line.
|
||||
"""
|
||||
return re.search(pattern, line)
|
||||
|
||||
def getLogIPv4(self, line):
|
||||
""" Returns IP if one is found in line. Match IPv4 string.
|
||||
"""
|
||||
matchIP = re.search("(?:\d{1,3}\.){3}\d{1,3}", line)
|
||||
if matchIP:
|
||||
return matchIP.group()
|
||||
else:
|
||||
return None
|
||||
|
||||
def getLogIP(self, line):
|
||||
""" Returns IP if one is found in line.
|
||||
"""
|
||||
return self.getLogIPv4(line)
|
||||
|
||||
def getLogTimeStandard(self, line):
|
||||
""" Returns the log time of line using a standard log format.
|
||||
|
||||
Format: Oct 14 11:47:08
|
||||
"""
|
||||
date = list(time.strptime(line[0:15], "%b %d %H:%M:%S"))
|
||||
date[0] = time.gmtime()[0]
|
||||
unixTime = time.mktime(date)
|
||||
return unixTime
|
||||
|
||||
def getLogTime(self, line):
|
||||
""" Returns the log time of line.
|
||||
"""
|
||||
return self.getLogTimeStandard(line)
|
||||
|
2
setup.py
2
setup.py
|
@ -38,5 +38,5 @@ setup(
|
|||
url = "http://www.sourceforge.net/projects/fail2ban",
|
||||
scripts = ['fail2ban.py'],
|
||||
py_modules = ['version'],
|
||||
packages = ['firewall', 'logreader']
|
||||
packages = ['firewall', 'logreader', 'confreader']
|
||||
)
|
|
@ -24,4 +24,4 @@ __date__ = "$Date$"
|
|||
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
||||
__license__ = "GPL"
|
||||
|
||||
version = "0.1.2"
|
||||
version = "0.3.0-CVS"
|
||||
|
|
Loading…
Reference in New Issue