summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG13
-rw-r--r--MANIFEST61
-rw-r--r--TODO2
-rw-r--r--client/actionreader.py19
-rw-r--r--client/jailreader.py15
-rw-r--r--config/action.d/dummy.conf2
-rw-r--r--config/action.d/foo.conf50
-rw-r--r--config/fail2ban.conf2
-rw-r--r--config/fail2ban.local3
-rw-r--r--config/jail.conf4
-rwxr-xr-xfail2ban-client7
-rwxr-xr-xfail2ban-server10
-rwxr-xr-xfail2ban-testcases7
-rw-r--r--server/action.py158
-rw-r--r--server/actions.py183
-rw-r--r--server/jail.py4
-rw-r--r--server/server.py60
-rw-r--r--server/transmitter.py44
-rw-r--r--setup.cfg5
-rwxr-xr-xsetup.py84
-rw-r--r--version.py27
21 files changed, 550 insertions, 210 deletions
diff --git a/CHANGELOG b/CHANGELOG
index fd74f7ce..ebcac024 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -4,9 +4,20 @@
|_| \__,_|_|_/___|_.__/\__,_|_||_|
=============================================================
-Fail2Ban (version 0.6.1) 2006/03/16
+Fail2Ban (version 0.7.0) 2006/07/??
=============================================================
+ver. 0.7.0 (2006/07/??) - alpha
+----------
+- Almost a complete rewrite :) Fail2ban design is really
+ better (IMHO). There is a lot of new features
+- Client/Server architecture
+- Multithreading. Each jail has its own threads: one for the
+ log reading and another for the actions
+- Execute several actions
+- Split configuration files. They are more readable and easy
+ to use
+
ver. 0.6.1 (2006/03/16) - stable
----------
- Added permanent banning. Set banTime to a negative value to
diff --git a/MANIFEST b/MANIFEST
index 22731947..22b3eca8 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -1,29 +1,52 @@
README
CHANGELOG
TODO
-setup.cfg
+fail2ban-client
+fail2ban-server
+fail2ban-testcases
+client/__init__.py
+client/actionreader.py
+client/configreader.py
+client/configurator.py
+client/csocket.py
+client/fail2banreader.py
+client/filterreader.py
+client/jailreader.py
+client/jailsreader.py
+server/__init__.py
+server/action.py
+server/actions.py
+server/banmanager.py
+server/banticket.py
+server/faildata.py
+server/failmanager.py
+server/failticket.py
+server/filter.py
+server/jail.py
+server/jailthread.py
+server/server.py
+server/ssocket.py
+server/ticket.py
+server/transmitter.py
setup.py
-version.py
-fail2ban
-fail2ban.py
-firewall/__init__.py
-firewall/firewall.py
-logreader/__init__.py
-logreader/logreader.py
-confreader/__init__.py
-confreader/configreader.py
+testcases/__init__.py
+testcases/banmanagertestcase.py
+testcases/failmanagertestcase.py
+testcases/filtertestcase.py
+testcases/servertestcase.py
utils/__init__.py
utils/dns.py
-utils/process.py
utils/mail.py
-utils/strings.py
utils/pidlock.py
-config/fail2ban.conf.iptables
-config/fail2ban.conf.shorewall
-config/fail2ban.conf.hostsdeny
-config/gentoo-initd
-config/gentoo-confd
-config/redhat-initd
-config/debian-initd
+utils/process.py
+utils/strings.py
+version.py
+config/fail2ban.conf
+config/fail2ban.local
+config/jail.conf
+config/action.d/dummy.conf
+config/action.d/iptables.conf
+config/filter.d/apache-auth.conf
+config/filter.d/sshd.conf
man/fail2ban.8
man/fail2ban.conf.5
diff --git a/TODO b/TODO
index 7c388e85..81ed4bbf 100644
--- a/TODO
+++ b/TODO
@@ -1,2 +1,2 @@
- Don't close socket after a send
-- Multiple actions !!! \ No newline at end of file
+- Refactoring in server.py, actions.py, filter.py \ No newline at end of file
diff --git a/client/actionreader.py b/client/actionreader.py
index 5486b90e..5b620d82 100644
--- a/client/actionreader.py
+++ b/client/actionreader.py
@@ -53,8 +53,7 @@ class ActionReader(ConfigReader):
ConfigReader.read(self, "action.d/" + self.file)
def getOptions(self, pOpts):
- opts = [["string", "bantime", "600"],
- ["string", "actionstart", ""],
+ opts = [["string", "actionstart", ""],
["string", "actionstop", ""],
["string", "actioncheck", ""],
["string", "actionban", ""],
@@ -62,19 +61,19 @@ class ActionReader(ConfigReader):
self.opts = ConfigReader.getOptions(self, "DEFAULT", opts, pOpts)
def convert(self):
+ head = ["set", self.name]
stream = list()
+ stream.append(head + ["addaction", self.file])
for opt in self.opts:
- if opt == "bantime":
- stream.append(["set", self.name, "bantime", self.opts[opt]])
- elif opt == "actionstart":
- stream.append(["set", self.name, "actionstart", self.opts[opt]])
+ if opt == "actionstart":
+ stream.append(head + ["actionstart", self.file, self.opts[opt]])
elif opt == "actionstop":
- stream.append(["set", self.name, "actionstop", self.opts[opt]])
+ stream.append(head + ["actionstop", self.file, self.opts[opt]])
elif opt == "actioncheck":
- stream.append(["set", self.name, "actioncheck", self.opts[opt]])
+ stream.append(head + ["actioncheck", self.file, self.opts[opt]])
elif opt == "actionban":
- stream.append(["set", self.name, "actionban", self.opts[opt]])
+ stream.append(head + ["actionban", self.file, self.opts[opt]])
elif opt == "actionunban":
- stream.append(["set", self.name, "actionunban", self.opts[opt]])
+ stream.append(head + ["actionunban", self.file, self.opts[opt]])
return stream
\ No newline at end of file
diff --git a/client/jailreader.py b/client/jailreader.py
index b839172c..52a62d16 100644
--- a/client/jailreader.py
+++ b/client/jailreader.py
@@ -38,7 +38,7 @@ class JailReader(ConfigReader):
ConfigReader.__init__(self)
self.name = name
self.filter = None
- self.action = None
+ self.actions = list()
def setName(self, value):
self.name = value
@@ -55,7 +55,7 @@ class JailReader(ConfigReader):
def getOptions(self):
opts = [["bool", "enabled", "false"],
["int", "maxretry", None],
- ["int", "bantime", None],
+ ["int", "bantime", 600],
["string", "filter", ""],
["string", "action", ""]]
self.opts = ConfigReader.getOptions(self, self.name, opts)
@@ -67,9 +67,11 @@ class JailReader(ConfigReader):
self.filter.getOptions(self.opts)
# Read action
- self.action = ActionReader(self.opts["action"], self.name)
- self.action.read()
- self.action.getOptions(self.opts)
+ for act in self.opts["action"].split():
+ action = ActionReader(act, self.name)
+ action.read()
+ action.getOptions(self.opts)
+ self.actions.append(action)
def convert(self):
stream = [["add", self.name]]
@@ -79,6 +81,7 @@ class JailReader(ConfigReader):
elif opt == "bantime":
stream.append(["set", self.name, "bantime", self.opts[opt]])
stream.extend(self.filter.convert())
- stream.extend(self.action.convert())
+ for action in self.actions:
+ stream.extend(action.convert())
return stream
\ No newline at end of file
diff --git a/config/action.d/dummy.conf b/config/action.d/dummy.conf
index 1be6253b..9f95871f 100644
--- a/config/action.d/dummy.conf
+++ b/config/action.d/dummy.conf
@@ -1,7 +1,5 @@
[DEFAULT]
-bantime = 1234
-
name = temporary
# Option: protocol
diff --git a/config/action.d/foo.conf b/config/action.d/foo.conf
new file mode 100644
index 00000000..6be4c389
--- /dev/null
+++ b/config/action.d/foo.conf
@@ -0,0 +1,50 @@
+[DEFAULT]
+
+name = temporary
+
+# Option: protocol
+# Notes.: internally used by config reader for interpolations.
+# Values: [ tcp | udp | icmp | all ] Default: tcp
+#
+protocol = tcp
+
+# Option: fwstart
+# Notes.: command executed once at the start of Fail2Ban.
+# Values: CMD Default:
+#
+actionstart = touch /tmp/fail2ban.foo
+
+# Option: fwend
+# Notes.: command executed once at the end of Fail2Ban
+# Values: CMD Default:
+#
+actionstop = rm /tmp/fail2ban.foo
+
+# 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 = echo "+<ip>" >> /tmp/fail2ban.foo
+
+# 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 = echo "-<ip>" >> /tmp/fail2ban.foo
diff --git a/config/fail2ban.conf b/config/fail2ban.conf
index 32a33411..4c29363d 100644
--- a/config/fail2ban.conf
+++ b/config/fail2ban.conf
@@ -1,4 +1,4 @@
[DEFAULT]
-loglevel = 4
+loglevel = 3
diff --git a/config/fail2ban.local b/config/fail2ban.local
index 12b8a6f5..db4574b5 100644
--- a/config/fail2ban.local
+++ b/config/fail2ban.local
@@ -1,4 +1 @@
[DEFAULT]
-
-test = 4567
-prout = fuck you
diff --git a/config/jail.conf b/config/jail.conf
index 66853517..ffa314e1 100644
--- a/config/jail.conf
+++ b/config/jail.conf
@@ -2,9 +2,9 @@
enabled = true
filter = sshd
-action = dummy
+action = dummy foo
maxretry = 2
-#bantime = 10
+bantime = 5
[SSH]
diff --git a/fail2ban-client b/fail2ban-client
index fa395b6e..f88f52bf 100755
--- a/fail2ban-client
+++ b/fail2ban-client
@@ -32,6 +32,7 @@ import sys, string, os, pickle, re, logging, getopt, time
sys.path.insert(1, "/usr/lib/fail2ban")
# Now we can import our modules
+from version import version
from client.csocket import CSocket
from client.configurator import Configurator
@@ -57,7 +58,7 @@ class Fail2banClient:
"""
print "Usage: "+self.argv[0]+" [OPTIONS] <COMMAND>"
print
- print "Fail2Ban v0.7 reads log file that contains password failure report"
+ print "Fail2Ban v" + version + " reads log file that contains password failure report"
print "and bans the corresponding IP addresses using firewall rules."
print
print " -b start in background"
@@ -126,6 +127,10 @@ class Fail2banClient:
self.startServer(self.conf["background"])
# Configure the server
self.processCmd(self.stream)
+ elif cmd[0] == "loadconf" and len(cmd) == 1:
+ self.readConfig()
+ # Configure the server
+ self.processCmd(self.stream)
else:
try:
client = CSocket()
diff --git a/fail2ban-server b/fail2ban-server
index 1d8ece42..c23c528e 100755
--- a/fail2ban-server
+++ b/fail2ban-server
@@ -25,9 +25,15 @@ __date__ = "$Date: 2004/10/10 13:33:40 $"
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
__license__ = "GPL"
+import locale, getopt, logging, sys
+
+# Inserts our own modules path first in the list
+# fix for bug #343821
+sys.path.insert(1, "/usr/lib/fail2ban")
+
+from version import version
from server.server import Server
from utils.process import *
-import locale, getopt, logging, sys
# Gets the instance of the logger.
logSys = logging.getLogger("fail2ban")
@@ -53,7 +59,7 @@ class Fail2banServer:
"""
print "Usage: "+self.argv[0]+" [OPTIONS]"
print
- print "Fail2Ban v0.7 reads log file that contains password failure report"
+ print "Fail2Ban v" + version + " reads log file that contains password failure report"
print "and bans the corresponding IP addresses using firewall rules."
print
print " -b start in background"
diff --git a/fail2ban-testcases b/fail2ban-testcases
index 3c427fe9..59f34461 100755
--- a/fail2ban-testcases
+++ b/fail2ban-testcases
@@ -28,6 +28,11 @@ __license__ = "GPL"
import unittest, logging, sys
+# Inserts our own modules path first in the list
+# fix for bug #343821
+sys.path.insert(1, "/usr/lib/fail2ban")
+
+from version import version
from testcases import filtertestcase
from testcases import servertestcase
from testcases import failmanagertestcase
@@ -40,7 +45,7 @@ stdout = logging.StreamHandler(sys.stdout)
logSys.addHandler(stdout)
logSys.setLevel(logging.FATAL)
-print "Fail2ban test suite. Please wait..."
+print "Fail2ban " + version + " test suite. Please wait..."
tests = unittest.TestSuite()
diff --git a/server/action.py b/server/action.py
index f47fe579..69ce903e 100644
--- a/server/action.py
+++ b/server/action.py
@@ -24,13 +24,10 @@ __date__ = "$Date: 2004/10/10 13:33:40 $"
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
__license__ = "GPL"
-from banmanager import BanManager
-from failmanager import FailManager, FailManagerEmpty
-from jailthread import JailThread
import time, logging, os
# Gets the instance of the logger.
-logSys = logging.getLogger("fail2ban.action")
+logSys = logging.getLogger("fail2ban.actions.action")
##
# Execute commands.
@@ -39,20 +36,10 @@ logSys = logging.getLogger("fail2ban.action")
# action has to be taken. A BanManager take care of the banned IP
# addresses.
-class Action(JailThread):
+class Action:
- ##
- # Constructor.
- #
- # Initialize the filter object with default values.
- # @param jail the jail object
-
- def __init__(self, jail):
- JailThread.__init__(self, jail)
- ## The jail which contains this action.
- self.jail = jail
- ## The ban manager.
- self.banManager = BanManager()
+ def __init__(self, name):
+ self.name = name
## Command executed in order to initialize the system.
self.actionStart = ''
## Command executed when an IP address gets banned.
@@ -64,7 +51,13 @@ class Action(JailThread):
## Command executed in order to stop the system.
self.actionStop = ''
logSys.debug("Created Action")
-
+
+ def setName(self, name):
+ self.name = name
+
+ def getName(self):
+ return self.name
+
##
# Set the "start" command.
#
@@ -82,6 +75,9 @@ class Action(JailThread):
def getActionStart(self):
return self.actionStart
+ def execActionStart(self, aInfo):
+ return self.executeCmd(self.actionStart, aInfo);
+
##
# Set the "ban" command.
#
@@ -99,6 +95,9 @@ class Action(JailThread):
def getActionBan(self):
return self.actionBan
+ def execActionBan(self, aInfo):
+ return self.executeCmd(self.actionBan, aInfo);
+
##
# Set the "unban" command.
#
@@ -116,6 +115,9 @@ class Action(JailThread):
def getActionUnban(self):
return self.actionUnban
+ def execActionUnban(self, aInfo):
+ return self.executeCmd(self.actionUnban, aInfo);
+
##
# Set the "check" command.
#
@@ -133,6 +135,9 @@ class Action(JailThread):
def getActionCheck(self):
return self.actionCheck
+ def execActionCheck(self, aInfo):
+ return self.executeCmd(self.actionCheck, aInfo);
+
##
# Set the "stop" command.
#
@@ -150,104 +155,8 @@ class Action(JailThread):
def getActionStop(self):
return self.actionStop
- ##
- # Set the ban time.
- #
- # @param value the time
-
- def setBanTime(self, value):
- self.banManager.setBanTime(value)
- logSys.info("Set banTime = %s" % value)
-
- ##
- # Get the ban time.
- #
- # @return the time
-
- def getBanTime(self):
- return self.banManager.getBanTime()
-
- ##
- # Main loop.
- #
- # This function is the main loop of the thread. It checks the Jail
- # queue and executes commands when an IP address is banned.
- # @return True when the thread exits nicely
-
- def run(self):
- self.executeCmd(self.actionStart)
- self.setActive(True)
- while self.isActive():
- if not self.isIdle:
- #logSys.debug(self.jail.getName() + ": action")
- ret = self.checkBan()
- if not ret:
- self.checkUnBan()
- time.sleep(self.sleepTime)
- else:
- time.sleep(self.sleepTime)
- self.flushBan()
- self.executeCmd(self.actionStop)
- logSys.debug(self.jail.getName() + ": action terminated")
- return True
-
- ##
- # Check for IP address to ban.
- #
- # Look in the Jail queue for FailTicket. If a ticket is available,
- # it executes the "ban" command and add a ticket to the BanManager.
- # @return True if an IP address get banned
-
- def checkBan(self):
- logSys.debug("Check for IP address to ban")
- ticket = self.jail.getFailTicket()
- if ticket != False:
- aInfo = dict()
- bTicket = BanManager.createBanTicket(ticket)
- aInfo["ip"] = bTicket.getIP()
- logSys.info("Ban %s" % aInfo["ip"])
- self.executeCmd(self.replaceTag(self.actionBan, aInfo))
- self.banManager.addBanTicket(bTicket)
- return True
- return False
-
- ##
- # Check for IP address to unban.
- #
- # Unban IP address which are outdated.
-
- def checkUnBan(self):
- logSys.debug("Check for IP address to unban")
- for ticket in self.banManager.unBanList(time.time()):
- aInfo = dict()
- aInfo["ip"] = ticket.getIP()
- logSys.info("Unban %s" % aInfo["ip"])
- self.executeCmd(self.replaceTag(self.actionUnban, aInfo))
-
- ##
- # Flush the ban list.
- #
- # Unban all IP address which are still in the banning list.
-
- def flushBan(self):
- logSys.debug("Flush ban list")
- for ticket in self.banManager.flushBanList():
- aInfo = dict()
- aInfo["ip"] = ticket.getIP()
- logSys.info("Unban %s" % aInfo["ip"])
- self.executeCmd(self.replaceTag(self.actionUnban, aInfo))
-
- ##
- # Get the status of the filter.
- #
- # Get some informations about the filter state such as the total
- # number of failures.
- # @return a list with tuple
-
- def status(self):
- ret = [("Currently banned", self.banManager.size()),
- ("Total banned", self.banManager.getBanTotal())]
- return ret
+ def execActionStop(self, aInfo):
+ return self.executeCmd(self.actionStop, aInfo);
@staticmethod
def replaceTag(query, aInfo):
@@ -261,21 +170,26 @@ class Action(JailThread):
return string
@staticmethod
- def executeCmd(cmd):
+ def executeCmd(cmd, aInfo = None):
""" Executes an OS command.
"""
if cmd == "":
logSys.debug("Nothing to do")
return True
- logSys.debug(cmd)
- retval = os.system(cmd)
+ # Replace tags
+ if not aInfo == None:
+ realCmd = Action.replaceTag(cmd, aInfo)
+ else:
+ realCmd = cmd
+
+ logSys.debug(realCmd)
+ retval = os.system(realCmd)
#if not retval == 0:
# logSys.error("'" + cmd + "' returned " + `retval`)
# raise Exception("Execution of command '%s' failed" % cmd)
if retval == 0:
return True
else:
- logSys.error("%s returned %x" % (cmd, retval))
- return False
- \ No newline at end of file
+ logSys.error("%s returned %x" % (realCmd, retval))
+ return False \ No newline at end of file
diff --git a/server/actions.py b/server/actions.py
new file mode 100644
index 00000000..707272d4
--- /dev/null
+++ b/server/actions.py
@@ -0,0 +1,183 @@
+# 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: 1.1 $
+
+__author__ = "Cyril Jaquier"
+__version__ = "$Revision: 1.1 $"
+__date__ = "$Date: 2004/10/10 13:33:40 $"
+__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
+__license__ = "GPL"
+
+from banmanager import BanManager
+from failmanager import FailManager, FailManagerEmpty
+from jailthread import JailThread
+from action import Action
+import time, logging, os
+
+# Gets the instance of the logger.
+logSys = logging.getLogger("fail2ban.actions")
+
+##
+# Execute commands.
+#
+# This class reads the failures from the Jail queue and decide if an
+# action has to be taken. A BanManager take care of the banned IP
+# addresses.
+
+class Actions(JailThread):
+
+ ##
+ # Constructor.
+ #
+ # Initialize the filter object with default values.
+ # @param jail the jail object
+
+ def __init__(self, jail):
+ JailThread.__init__(self, jail)
+ ## The jail which contains this action.
+ self.jail = jail
+ self.actions = list()
+ ## The ban manager.
+ self.banManager = BanManager()
+
+ def addAction(self, name):
+ action = Action(name)
+ self.actions.append(action)
+
+ def delAction(self, name):
+ for action in self.actions:
+ if action.getName() == name:
+ self.actions.remove(action)
+ break
+
+ def getAction(self, name):
+ for action in self.actions:
+ if action.getName() == name:
+ return action
+ raise KeyError
+
+ def getLastAction(self):
+ action = self.actions.pop()
+ self.actions.append(action)
+ return action
+
+ ##
+ # Set the ban time.
+ #
+ # @param value the time
+
+ def setBanTime(self, value):
+ self.banManager.setBanTime(value)
+ logSys.info("Set banTime = %s" % value)
+
+ ##
+ # Get the ban time.
+ #
+ # @return the time
+
+ def getBanTime(self):
+ return self.banManager.getBanTime()
+
+ ##
+ # Main loop.
+ #
+ # This function is the main loop of the thread. It checks the Jail
+ # queue and executes commands when an IP address is banned.
+ # @return True when the thread exits nicely
+
+ def run(self):
+ for action in self.actions:
+ action.execActionStart(None)
+ self.setActive(True)
+ while self.isActive():
+ if not self.isIdle:
+ #logSys.debug(self.jail.getName() + ": action")
+ ret = self.checkBan()
+ if not ret:
+ self.checkUnBan()
+ time.sleep(self.sleepTime)
+ else:
+ time.sleep(self.sleepTime)
+ self.flushBan()
+ for action in self.actions:
+ action.execActionStop(None)
+ logSys.debug(self.jail.getName() + ": action terminated")
+ return True
+
+ ##
+ # Check for IP address to ban.
+ #
+ # Look in the Jail queue for FailTicket. If a ticket is available,
+ # it executes the "ban" command and add a ticket to the BanManager.
+ # @return True if an IP address get banned
+
+ def checkBan(self):
+ logSys.debug("Check for IP address to ban")
+ ticket = self.jail.getFailTicket()
+ if ticket != False:
+ aInfo = dict()
+ bTicket = BanManager.createBanTicket(ticket)
+ aInfo["ip"] = bTicket.getIP()
+ logSys.info("Ban %s" % aInfo["ip"])
+ for action in self.actions:
+ action.execActionBan(aInfo)
+ self.banManager.addBanTicket(bTicket)
+ return True
+ return False
+
+ ##
+ # Check for IP address to unban.
+ #
+ # Unban IP address which are outdated.
+
+ def checkUnBan(self):
+ logSys.debug("Check for IP address to unban")
+ for ticket in self.banManager.unBanList(time.time()):
+ aInfo = dict()
+ aInfo["ip"] = ticket.getIP()
+ logSys.info("Unban %s" % aInfo["ip"])
+ for action in self.actions:
+ action.execActionUnban(aInfo)
+
+ ##
+ # Flush the ban list.
+ #
+ # Unban all IP address which are still in the banning list.
+
+ def flushBan(self):
+ logSys.debug("Flush ban list")
+ for ticket in self.banManager.flushBanList():
+ aInfo = dict()
+ aInfo["ip"] = ticket.getIP()
+ logSys.info("Unban %s" % aInfo["ip"])
+ for action in self.actions:
+ action.execActionUnban(aInfo)
+
+ ##
+ # Get the status of the filter.
+ #
+ # Get some informations about the filter state such as the total
+ # number of failures.
+ # @return a list with tuple
+
+ def status(self):
+ ret = [("Currently banned", self.banManager.size()),
+ ("Total banned", self.banManager.getBanTotal())]
+ return ret
+ \ No newline at end of file
diff --git a/server/jail.py b/server/jail.py
index 06b1229d..10dd22df 100644
--- a/server/jail.py
+++ b/server/jail.py
@@ -24,7 +24,7 @@ __date__ = "$Date: 2004/10/10 13:33:40 $"
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
__license__ = "GPL"
-from action import Action
+from actions import Actions
from filter import Filter
import Queue
@@ -35,7 +35,7 @@ class Jail:
self.name = name
self.queue = Queue.Queue()
self.filter = Filter(self)
- self.action = Action(self)
+ self.action = Actions(self)
def setName(self, name):
self.name = name
diff --git a/server/server.py b/server/server.py
index 7ef3886f..31f9d97d 100644
--- a/server/server.py
+++ b/server/server.py
@@ -162,7 +162,25 @@ class Server:
else:
raise ServerUnknownJail(name)
- # Action
+ # Action
+ def addAction(self, name, value):
+ if self.jails.has_key(name):
+ self.jails[name].getAction().addAction(value)
+ else:
+ raise ServerUnknownJail(name)
+
+ def getLastAction(self, name):
+ if self.jails.has_key(name):
+ return self.jails[name].getAction().getLastAction()
+ else:
+ raise ServerUnknownJail(name)
+
+ def delAction(self, name, value):
+ if self.jails.has_key(name):
+ self.jails[name].getAction().delAction(value)
+ else:
+ raise ServerUnknownJail(name)
+
def setBanTime(self, name, value):
if self.jails.has_key(name):
self.jails[name].getAction().setBanTime(value)
@@ -175,63 +193,63 @@ class Server:
else:
raise ServerUnknownJail(name)
- def setActionStart(self, name, value):
+ def setActionStart(self, name, action, value):
if self.jails.has_key(name):
- self.jails[name].getAction().setActionStart(value)
+ self.jails[name].getAction().getAction(action).setActionStart(value)
else:
raise ServerUnknownJail(name)
- def getActionStart(self, name):
+ def getActionStart(self, name, action):
if self.jails.has_key(name):
- return self.jails[name].getAction().getActionStart()
+ return self.jails[name].getAction().getAction(action).getActionStart()
else:
raise ServerUnknownJail(name)
- def setActionStop(self, name, value):
+ def setActionStop(self, name, action, value):
if self.jails.has_key(name):
- self.jails[name].getAction().setActionStop(value)
+ self.jails[name].getAction().getAction(action).setActionStop(value)
else:
raise ServerUnknownJail(name)
- def getActionStop(self, name):
+ def getActionStop(self, name, action):
if self.jails.has_key(name):
- return self.jails[name].getAction().getActionStop()
+ return self.jails[name].getAction().getAction(action).getActionStop()
else:
raise ServerUnknownJail(name)
- def setActionCheck(self, name, value):
+ def setActionCheck(self, name, action, value):
if self.jails.has_key(name):
- self.jails[name].getAction().setActionCheck(value)
+ self.jails[name].getAction().getAction(action).setActionCheck(value)
else:
raise ServerUnknownJail(name)
- def getActionCheck(self, name):
+ def getActionCheck(self, name, action):
if self.jails.has_key(name):
- return self.jails[name].getAction().getActionCheck()
+ return self.jails[name].getAction().getAction(action).getActionCheck()
else:
raise ServerUnknownJail(name)
- def setActionBan(self, name, value):
+ def setActionBan(self, name, action, value):
if self.jails.has_key(name):
- self.jails[name].getAction().setActionBan(value)
+ self.jails[name].getAction().getAction(action).setActionBan(value)
else:
raise ServerUnknownJail(name)
- def getActionBan(self, name):
+ def getActionBan(self, name, action):
if self.jails.has_key(name):
- return self.jails[name].getAction().getActionBan()
+ return self.jails[name].getAction().getAction(action).getActionBan()
else:
raise ServerUnknownJail(name)
- def setActionUnban(self, name, value):
+ def setActionUnban(self, name, action, value):
if self.jails.has_key(name):
- self.jails[name].getAction().setActionUnban(value)
+ self.jails[name].getAction().getAction(action).setActionUnban(value)
else:
raise ServerUnknownJail(name)
- def getActionUnban(self, name):
+ def getActionUnban(self, name, action):
if self.jails.has_key(name):
- return self.jails[name].getAction().getActionUnban()
+ return self.jails[name].getAction().getAction(action).getActionUnban()
else:
raise ServerUnknownJail(name)
diff --git a/server/transmitter.py b/server/transmitter.py
index a3de9a23..c10157c9 100644
--- a/server/transmitter.py
+++ b/server/transmitter.py
@@ -104,7 +104,7 @@ class Transmitter:
self.server.setLogLevel(value)
return self.server.getLogLevel()
# Jail
- if action[1] == "idle":
+ elif action[1] == "idle":
if action[2] == "on":
self.server.setIdleJail(name, True)
elif action[2] == "off":
@@ -140,26 +140,38 @@ class Transmitter:
value = action[2]
self.server.setBanTime(name, int(value))
return self.server.getBanTime(name)
- elif action[1] == "actionstart":
+ elif action[1] == "addaction":
value = action[2]
- self.server.setActionStart(name, value)
- return self.server.getActionStart(name)
+ self.server.addAction(name, value)
+ return self.server.getLastAction(name).getName()
+ elif action[1] == "delaction":
+ self.server.delAction(name, value)
+ return None
+ elif action[1] == "actionstart":
+ act = action[2]
+ value = action[3]
+ self.server.setActionStart(name, act, value)
+ return self.server.getActionStart(name, act)
elif action[1] == "actionstop":
- value = action[2]
- self.server.setActionStop(name, value)
- return self.server.getActionStop(name)
+ act = action[2]
+ value = action[3]
+ self.server.setActionStop(name, act, value)
+ return self.server.getActionStop(name, act)
elif action[1] == "actioncheck":
- value = action[2]
- self.server.setActionCheck(name, value)
- return self.server.getActionCheck(name)
+ act = action[2]
+ value = action[3]
+ self.server.setActionCheck(name, act, value)
+ return self.server.getActionCheck(name, act)
elif action[1] == "actionban":
- value = action[2]
- self.server.setActionBan(name, value)
- return self.server.getActionBan(name)
+ act = action[2]
+ value = action[3]
+ self.server.setActionBan(name, act, value)
+ return self.server.getActionBan(name, act)
elif action[1] == "actionunban":
- value = action[2]
- self.server.setActionUnban(name, value)
- return self.server.getActionUnban(name)
+ act = action[2]
+ value = action[3]
+ self.server.setActionUnban(name, act, value)
+ return self.server.getActionUnban(name, act)
raise Exception("Invalid command (no set action)")
def actionGet(self, action):
diff --git a/setup.cfg b/setup.cfg
new file mode 100644
index 00000000..fba97f88
--- /dev/null
+++ b/setup.cfg
@@ -0,0 +1,5 @@
+[install]
+install-purelib=/usr/lib/fail2ban
+
+[sdist]
+formats=bztar
diff --git a/setup.py b/setup.py
new file mode 100755
index 00000000..f894f3a2
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,84 @@
+#!/usr/bin/env python
+
+# 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: 1.6 $
+
+__author__ = "Cyril Jaquier"
+__version__ = "$Revision: 1.6 $"
+__date__ = "$Date: 2006/01/22 11:08:42 $"
+__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
+__license__ = "GPL"
+
+from distutils.core import setup
+from version import version
+from os.path import isfile, join
+from sys import exit, argv
+
+longdesc = '''
+Fail2Ban scans log files like /var/log/pwdfail or
+/var/log/apache/error_log and bans IP that makes
+too many password failures. It updates firewall rules
+to reject the IP address or executes user defined
+commands.'''
+
+setup(
+ name = "fail2ban",
+ version = version,
+ description = "Ban IPs that make too many password failure",
+ long_description = longdesc,
+ author = "Cyril Jaquier",
+ author_email = "lostcontrol@users.sourceforge.net",
+ url = "http://fail2ban.sourceforge.net",
+ license = "GPL",
+ platforms = "Posix",
+ scripts = ['fail2ban-client', 'fail2ban-server',
+ 'fail2ban-testcases'],
+ py_modules = ['version'],
+ packages = ['client', 'server', 'testcases', 'utils']
+)
+
+# Do some checks after installation
+# Search for obsolete files.
+obsoleteFiles = []
+elements = {"/etc/": ["fail2ban.conf"],
+ "/usr/bin/": ["fail2ban.py"],
+ "/usr/lib/fail2ban/firewall/": ["iptables.py", "ipfwadm.py",
+ "ipfw.py"]}
+for dir in elements:
+ for f in elements[dir]:
+ path = join(dir, f)
+ if isfile(path):
+ obsoleteFiles.append(path)
+if obsoleteFiles:
+ print
+ print "Obsolete files from previous Fail2Ban versions were found on " \
+ "your system."
+ print "Please delete them:"
+ print
+ for f in obsoleteFiles:
+ print "\t" + f
+ print
+
+# Update config file
+if argv[1] == "install":
+ print
+ print "Please do not forget to update your configuration files."
+ print "Use config/ as an example."
+ print
diff --git a/version.py b/version.py
new file mode 100644
index 00000000..d4fe1137
--- /dev/null
+++ b/version.py
@@ -0,0 +1,27 @@
+# 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: 1.15.2.1 $
+
+__author__ = "Cyril Jaquier"
+__version__ = "$Revision: 1.15.2.1 $"
+__date__ = "$Date: 2006/03/19 18:35:21 $"
+__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
+__license__ = "GPL"
+
+version = "0.7.0-SVN"