I've written this module ( using a tutorial on the web I can't find now ) to stop unusual requests from clients . it's working as I tested it on local system .
1- but I'm not sure if its logic is fine enough ?
2- another problem is that , it counts requests for non-aspx resources ( images , css , ...) too but it shouldn't . how can I filter request for aspx pages ?
this is the module code :
public class AntiDosModule : IHttpModule
{
const string blockKey = "IsBlocked";
const string reqsKey = "Requests";
public void Dispose()
{ }
public void Init(HttpApplication context)
{
context.BeginRequest += ValidateRequest;
}
private static void ValidateRequest(object sender, EventArgs e)
{
// get configs from web.config
AntiDosModuleSettings setting = AntiDosModuleSettings.GetConfig();
int blockDuration = setting.IPBlockDuration;
// time window in which request are counted e.g 1000 request in 1 minute
int validationTimeWindow = setting.ValidationTimeWindow;
// max requests count in specified time window e.g 1000 request in 1 minute
int maxValidRequests = setting.MaxValidRequests;
string masterKey = setting.MasterKey;
HttpContextBase context = new HttpContextWrapper(HttpContext.Current);
CacheManager cacheMgr = new CacheManager(context, masterKey);
// is client IP blocked
bool IsBlocked = (bool)cacheMgr.GetItem<Boolean>(blockKey);
if (IsBlocked)
{
context.Response.End();
}
// number of requests sent by client till now
IPReqsHint hint = cacheMgr.GetItem<IPReqsHint>(reqsKey) ?? new IPReqsHint();
if (hint.HintCount > maxValidRequests)
{
// block client IP
cacheMgr.AddItem(blockKey, true, blockDuration);
context.Response.End();
}
hint.HintCount++;
if (hint.HintCount == 1)
{
cacheMgr.AddItem(reqsKey, hint, validationTimeWindow);
}
}
}
internal class IPReqsHint
{
public int HintCount { get; set; }
public IPReqsHint()
{
HintCount = 0;
}
}
and this is CacheManager class :
public class CacheManager
{
HttpContextBase context;
string masterKey;
public CacheManager(HttpContextBase context, string masterKey)
{
this.context = context;
this.masterKey = masterKey;
}
public void AddItem(string key, object value, int duration)
{
string finalKey = GenerateFinalKey(key);
context.Cache.Add(
finalKey,
value,
null,
DateTime.Now.AddSeconds(duration),
System.Web.Caching.Cache.NoSlidingExpiration,
System.Web.Caching.CacheItemPriority.Normal,
null);
}
public T GetItem<T>(string key)
{
string finalKey = GenerateFinalKey(key);
var obj = context.Cache[finalKey] ?? default(T);
return (T)obj;
}
string GenerateFinalKey(string key)
{
return masterKey + "-" + context.Request.UserHostAddress + "-" + key;
}
}