|
|
@ -25,7 +25,8 @@ __date__ = "$Date$"
|
|
|
|
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
|
|
|
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
|
|
|
__license__ = "GPL"
|
|
|
|
__license__ = "GPL"
|
|
|
|
|
|
|
|
|
|
|
|
import time, sys, getopt, os, string, signal, logging, logging.handlers, copy
|
|
|
|
import time, sys, getopt, os, string, signal, logging, logging.handlers, \
|
|
|
|
|
|
|
|
copy, locale
|
|
|
|
from ConfigParser import *
|
|
|
|
from ConfigParser import *
|
|
|
|
|
|
|
|
|
|
|
|
from version import version
|
|
|
|
from version import version
|
|
|
@ -192,7 +193,7 @@ def main():
|
|
|
|
# Reads the command line options.
|
|
|
|
# Reads the command line options.
|
|
|
|
try:
|
|
|
|
try:
|
|
|
|
cmdOpts = 'hvVbdkc:t:i:r:p:'
|
|
|
|
cmdOpts = 'hvVbdkc:t:i:r:p:'
|
|
|
|
cmdLongOpts = ['help','version']
|
|
|
|
cmdLongOpts = ['help', 'version']
|
|
|
|
optList, args = getopt.getopt(sys.argv[1:], cmdOpts, cmdLongOpts)
|
|
|
|
optList, args = getopt.getopt(sys.argv[1:], cmdOpts, cmdLongOpts)
|
|
|
|
except getopt.GetoptError:
|
|
|
|
except getopt.GetoptError:
|
|
|
|
dispUsage()
|
|
|
|
dispUsage()
|
|
|
@ -212,19 +213,20 @@ def main():
|
|
|
|
confReader.openConf()
|
|
|
|
confReader.openConf()
|
|
|
|
|
|
|
|
|
|
|
|
# Options
|
|
|
|
# Options
|
|
|
|
optionValues = (["bool", "background", False],
|
|
|
|
optionValues = (["bool", "background", False],
|
|
|
|
["str", "logtargets", "/var/log/fail2ban.log"],
|
|
|
|
["str", "logtargets", "/var/log/fail2ban.log"],
|
|
|
|
["str", "syslog-target", "/dev/log"],
|
|
|
|
["str", "syslog-target", "/dev/log"],
|
|
|
|
["int", "syslog-facility", 1],
|
|
|
|
["int", "syslog-facility", 1],
|
|
|
|
["str", "pidlock", "/var/run/fail2ban.pid"],
|
|
|
|
["str", "pidlock", "/var/run/fail2ban.pid"],
|
|
|
|
["int", "maxfailures", 5],
|
|
|
|
["str", "locale", ""],
|
|
|
|
["int", "bantime", 600],
|
|
|
|
["int", "maxfailures", 5],
|
|
|
|
["int", "findtime", 600],
|
|
|
|
["int", "bantime", 600],
|
|
|
|
["str", "ignoreip", ""],
|
|
|
|
["int", "findtime", 600],
|
|
|
|
["int", "polltime", 1],
|
|
|
|
["str", "ignoreip", ""],
|
|
|
|
["str", "cmdstart", ""],
|
|
|
|
["int", "polltime", 1],
|
|
|
|
["str", "cmdend", ""],
|
|
|
|
["str", "cmdstart", ""],
|
|
|
|
["int", "reinittime", 100],
|
|
|
|
["str", "cmdend", ""],
|
|
|
|
|
|
|
|
["int", "reinittime", 100],
|
|
|
|
["int", "maxreinits", 100])
|
|
|
|
["int", "maxreinits", 100])
|
|
|
|
|
|
|
|
|
|
|
|
# Gets global configuration options
|
|
|
|
# Gets global configuration options
|
|
|
@ -236,6 +238,14 @@ def main():
|
|
|
|
# PID lock
|
|
|
|
# PID lock
|
|
|
|
pidLock.setPath(conf["pidlock"])
|
|
|
|
pidLock.setPath(conf["pidlock"])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Set the LC_TIME with the user's default setting
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
|
|
|
logSys.info("Setting LC_TIME locale option to '%s'"%conf["locale"])
|
|
|
|
|
|
|
|
locale.setlocale(locale.LC_TIME, conf["locale"])
|
|
|
|
|
|
|
|
except Exception:
|
|
|
|
|
|
|
|
logSys.error("Unable to set locale to '%s'"%conf["locale"])
|
|
|
|
|
|
|
|
sys.exit(-1)
|
|
|
|
|
|
|
|
|
|
|
|
# Now we can kill properly a running instance if needed
|
|
|
|
# Now we can kill properly a running instance if needed
|
|
|
|
if conf["kill"]:
|
|
|
|
if conf["kill"]:
|
|
|
|
pid = pidLock.exists()
|
|
|
|
pid = pidLock.exists()
|
|
|
@ -270,7 +280,7 @@ def main():
|
|
|
|
# a socket (file, so it starts with /)
|
|
|
|
# a socket (file, so it starts with /)
|
|
|
|
# or hostname
|
|
|
|
# or hostname
|
|
|
|
# or hostname:port
|
|
|
|
# or hostname:port
|
|
|
|
syslogtargets = re.findall("(/[\w/]*)|([^/ ][^: ]*)(:(\d+)){,1}",
|
|
|
|
syslogtargets = re.findall("(/[\w/]*)|([^/ ][^: ]*)(:(\d+)){,1}",
|
|
|
|
conf["syslog-target"])
|
|
|
|
conf["syslog-target"])
|
|
|
|
# we are waiting for a single match
|
|
|
|
# we are waiting for a single match
|
|
|
|
syslogtargets = syslogtargets[0]
|
|
|
|
syslogtargets = syslogtargets[0]
|
|
|
@ -284,7 +294,7 @@ def main():
|
|
|
|
if len(syslogtargets) == 0: # everything default
|
|
|
|
if len(syslogtargets) == 0: # everything default
|
|
|
|
hdlr = logging.handlers.SysLogHandler()
|
|
|
|
hdlr = logging.handlers.SysLogHandler()
|
|
|
|
else:
|
|
|
|
else:
|
|
|
|
if not ( syslogtargets[0] == "" ): # got socket
|
|
|
|
if not (syslogtargets[0] == ""): # got socket
|
|
|
|
syslogtarget = syslogtargets[0]
|
|
|
|
syslogtarget = syslogtargets[0]
|
|
|
|
else: # got hostname and maybe a port
|
|
|
|
else: # got hostname and maybe a port
|
|
|
|
if syslogtargets[3] == "": # no port specified
|
|
|
|
if syslogtargets[3] == "": # no port specified
|
|
|
@ -326,7 +336,9 @@ def main():
|
|
|
|
"ONLY DISPLAYED IN THE LOG MESSAGES")
|
|
|
|
"ONLY DISPLAYED IN THE LOG MESSAGES")
|
|
|
|
|
|
|
|
|
|
|
|
# Ignores IP list
|
|
|
|
# Ignores IP list
|
|
|
|
ignoreIPList = conf["ignoreip"].split(' ')
|
|
|
|
# and filter out empty entries. Otherwise
|
|
|
|
|
|
|
|
# WARNING: is not a valid IP address
|
|
|
|
|
|
|
|
ignoreIPList = filter(None, conf["ignoreip"].split(' '))
|
|
|
|
|
|
|
|
|
|
|
|
# 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.
|
|
|
@ -352,15 +364,15 @@ def main():
|
|
|
|
logSys.debug("MaxFailure is " + `conf["maxfailures"]`)
|
|
|
|
logSys.debug("MaxFailure is " + `conf["maxfailures"]`)
|
|
|
|
|
|
|
|
|
|
|
|
# Options
|
|
|
|
# Options
|
|
|
|
optionValues = (["bool", "enabled", False],
|
|
|
|
optionValues = (["bool", "enabled", False],
|
|
|
|
["str", "host", "localhost"],
|
|
|
|
["str", "host", "localhost"],
|
|
|
|
["int", "port", "25"],
|
|
|
|
["int", "port", "25"],
|
|
|
|
["str", "from", "root"],
|
|
|
|
["str", "from", "root"],
|
|
|
|
["str", "to", "root"],
|
|
|
|
["str", "to", "root"],
|
|
|
|
["str", "user", ''],
|
|
|
|
["str", "user", ''],
|
|
|
|
["str", "password", ''],
|
|
|
|
["str", "password", ''],
|
|
|
|
["bool", "localtime", False],
|
|
|
|
["bool", "localtime", False],
|
|
|
|
["str", "subject", "[Fail2Ban] Banned <ip>"],
|
|
|
|
["str", "subject", "[Fail2Ban] Banned <ip>"],
|
|
|
|
["str", "message", "Fail2Ban notification"])
|
|
|
|
["str", "message", "Fail2Ban notification"])
|
|
|
|
|
|
|
|
|
|
|
|
# Gets global configuration options
|
|
|
|
# Gets global configuration options
|
|
|
@ -378,18 +390,18 @@ def main():
|
|
|
|
logSys.debug("to: " + mailConf["to"] + " from: " + mailConf["from"])
|
|
|
|
logSys.debug("to: " + mailConf["to"] + " from: " + mailConf["from"])
|
|
|
|
|
|
|
|
|
|
|
|
# Options
|
|
|
|
# Options
|
|
|
|
optionValues = (["bool", "enabled", False],
|
|
|
|
optionValues = (["bool", "enabled", False],
|
|
|
|
["str", "logfile", "/dev/null"],
|
|
|
|
["str", "logfile", "/dev/null"],
|
|
|
|
["int", "maxfailures", conf["maxfailures"]],
|
|
|
|
["int", "maxfailures", conf["maxfailures"]],
|
|
|
|
["int", "bantime", conf["bantime"]],
|
|
|
|
["int", "bantime", conf["bantime"]],
|
|
|
|
["int", "findtime", conf["findtime"]],
|
|
|
|
["int", "findtime", conf["findtime"]],
|
|
|
|
["str", "timeregex", ""],
|
|
|
|
["str", "timeregex", ""],
|
|
|
|
["str", "timepattern", ""],
|
|
|
|
["str", "timepattern", ""],
|
|
|
|
["str", "failregex", ""],
|
|
|
|
["str", "failregex", ""],
|
|
|
|
["str", "fwstart", ""],
|
|
|
|
["str", "fwstart", ""],
|
|
|
|
["str", "fwend", ""],
|
|
|
|
["str", "fwend", ""],
|
|
|
|
["str", "fwban", ""],
|
|
|
|
["str", "fwban", ""],
|
|
|
|
["str", "fwunban", ""],
|
|
|
|
["str", "fwunban", ""],
|
|
|
|
["str", "fwcheck", ""])
|
|
|
|
["str", "fwcheck", ""])
|
|
|
|
|
|
|
|
|
|
|
|
logSys.info("Fail2Ban v" + version + " is running")
|
|
|
|
logSys.info("Fail2Ban v" + version + " is running")
|
|
|
@ -399,10 +411,10 @@ def main():
|
|
|
|
l = confReader.getLogOptions(t, optionValues)
|
|
|
|
l = confReader.getLogOptions(t, optionValues)
|
|
|
|
if l["enabled"]:
|
|
|
|
if l["enabled"]:
|
|
|
|
# Creates a logreader object
|
|
|
|
# Creates a logreader object
|
|
|
|
lObj = LogReader(l["logfile"], l["timeregex"], l["timepattern"],
|
|
|
|
lObj = LogReader(l["logfile"], l["timeregex"], l["timepattern"],
|
|
|
|
l["failregex"], l["maxfailures"], l["findtime"])
|
|
|
|
l["failregex"], l["maxfailures"], l["findtime"])
|
|
|
|
# Creates a firewall object
|
|
|
|
# Creates a firewall object
|
|
|
|
fObj = Firewall(l["fwstart"], l["fwend"], l["fwban"], l["fwunban"],
|
|
|
|
fObj = Firewall(l["fwstart"], l["fwend"], l["fwban"], l["fwunban"],
|
|
|
|
l["fwcheck"], l["bantime"])
|
|
|
|
l["fwcheck"], l["bantime"])
|
|
|
|
# "Name" the firewall
|
|
|
|
# "Name" the firewall
|
|
|
|
fObj.setSection(t)
|
|
|
|
fObj.setSection(t)
|
|
|
@ -474,7 +486,7 @@ def main():
|
|
|
|
e = element[1].getFailures()
|
|
|
|
e = element[1].getFailures()
|
|
|
|
for key in e.iterkeys():
|
|
|
|
for key in e.iterkeys():
|
|
|
|
if element[3].has_key(key):
|
|
|
|
if element[3].has_key(key):
|
|
|
|
element[3][key] = (element[3][key][0] + e[key][0],
|
|
|
|
element[3][key] = (element[3][key][0] + e[key][0],
|
|
|
|
e[key][1])
|
|
|
|
e[key][1])
|
|
|
|
else:
|
|
|
|
else:
|
|
|
|
element[3][key] = (e[key][0], e[key][1])
|
|
|
|
element[3][key] = (e[key][0], e[key][1])
|
|
|
@ -491,9 +503,9 @@ def main():
|
|
|
|
if failTime < unixTime - findTime:
|
|
|
|
if failTime < unixTime - findTime:
|
|
|
|
del element[3][attempt]
|
|
|
|
del element[3][attempt]
|
|
|
|
elif fails[attempt][0] >= element[1].getMaxRetry():
|
|
|
|
elif fails[attempt][0] >= element[1].getMaxRetry():
|
|
|
|
aInfo = {"section": element[0],
|
|
|
|
aInfo = {"section": element[0],
|
|
|
|
"ip": attempt,
|
|
|
|
"ip": attempt,
|
|
|
|
"failures": element[3][attempt][0],
|
|
|
|
"failures": element[3][attempt][0],
|
|
|
|
"failtime": failTime}
|
|
|
|
"failtime": failTime}
|
|
|
|
logSys.info(element[0] + ": " + aInfo["ip"] +
|
|
|
|
logSys.info(element[0] + ": " + aInfo["ip"] +
|
|
|
|
" has " + `aInfo["failures"]` +
|
|
|
|
" has " + `aInfo["failures"]` +
|
|
|
@ -501,7 +513,7 @@ def main():
|
|
|
|
element[2].addBanIP(aInfo, conf["debug"])
|
|
|
|
element[2].addBanIP(aInfo, conf["debug"])
|
|
|
|
# Send a mail notification
|
|
|
|
# Send a mail notification
|
|
|
|
if 'mail' in locals():
|
|
|
|
if 'mail' in locals():
|
|
|
|
mail.sendmail(mailConf["subject"],
|
|
|
|
mail.sendmail(mailConf["subject"],
|
|
|
|
mailConf["message"], aInfo)
|
|
|
|
mailConf["message"], aInfo)
|
|
|
|
del element[3][attempt]
|
|
|
|
del element[3][attempt]
|
|
|
|
except ExternalError, e:
|
|
|
|
except ExternalError, e:
|
|
|
|