mirror of https://github.com/fail2ban/fail2ban
- Configuration using /etc/fail2ban.conf
git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@36 a942ae1a-1317-0410-a47c-b1dcaea8d6050.6
parent
3b7f952cd2
commit
b9349fd45e
|
@ -15,6 +15,7 @@ ver. 0.1.1 (??/??/????) - alpha
|
||||||
daemon specific
|
daemon specific
|
||||||
- Rewrite log reader to be service centered. Sshd support
|
- Rewrite log reader to be service centered. Sshd support
|
||||||
added. Match "Failed password" and "Illegal user"
|
added. Match "Failed password" and "Illegal user"
|
||||||
|
- Add /etc/fail2ban.conf configuration support
|
||||||
- Code documentation
|
- Code documentation
|
||||||
|
|
||||||
|
|
||||||
|
|
186
fail2ban.py
186
fail2ban.py
|
@ -27,6 +27,7 @@ __copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
||||||
__license__ = "GPL"
|
__license__ = "GPL"
|
||||||
|
|
||||||
import posix, time, sys, getopt, os, signal
|
import posix, time, sys, getopt, os, signal
|
||||||
|
from ConfigParser import *
|
||||||
|
|
||||||
# Checks if log4py is present.
|
# Checks if log4py is present.
|
||||||
try:
|
try:
|
||||||
|
@ -52,6 +53,7 @@ def usage():
|
||||||
print " -d start fail2ban in debug mode"
|
print " -d start fail2ban in debug mode"
|
||||||
print " -f <FILE> read password failure from FILE"
|
print " -f <FILE> read password failure from FILE"
|
||||||
print " -h display this help message"
|
print " -h display this help message"
|
||||||
|
print " -i <IP(s)> IP(s) to ignore"
|
||||||
print " -l <FILE> log message in FILE"
|
print " -l <FILE> log message in FILE"
|
||||||
print " -r <VALUE> allow a max of VALUE password failure"
|
print " -r <VALUE> allow a max of VALUE password failure"
|
||||||
print " -t <TIME> ban IP for TIME seconds"
|
print " -t <TIME> ban IP for TIME seconds"
|
||||||
|
@ -151,12 +153,101 @@ if __name__ == "__main__":
|
||||||
logSys = log4py.Logger().get_instance()
|
logSys = log4py.Logger().get_instance()
|
||||||
logSys.set_formatstring("%T %L %M")
|
logSys.set_formatstring("%T %L %M")
|
||||||
|
|
||||||
# Initializes some variables.
|
# Config file
|
||||||
debug = False
|
configParser = SafeConfigParser()
|
||||||
logFilePath = "/var/log/pwdfail/current"
|
configParser.read("/etc/fail2ban.conf")
|
||||||
banTime = 600
|
|
||||||
ignoreIPList = {}
|
conf = dict()
|
||||||
retryAllowed = 3
|
conf["verbose"] = False
|
||||||
|
conf["background"] = False
|
||||||
|
conf["debug"] = False
|
||||||
|
conf["pwdfailfile"] = "/var/log/pwdfail/current"
|
||||||
|
conf["logging"] = False
|
||||||
|
conf["logfile"] = "/var/log/fail2ban.log"
|
||||||
|
conf["maxretry"] = 3
|
||||||
|
conf["bantime"] = 600
|
||||||
|
conf["ignoreip"] = ''
|
||||||
|
conf["polltime"] = 1
|
||||||
|
|
||||||
|
# background
|
||||||
|
try:
|
||||||
|
conf["background"] = configParser.getboolean("DEFAULT", "background")
|
||||||
|
except ValueError:
|
||||||
|
logSys.warn("background option should be a boolean")
|
||||||
|
logSys.warn("Using default value")
|
||||||
|
except NoOptionError:
|
||||||
|
logSys.warn("background option not in config file")
|
||||||
|
logSys.warn("Using default value")
|
||||||
|
|
||||||
|
# debug
|
||||||
|
try:
|
||||||
|
conf["debug"] = configParser.getboolean("DEFAULT", "debug")
|
||||||
|
except ValueError:
|
||||||
|
logSys.warn("debug option should be a boolean")
|
||||||
|
logSys.warn("Using default value")
|
||||||
|
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:
|
||||||
|
conf["logfile"] = configParser.get("DEFAULT", "logfile")
|
||||||
|
except ValueError:
|
||||||
|
logSys.warn("logfile option should be a string")
|
||||||
|
logSys.warn("Using default value")
|
||||||
|
except NoOptionError:
|
||||||
|
logSys.warn("logfile option not in config file")
|
||||||
|
logSys.warn("Using default value")
|
||||||
|
|
||||||
|
# maxretry
|
||||||
|
try:
|
||||||
|
conf["maxretry"] = configParser.getint("DEFAULT", "maxretry")
|
||||||
|
except ValueError:
|
||||||
|
logSys.warn("maxretry option should be an integer")
|
||||||
|
logSys.warn("Using default value")
|
||||||
|
except NoOptionError:
|
||||||
|
logSys.warn("maxretry option not in config file")
|
||||||
|
logSys.warn("Using default value")
|
||||||
|
|
||||||
|
# bantime
|
||||||
|
try:
|
||||||
|
conf["bantime"] = configParser.getint("DEFAULT", "bantime")
|
||||||
|
except ValueError:
|
||||||
|
logSys.warn("bantime option should be an integer")
|
||||||
|
logSys.warn("Using default value")
|
||||||
|
except NoOptionError:
|
||||||
|
logSys.warn("bantime option not in config file")
|
||||||
|
logSys.warn("Using default value")
|
||||||
|
|
||||||
|
# ignoreip
|
||||||
|
try:
|
||||||
|
conf["ignoreip"] = configParser.get("DEFAULT", "ignoreip")
|
||||||
|
except ValueError:
|
||||||
|
logSys.warn("ignoreip option should be a string")
|
||||||
|
logSys.warn("Using default value")
|
||||||
|
except NoOptionError:
|
||||||
|
logSys.warn("ignoreip option not in config file")
|
||||||
|
logSys.warn("Using default value")
|
||||||
|
|
||||||
|
# polltime
|
||||||
|
try:
|
||||||
|
conf["polltime"] = configParser.getint("DEFAULT", "polltime")
|
||||||
|
except ValueError:
|
||||||
|
logSys.warn("polltime option should be an integer")
|
||||||
|
logSys.warn("Using default value")
|
||||||
|
except NoOptionError:
|
||||||
|
logSys.warn("polltime option not in config file")
|
||||||
|
logSys.warn("Using default value")
|
||||||
|
|
||||||
# Reads the command line options.
|
# Reads the command line options.
|
||||||
try:
|
try:
|
||||||
|
@ -168,55 +259,64 @@ if __name__ == "__main__":
|
||||||
if opt[0] == "-h":
|
if opt[0] == "-h":
|
||||||
usage()
|
usage()
|
||||||
if opt[0] == "-v":
|
if opt[0] == "-v":
|
||||||
logSys.set_loglevel(log4py.LOGLEVEL_VERBOSE)
|
conf["verbose"] = True
|
||||||
if opt[0] == "-b":
|
if opt[0] == "-b":
|
||||||
|
conf["background"] = True
|
||||||
|
if opt[0] == "-d":
|
||||||
|
conf["debug"] = True
|
||||||
|
if opt[0] == "-f":
|
||||||
|
conf["pwdfailfile"] = opt[1]
|
||||||
|
if opt[0] == "-l":
|
||||||
|
conf["logging"] = True
|
||||||
|
conf["logfile"] = opt[1]
|
||||||
|
if opt[0] == "-t":
|
||||||
|
try:
|
||||||
|
conf["bantime"] = int(opt[1])
|
||||||
|
except ValueError:
|
||||||
|
logSys.warn("banTime must be an integer")
|
||||||
|
logSys.warn("Using default value")
|
||||||
|
if opt[0] == "-i":
|
||||||
|
conf["ignoreip"] = opt[1]
|
||||||
|
if opt[0] == "-r":
|
||||||
|
conf["retrymax"] = int(opt[1])
|
||||||
|
|
||||||
|
# Process some options
|
||||||
|
for c in conf:
|
||||||
|
if c == "verbose" and conf[c]:
|
||||||
|
logSys.set_loglevel(log4py.LOGLEVEL_VERBOSE)
|
||||||
|
elif c == "debug" and conf[c]:
|
||||||
|
logSys.set_loglevel(log4py.LOGLEVEL_DEBUG)
|
||||||
|
logSys.set_formatstring(log4py.FMT_DEBUG)
|
||||||
|
elif c == "background" and conf[c]:
|
||||||
retCode = createDaemon()
|
retCode = createDaemon()
|
||||||
logSys.set_target("/tmp/fail2ban.log")
|
logSys.set_target(conf["logfile"])
|
||||||
if retCode != 0:
|
if retCode != 0:
|
||||||
logSys.error("Unable to start daemon")
|
logSys.error("Unable to start daemon")
|
||||||
sys.exit(-1)
|
sys.exit(-1)
|
||||||
if opt[0] == "-d":
|
elif c == "logging" and conf[c]:
|
||||||
debug = True
|
|
||||||
logSys.set_loglevel(log4py.LOGLEVEL_DEBUG)
|
|
||||||
logSys.set_formatstring(log4py.FMT_DEBUG)
|
|
||||||
if opt[0] == "-f":
|
|
||||||
logFilePath = opt[1]
|
|
||||||
if opt[0] == "-l":
|
|
||||||
try:
|
try:
|
||||||
open(opt[1], "a")
|
open(conf["logfile"], "a")
|
||||||
logSys.set_target(opt[1])
|
logSys.set_target(conf["logfile"])
|
||||||
except IOError:
|
except IOError:
|
||||||
logSys.error("Unable to log to "+opt[1])
|
logSys.warn("Unable to log to "+conf["logfile"])
|
||||||
logSys.error("Using default output for logging")
|
logSys.warn("Using default output for logging")
|
||||||
if opt[0] == "-t":
|
elif c == "ignoreip":
|
||||||
try:
|
ignoreIPList = conf[c].split(' ')
|
||||||
banTime = int(opt[1])
|
|
||||||
except ValueError:
|
|
||||||
logSys.error("banTime must be an integer")
|
|
||||||
logSys.error("Using default value")
|
|
||||||
if opt[0] == "-i":
|
|
||||||
ignoreIPList = opt[1].split(' ')
|
|
||||||
if opt[0] == "-r":
|
|
||||||
try:
|
|
||||||
retryAllowed = int(opt[1])
|
|
||||||
except ValueError:
|
|
||||||
logSys.error("retryAllowed must be an integer")
|
|
||||||
logSys.error("Using default value")
|
|
||||||
|
|
||||||
# Checks for root user. This is necessary because log files
|
# Checks for root user. This is necessary because log files
|
||||||
# are owned by root and firewall needs root access.
|
# are owned by root and firewall needs root access.
|
||||||
if not checkForRoot():
|
if not checkForRoot():
|
||||||
logSys.error("You must be root")
|
logSys.error("You must be root")
|
||||||
if not debug:
|
if not conf["debug"]:
|
||||||
sys.exit(-1)
|
sys.exit(-1)
|
||||||
|
|
||||||
logSys.debug("logFilePath is "+logFilePath)
|
logSys.debug("logFilePath is "+conf["pwdfailfile"])
|
||||||
logSys.debug("BanTime is "+`banTime`)
|
logSys.debug("BanTime is "+`conf["bantime"]`)
|
||||||
logSys.debug("retryAllowed is "+`retryAllowed`)
|
logSys.debug("retryAllowed is "+`conf["maxretry"]`)
|
||||||
|
|
||||||
# Creates one instance of Iptables and one of LogReader.
|
# Creates one instance of Iptables and one of LogReader.
|
||||||
fireWall = Iptables(banTime, logSys)
|
fireWall = Iptables(conf["bantime"], logSys)
|
||||||
logFile = LogReader(logFilePath, logSys, banTime)
|
logFile = LogReader(conf["pwdfailfile"], logSys, conf["bantime"])
|
||||||
|
|
||||||
# We add 127.0.0.1 to the ignore list has we do not want
|
# We add 127.0.0.1 to the ignore list has we do not want
|
||||||
# to be ban ourself.
|
# to be ban ourself.
|
||||||
|
@ -234,13 +334,13 @@ if __name__ == "__main__":
|
||||||
|
|
||||||
# Checks if some IP have to be remove from ban
|
# Checks if some IP have to be remove from ban
|
||||||
# list.
|
# list.
|
||||||
fireWall.checkForUnBan(debug)
|
fireWall.checkForUnBan(conf["debug"])
|
||||||
|
|
||||||
# If the log file has not been modified since the
|
# If the log file has not been modified since the
|
||||||
# last time, we sleep for 1 second. This is active
|
# last time, we sleep for 1 second. This is active
|
||||||
# polling so not very effective.
|
# polling so not very effective.
|
||||||
if not logFile.isModified():
|
if not logFile.isModified():
|
||||||
time.sleep(1)
|
time.sleep(conf["polltime"])
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Gets the failure list from the log file.
|
# Gets the failure list from the log file.
|
||||||
|
@ -252,12 +352,12 @@ if __name__ == "__main__":
|
||||||
for i in range(len(failList)):
|
for i in range(len(failList)):
|
||||||
element = iterFailList.next()
|
element = iterFailList.next()
|
||||||
if element[1][0] >= retryAllowed:
|
if element[1][0] >= retryAllowed:
|
||||||
fireWall.addBanIP(element[0], debug)
|
fireWall.addBanIP(element[0], conf["debug"])
|
||||||
|
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
# When the user press <ctrl>+<c> we flush the ban list
|
# When the user press <ctrl>+<c> we flush the ban list
|
||||||
# and exit nicely.
|
# and exit nicely.
|
||||||
logSys.info("Restoring iptables...")
|
logSys.info("Restoring iptables...")
|
||||||
fireWall.flushBanList(debug)
|
fireWall.flushBanList(conf["debug"])
|
||||||
logSys.info("Exiting...")
|
logSys.info("Exiting...")
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
Loading…
Reference in New Issue