#RequestFilter.py #This servlet filter will block requests from the client #temporarily if it exceeds a specified limit within a #specified time from javax import servlet from javax.servlet import http import time , thread , sys #To Keep track of Blocked IP addresses and to track all Requests block_list = {} Request_tracker = {} done = 0 #Number of Requests which are allowed within a particular time (in seconds) #If there are more requests within time TIME , that client IP is #blocked for BLOCK_TIME seconds MAX_REQUESTS = 20 TIME = 10 BLOCK_TIME = 60 CLEAN_UP_TIME = 20 def clean_tables(): global block_list , Request_tracker #This function is called as a thread from the main routine #Its function is to frequently clean up the block_list and Request_tracker #from unwanted entries.This is done to avoid #outdated entries in both the tables since these tables #are altered only when the client makes a request while 1: time.sleep(CLEAN_UP_TIME) print "Cleaner thread Invoked at " , time.ctime(time.time()) try: #Clean up Entries in Request_tracker list if #there is no client request for a time > TIME + 10 #i.e this entry is timed out for entries in Request_tracker.keys(): if (time.time() - Request_tracker[entries][1] > TIME + 10 ): del Request_tracker[entries] print "Deleted entry " , entries , " from Request_tracker " except: pass try: #Clean up Entries in block_list if #there are no client requests for a time >BLOCK_TIME + 10 #i.e this entry is timed out for entries in block_list.keys(): if (time.time() - block_list[entries] > BLOCK_TIME + 10 ): del block_list[entries] print "Deleted entry " , entries , " from block_list" except: pass def Track_Request (client_request): global block_list , Request_tracker , done #Global variables are used so that they are in memory #even after the filter processes a client's request #and exits.This is useful for Subsequent processing done = 0 #If the request_tracker has Client's IP as key #then track the request if Request_tracker.has_key(client_request): #Increment the number of connection attempts Request_tracker[client_request][0] = Request_tracker[client_request][0] + 1 if ( time.time() - Request_tracker[client_request][1] >= TIME ): #If the difference between the current time and the #time of last request exceeds the specified TIME limit if (Request_tracker[client_request][0] > MAX_REQUESTS): #If more than MAX_REQUESTS requests are made within that #time,add that IP address to the block_list block_list[client_request] = time.time() #Time at which the address is added to the block_list del Request_tracker[client_request] #Delete that entry from Request_tracker as it is #already added to block_list return 1 else: #If the client has not made requests > MAX_REQUESTS #within time TIME , remove that client's IP address #from the block list as it is a legitimate IP del Request_tracker[client_request] return 0 else: if (Request_tracker[client_request][0] > MAX_REQUESTS): #If the number of requests exceeds MAX_REQUESTS within time #TIME,then add the client's IP to the block list block_list[client_request] = time.time() del Request_tracker[client_request] return 1 else: return 0 #New client accessing the server #Keep track of the IP list = [ 1 , time.time() ] Request_tracker[client_request] = list return 0 def check_block_list (client_request): global block_list , Request_tracker #Use global variables (associative arrays) #block list and Request_tracker if (block_list.has_key( client_request )): #If the block_list contains client's IP as key #If the difference between the current time #and the time at which the IP address was blocked #exceeds BLOCK_TIME , that IP address is released #from the block_list if ( time.time() - block_list[client_request] > BLOCK_TIME ): del block_list[client_request] return 0 else: return 1 else: return 0 #IP address not in block list class RequestFilter (servlet.Filter): def doFilter(self, req, res,chain): global block_list , Request_tracker done = 0 remote_addr = req.getRemoteAddr() #IP address in block list, access temporarily suspended if check_block_list (remote_addr) == 1: res.sendError(403, "DOS Attempt, temporarily blocked") #Here an error code 403 is used to #indicate temproary blocking of IP done = 1 #Finished processing client's request , exit if done == 0 and Track_Request (remote_addr) == 1: res.sendError(403, "DOS Attempt, IP temporarily blocked ") done = 1 if done == 0: #Legitimate request , access allowed chain.doFilter(req,res) def init(self, config): #Initialize filter print "Request Filter Initialized" #Start a new thread to clean up entries #at frequent intervals thread.start_new_thread(clean_tables,()) def destroy(self): print "Request Filter Destroyed" sys.exit(0)