- 0.7.0 soon

git-svn-id: https://fail2ban.svn.sourceforge.net/svnroot/fail2ban/trunk@251 a942ae1a-1317-0410-a47c-b1dcaea8d605
0.x
Cyril Jaquier 2006-07-16 21:35:08 +00:00
parent 12c222bd1c
commit 7048e19995
18 changed files with 276 additions and 63 deletions

View File

@ -32,9 +32,10 @@ logSys = logging.getLogger("fail2ban.client.config")
class ActionReader(ConfigReader):
def __init__(self, file, name):
def __init__(self, action, name):
ConfigReader.__init__(self)
self.file = file
self.file = action[0]
self.cInfo = action[1]
self.name = name
def setFile(self, file):
@ -58,7 +59,12 @@ class ActionReader(ConfigReader):
["string", "actioncheck", ""],
["string", "actionban", ""],
["string", "actionunban", ""]]
self.opts = ConfigReader.getOptions(self, "DEFAULT", opts, pOpts)
self.opts = ConfigReader.getOptions(self, "Definition", opts, pOpts)
if self.has_section("Init"):
for opt in self.options("Init"):
if not self.cInfo.has_key(opt):
self.cInfo[opt] = self.get("Init", opt)
def convert(self):
head = ["set", self.name]
@ -75,5 +81,10 @@ class ActionReader(ConfigReader):
stream.append(head + ["actionban", self.file, self.opts[opt]])
elif opt == "actionunban":
stream.append(head + ["actionunban", self.file, self.opts[opt]])
# cInfo
if self.cInfo:
for p in self.cInfo:
stream.append(head + ["setcinfo", self.file, p, self.cInfo[p]])
return stream

View File

@ -40,7 +40,7 @@ class Fail2banReader(ConfigReader):
def getOptions(self):
opts = [["int", "loglevel", 1]]
self.opts = ConfigReader.getOptions(self, "DEFAULT", opts)
self.opts = ConfigReader.getOptions(self, "Definition", opts)
def convert(self):
stream = list()

View File

@ -59,7 +59,7 @@ class FilterReader(ConfigReader):
["string", "failregex", ""],
["int", "maxtime", 600],
["int", "maxretry", 3]]
self.opts = ConfigReader.getOptions(self, "DEFAULT", opts, pOpts)
self.opts = ConfigReader.getOptions(self, "Definition", opts, pOpts)
def convert(self):
stream = list()

View File

@ -24,7 +24,7 @@ __date__ = "$Date: 2005/11/20 17:07:47 $"
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
__license__ = "GPL"
import logging
import logging, re
from configreader import ConfigReader
from filterreader import FilterReader
from actionreader import ActionReader
@ -68,7 +68,8 @@ class JailReader(ConfigReader):
# Read action
for act in self.opts["action"].split():
action = ActionReader(act, self.name)
splitAct = JailReader.splitAction(act)
action = ActionReader(splitAct, self.name)
action.read()
action.getOptions(self.opts)
self.actions.append(action)
@ -84,4 +85,13 @@ class JailReader(ConfigReader):
for action in self.actions:
stream.extend(action.convert())
return stream
@staticmethod
def splitAction(action):
m = re.match("^(\w+)(?:\[(.*)\])?$", action)
d = dict()
if m.group(2) <> None:
for param in m.group(2).split(','):
p = param.split('=')
d[p[0]] = p[1]
return [m.group(1), d]

View File

@ -42,7 +42,7 @@ class JailsReader(ConfigReader):
def getOptions(self):
opts = []
self.opts = ConfigReader.getOptions(self, "DEFAULT", opts)
self.opts = ConfigReader.getOptions(self, "Definition", opts)
for sec in self.sections():
jail = JailReader(sec)

View File

@ -1,18 +1,11 @@
[DEFAULT]
name = temporary
# Option: protocol
# Notes.: internally used by config reader for interpolations.
# Values: [ tcp | udp | icmp | all ] Default: tcp
#
protocol = tcp
[Definition]
# Option: fwstart
# Notes.: command executed once at the start of Fail2Ban.
# Values: CMD Default:
#
actionstart = touch /tmp/fail2ban.dummy
echo "<init>" >> /tmp/fail2ban.dummy
# Option: fwend
# Notes.: command executed once at the end of Fail2Ban
@ -48,3 +41,7 @@ actionban = echo "+<ip>" >> /tmp/fail2ban.dummy
# Default: iptables -D INPUT -s <ip> -j DROP
#
actionunban = echo "-<ip>" >> /tmp/fail2ban.dummy
[Init]
init = 123

View File

@ -1,6 +1,4 @@
[DEFAULT]
name = temporary
[Definition]
# Option: protocol
# Notes.: internally used by config reader for interpolations.
@ -18,13 +16,13 @@ actionstart = touch /tmp/fail2ban.foo
# Notes.: command executed once at the end of Fail2Ban
# Values: CMD Default:
#
actionstop = rm /tmp/fail2ban.foo
actionstop = rm -f /tmp/fail2ban.foo
# Option: fwcheck
# Notes.: command executed once before each fwban command
# Values: CMD Default:
#
actioncheck =
actioncheck = [ -e "/tmp/fail2ban.foo" ]
# Option: fwban
# Notes.: command executed when banning an IP. Take care that the

View File

@ -0,0 +1,59 @@
[Definition]
# Option: fwstart
# Notes.: command executed once at the start of Fail2Ban.
# Values: CMD Default:
#
actionstart = touch <tmpfile>
# Option: fwend
# Notes.: command executed once at the end of Fail2Ban
# Values: CMD Default:
#
actionstop = rm -f <tmpfile>
# Option: fwcheck
# Notes.: command executed once before each fwban command
# Values: CMD Default:
#
actioncheck =
# Option: fwban
# Notes.: command executed when banning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# Tags: <ip> IP address
# <failures> number of failures
# <failtime> unix timestamp of the last failure
# <bantime> unix timestamp of the ban time
# Values: CMD
# Default: iptables -I INPUT 1 -s <ip> -j DROP
#
actionban = IP=<ip> &&
echo "ALL: $IP" >> <file>
# Option: fwunban
# Notes.: command executed when unbanning an IP. Take care that the
# command is executed with Fail2Ban user rights.
# Tags: <ip> IP address
# <bantime> unix timestamp of the ban time
# <unbantime> unix timestamp of the unban time
# Values: CMD
# Default: iptables -D INPUT -s <ip> -j DROP
#
actionunban = IP=<ip> &&
grep -v "ALL: $IP" <file> > <tmpfile> &&
mv <tmpfile> <file>
[Init]
# Option: file
# Notes.: hosts.deny file path.
# Values: STR Default: /etc/hosts.deny
#
file = /etc/hosts.deny
# Option: file
# Notes.: hosts.deny temporary file path.
# Values: STR Default: /etc/hostsdeny.failban
#
tmpfile = /tmp/hosts.deny.tmp

View File

@ -1,35 +1,26 @@
[DEFAULT]
name = temporary
port = 22
# Option: protocol
# Notes.: internally used by config reader for interpolations.
# Values: [ tcp | udp | icmp | all ] Default: tcp
#
protocol = tcp
[Definition]
# Option: fwstart
# Notes.: command executed once at the start of Fail2Ban.
# Values: CMD Default:
#
actionstart = iptables -N fail2ban-%(name)s
iptables -A fail2ban-%(name)s -j RETURN
iptables -I INPUT -p %(protocol)s --dport %(port)s -j fail2ban-%(name)s
actionstart = iptables -N fail2ban-<name>
iptables -A fail2ban-<name> -j RETURN
iptables -I INPUT -p <protocol> --dport <port> -j fail2ban-<name>
# Option: fwend
# Notes.: command executed once at the end of Fail2Ban
# Values: CMD Default:
#
actionstop = iptables -D INPUT -p %(protocol)s --dport %(port)s -j fail2ban-%(name)s
iptables -F fail2ban-%(name)s
iptables -X fail2ban-%(name)s
actionstop = iptables -D INPUT -p <protocol> --dport <port> -j fail2ban-<name>
iptables -F fail2ban-<name>
iptables -X fail2ban-<name>
# Option: fwcheck
# Notes.: command executed once before each fwban command
# Values: CMD Default:
#
actioncheck = iptables -L INPUT | grep -q fail2ban-%(name)s
actioncheck = iptables -L INPUT | grep -q fail2ban-<name>
# Option: fwban
# Notes.: command executed when banning an IP. Take care that the
@ -41,7 +32,7 @@ actioncheck = iptables -L INPUT | grep -q fail2ban-%(name)s
# Values: CMD
# Default: iptables -I INPUT 1 -s <ip> -j DROP
#
actionban = iptables -I fail2ban-%(name)s 1 -s <ip> -j DROP
actionban = iptables -I fail2ban-<name> 1 -s <ip> -j DROP
# Option: fwunban
# Notes.: command executed when unbanning an IP. Take care that the
@ -52,4 +43,22 @@ actionban = iptables -I fail2ban-%(name)s 1 -s <ip> -j DROP
# Values: CMD
# Default: iptables -D INPUT -s <ip> -j DROP
#
actionunban = iptables -D fail2ban-%(name)s -s <ip> -j DROP
actionunban = iptables -D fail2ban-<name> -s <ip> -j DROP
[Init]
# Defaut name of the chain
#
name = default
# Option: port
# Notes.: specifies port to monitor
# Values: [ NUM | STRING ] Default:
#
port = ssh
# Option: protocol
# Notes.: internally used by config reader for interpolations.
# Values: [ tcp | udp | icmp | all ] Default: tcp
#
protocol = tcp

View File

@ -1,4 +1,4 @@
[DEFAULT]
[Definition]
loglevel = 3

View File

@ -0,0 +1,35 @@
[Definition]
# Option: maxretry
# Notes.: number of failures before IP gets banned.
# Values: NUM Default: 5
#
maxretry = 5
# Option: logfile
# Notes.: logfile to monitor.
# Values: FILE Default: /var/log/httpd/access_log
#
logfile = /var/log/httpd/access_log
# Option: timeregex
# Notes.: regex to match timestamp in Apache logfile. For TAI64N format,
# use timeregex = @[0-9a-f]{24}
# Values: [Wed Jan 05 15:08:01 2005]
# Default: \S{3} \S{3} \d{2} \d{2}:\d{2}:\d{2} \d{4}
#
timeregex = \S{3} \S{3} \d{2} \d{2}:\d{2}:\d{2} \d{4}
# Option: timepattern
# Notes.: format used in "timeregex" fields definition. Note that '%' must be
# escaped with '%' (see http://rgruet.free.fr/PQR2.3.html#timeModule).
# For TAI64N format, use timepattern = tai64n
# Values: TEXT Default: %%a %%b %%d %%H:%%M:%%S %%Y
#
timepattern = %%a %%b %%d %%H:%%M:%%S %%Y
# Option: failregex
# Notes.: regex to match the password failure messages in the logfile.
# Values: TEXT Default: authentication failure|user .* not found
#
failregex = authentication failure|user .* not found

View File

@ -1,12 +1,16 @@
[DEFAULT]
[Definition]
maxretry = 22
# Option: maxretry
# Notes.: number of failures before IP gets banned.
# Values: NUM Default: 5
#
maxretry = 5
# Option: logpath
# Notes.: logfile to monitor.
# Values: FILE Default: /var/log/secure
#
logpath = testcases/files/testcase01.log
logpath = /var/log/secure
# Option: timeregex
# Notes.: regex to match timestamp in SSH logfile. For TAI64N format,

View File

@ -0,0 +1,33 @@
[Definition]
# Option: maxretry
# Notes.: number of failures before IP gets banned.
# Values: NUM Default: 5
#
maxretry = 5
# Option: logfile
# Notes.: logfile to monitor.
# Values: FILE Default: /var/log/vsftpd.log
#
logfile = /var/log/vsftpd.log
# Option: timeregex
# Notes.: regex to match timestamp in VSFTPD logfile.
# Values: [Mar 7 17:53:28]
# Default: \S{3}\s{1,2}\d{1,2} \d{2}:\d{2}:\d{2}
#
timeregex = \S{3}\s{1,2}\d{1,2} \d{2}:\d{2}:\d{2}
# Option: timepattern
# Notes.: format used in "timeregex" fields definition. Note that '%' must be
# escaped with '%' (see http://rgruet.free.fr/PQR2.3.html#timeModule)
# Values: TEXT Default: %%b %%d %%H:%%M:%%S
#
timepattern = %%b %%d %%H:%%M:%%S
# Option: failregex
# Notes.: regex to match the password failures messages in the logfile.
# Values: TEXT Default: Authentication failure|Failed password|Invalid user
#
failregex = FAIL LOGIN

View File

@ -2,18 +2,18 @@
enabled = true
filter = sshd
action = dummy foo
action = hostsdeny[file=/tmp/hosts.deny]
maxretry = 2
bantime = 5
[SSH]
[ssh]
enabled = false
filter = sshd
action = iptables
bantime = 10
[Apache-error]
[apache-error]
enabled = false
filter = apache-error

View File

@ -40,6 +40,7 @@ class Action:
def __init__(self, name):
self.name = name
self.cInfo = dict()
## Command executed in order to initialize the system.
self.actionStart = ''
## Command executed when an IP address gets banned.
@ -58,6 +59,15 @@ class Action:
def getName(self):
return self.name
def setCInfo(self, key, value):
self.cInfo[key] = value
def getCInfo(self, key):
return self.cInfo[key]
def delCInfo(self, key):
del self.cInfo[key]
##
# Set the "start" command.
#
@ -75,8 +85,9 @@ class Action:
def getActionStart(self):
return self.actionStart
def execActionStart(self, aInfo):
return self.executeCmd(self.actionStart, aInfo);
def execActionStart(self):
startCmd = Action.replaceTag(self.actionStart, self.cInfo)
return Action.executeCmd(startCmd)
##
# Set the "ban" command.
@ -96,7 +107,7 @@ class Action:
return self.actionBan
def execActionBan(self, aInfo):
return self.executeCmd(self.actionBan, aInfo);
return self.processCmd(self.actionBan, aInfo);
##
# Set the "unban" command.
@ -116,7 +127,7 @@ class Action:
return self.actionUnban
def execActionUnban(self, aInfo):
return self.executeCmd(self.actionUnban, aInfo);
return self.processCmd(self.actionUnban, aInfo);
##
# Set the "check" command.
@ -135,9 +146,6 @@ class Action:
def getActionCheck(self):
return self.actionCheck
def execActionCheck(self, aInfo):
return self.executeCmd(self.actionCheck, aInfo);
##
# Set the "stop" command.
#
@ -155,8 +163,9 @@ class Action:
def getActionStop(self):
return self.actionStop
def execActionStop(self, aInfo):
return self.executeCmd(self.actionStop, aInfo);
def execActionStop(self):
stopCmd = Action.replaceTag(self.actionStop, self.cInfo)
return Action.executeCmd(stopCmd)
@staticmethod
def replaceTag(query, aInfo):
@ -169,20 +178,38 @@ class Action:
string = string.replace("<br>", '\n')
return string
@staticmethod
def executeCmd(cmd, aInfo = None):
def processCmd(self, cmd, aInfo = None):
""" Executes an OS command.
"""
if cmd == "":
logSys.debug("Nothing to do")
return True
checkCmd = Action.replaceTag(self.actionCheck, self.cInfo)
if not Action.executeCmd(checkCmd):
logSys.error("Invariant check failed. Trying to restore a sane" +
" environment")
stopCmd = Action.replaceTag(self.actionStop, self.cInfo)
Action.executeCmd(stopCmd)
startCmd = Action.replaceTag(self.actionStart, self.cInfo)
Action.executeCmd(startCmd)
if not Action.executeCmd(checkCmd):
logSys.fatal("Unable to restore environment")
return False
# Replace tags
if not aInfo == None:
realCmd = Action.replaceTag(cmd, aInfo)
else:
realCmd = cmd
# Replace static fields
realCmd = Action.replaceTag(realCmd, self.cInfo)
return Action.executeCmd(realCmd)
@staticmethod
def executeCmd(realCmd):
logSys.debug(realCmd)
retval = os.system(realCmd)
#if not retval == 0:
@ -192,4 +219,5 @@ class Action:
return True
else:
logSys.error("%s returned %x" % (realCmd, retval))
return False
return False

View File

@ -103,7 +103,7 @@ class Actions(JailThread):
def run(self):
for action in self.actions:
action.execActionStart(None)
action.execActionStart()
self.setActive(True)
while self.isActive():
if not self.isIdle:
@ -116,7 +116,7 @@ class Actions(JailThread):
time.sleep(self.sleepTime)
self.flushBan()
for action in self.actions:
action.execActionStop(None)
action.execActionStop()
logSys.debug(self.jail.getName() + ": action terminated")
return True

View File

@ -181,6 +181,24 @@ class Server:
else:
raise ServerUnknownJail(name)
def setCInfo(self, name, action, key, value):
if self.jails.has_key(name):
self.jails[name].getAction().getAction(action).setCInfo(key, value)
else:
raise ServerUnknownJail(name)
def getCInfo(self, name, action, key):
if self.jails.has_key(name):
return self.jails[name].getAction().getAction(action).getCInfo(key)
else:
raise ServerUnknownJail(name)
def delCInfo(self, name, action, key):
if self.jails.has_key(name):
self.jails[name].getAction().getAction(action).delCInfo(key)
else:
raise ServerUnknownJail(name)
def setBanTime(self, name, value):
if self.jails.has_key(name):
self.jails[name].getAction().setBanTime(value)

View File

@ -147,6 +147,17 @@ class Transmitter:
elif action[1] == "delaction":
self.server.delAction(name, value)
return None
elif action[1] == "setcinfo":
act = action[2]
key = action[3]
value = action[4]
self.server.setCInfo(name, act, key, value)
return self.server.getCInfo(name, act, key)
elif action[1] == "delcinfo":
act = action[2]
key = action[3]
self.server.delCInfo(name, act, key)
return None
elif action[1] == "actionstart":
act = action[2]
value = action[3]