mirror of https://github.com/fail2ban/fail2ban
172 lines
4.0 KiB
Python
Executable File
172 lines
4.0 KiB
Python
Executable File
#!/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$
|
|
|
|
__author__ = "Cyril Jaquier"
|
|
__version__ = "$Revision$"
|
|
__date__ = "$Date$"
|
|
__copyright__ = "Copyright (c) 2004 Cyril Jaquier"
|
|
__license__ = "GPL"
|
|
|
|
import posix,sys,os
|
|
import string,re,time
|
|
|
|
from firewall.iptables import Iptables
|
|
|
|
def checkForRoot():
|
|
""" Check for root user.
|
|
"""
|
|
uid = `posix.getuid()`
|
|
if uid == '0':
|
|
return True
|
|
else:
|
|
return False
|
|
|
|
# start: To be removed
|
|
def executeCmd(cmd):
|
|
return #os.system(cmd)
|
|
|
|
def unBanIP(ip):
|
|
iptables = 'iptables -D INPUT -i eth0 -s '+ip+' -j DROP'
|
|
executeCmd(iptables)
|
|
print iptables
|
|
|
|
def banIP(ip):
|
|
iptables = 'iptables -I INPUT 1 -i eth0 -s '+ip+' -j DROP'
|
|
executeCmd(iptables)
|
|
print iptables
|
|
# end:
|
|
|
|
def checkForUnBan(banList, currentTime, banTime):
|
|
""" Check for user to remove from ban list.
|
|
"""
|
|
iterBanList = banList.iteritems()
|
|
for i in range(len(banList)):
|
|
element = iterBanList.next()
|
|
ip = element[0]
|
|
btime = element[1]
|
|
if btime < currentTime-banTime:
|
|
del banList[ip]
|
|
unBanIP(ip)
|
|
print '`->', currentTime
|
|
return banList
|
|
|
|
def checkForBan(retryList, banList, currentTime):
|
|
iterRetry = retryList.iteritems()
|
|
for i in range(len(retryList)):
|
|
element = iterRetry.next()
|
|
retry = element[1][0]
|
|
ip = element[0]
|
|
if element[1][0] > 2 and not banList.has_key(ip):
|
|
banList[ip] = currentTime
|
|
banIP(ip)
|
|
print '`->', currentTime
|
|
return banList
|
|
|
|
def flushBanList(banList):
|
|
iterBanList = banList.iteritems()
|
|
for i in range(len(banList)):
|
|
element = iterBanList.next()
|
|
ip = element[0]
|
|
unBanIP(ip)
|
|
|
|
def parseLogLine(line):
|
|
""" Match sshd failed password log
|
|
"""
|
|
if re.search("Failed password", line):
|
|
matchIP = re.search("(?:\d{1,3}\.){3}\d{1,3}", line)
|
|
return matchIP
|
|
|
|
if __name__ == "__main__":
|
|
|
|
# start: For object oriented testing
|
|
f = Iptables()
|
|
f.banIP('11', 1231)
|
|
f.banIP('13', 1232)
|
|
f.banIP('13', 1233)
|
|
f.unBanIP('11')
|
|
f.viewBanList()
|
|
f.flushBanList()
|
|
# end:
|
|
|
|
if not checkForRoot():
|
|
print "You must be root."
|
|
#sys.exit(-1)
|
|
|
|
logPath = './log-test/test'
|
|
banTime = 60
|
|
ignoreIPs = '127.0.0.1'
|
|
|
|
lastModTime = 0
|
|
banList = dict()
|
|
while True:
|
|
try:
|
|
currentTime = time.time()
|
|
|
|
banList = checkForUnBan(banList, currentTime, banTime)
|
|
|
|
try:
|
|
pwdFailStats = os.stat(logPath)
|
|
except OSError:
|
|
print "Unable to get stat on", logPath
|
|
sys.exit(-1)
|
|
|
|
if lastModTime == pwdFailStats.st_mtime:
|
|
time.sleep(1)
|
|
continue
|
|
|
|
print logPath, 'has been modified'
|
|
lastModTime = pwdFailStats.st_mtime
|
|
|
|
try:
|
|
pwdfail = open(logPath)
|
|
except OSError:
|
|
print "Unable to open", logPath
|
|
sys.exit(-1)
|
|
|
|
retryList = dict()
|
|
for line in pwdfail.readlines():
|
|
match = parseLogLine(line)
|
|
if match:
|
|
ip = match.group()
|
|
date = list(time.strptime(line[0:15], "%b %d %H:%M:%S"))
|
|
date[0] = time.gmtime()[0]
|
|
unixTime = time.mktime(date)
|
|
if unixTime < currentTime-banTime:
|
|
continue
|
|
if re.search(ip, ignoreIPs):
|
|
print 'Ignore ', ip
|
|
continue
|
|
print 'Found', ip, 'at', unixTime
|
|
if retryList.has_key(`ip`):
|
|
retryList[`ip`] = (retryList[`ip`][0]+1,unixTime)
|
|
else:
|
|
retryList[`ip`] = (1,unixTime)
|
|
|
|
pwdfail.close()
|
|
|
|
banList = checkForBan(retryList, banList, currentTime)
|
|
except KeyboardInterrupt:
|
|
print 'Restoring iptables...'
|
|
flushBanList(banList)
|
|
print 'Exiting...'
|
|
sys.exit(0)
|