Potty Little Details

Just another WordPress.com weblog

IP Blacklisting

leave a comment »

I do not have direct access to the IIS administrative console at my ISP, so when I wanted to block some troublesome IP addresses that were spamming my blog, I needed a software solution that would run in ASP.NET. An HttpModule was the easiest solution to write—it is easily configurable and easily added to my ASP.NET application without recompiling. This module will listen on the BeginRequest event that fires for every HttpRequest that comes into the configured application. Because modules like this listen on every request, you’ll want to be especially diligent about the work you do and get out of the module as soon as possible.
An IP Blacklisting HttpModule
using System;
using System.Text.RegularExpressions;
using System.IO;
using System.Web;
using System.Web.Caching;
using System.Collections.Specialized;

namespace MVPHacks
{
public class IPBlackList : IHttpModule
{
public IPBlackList(){}

void IHttpModule.Dispose(){}

void IHttpModule.Init(HttpApplication context)
{
context.BeginRequest += new EventHandler(this.HandleBeginRequest);
}

const string FILE = “~/blockedips.config”;
const string CACHEKEY = “blockedips”;

public static StringDictionary GetBlockedIPs(HttpContext context)
{
StringDictionary ips = (StringDictionary)context.Cache[CACHEKEY];
if (ips == null)
{
ips = GetBlockedIPs(GetBlockedIPsFile(context));
context.Cache.Insert(CACHEKEY, ips,
new CacheDependency(GetBlockedIPsFile(context)));
}
return ips;
}

private static string BlockedIPFileName = null;
private static object blockedIPFileNameObject = new object();
public static string GetBlockedIPsFile(HttpContext context)
{
if (BlockedIPFileName != null) return BlockedIPFileName;
lock(blockedIPFileNameObject)
{
if (BlockedIPFileName == null)
{
BlockedIPFileName = context.Server.MapPath(FILE);
}
}
return BlockedIPFileName;
}

public static StringDictionary GetBlockedIPs(string configPath)
{
StringDictionary retval = new StringDictionary();
using (StreamReader sr = new StreamReader(configPath))
{
String line;
while ((line = sr.ReadLine()) != null)
{
line = line.Trim();
if (line.Length != 0)
{
if (retval.ContainsKey(line) == false)
{
retval.Add(line, null);
}
}
}
}
return retval;
}

private void HandleBeginRequest( object sender, EventArgs evargs )
{
HttpApplication app = sender as HttpApplication;
if ( app != null )
{
string IPAddr = app.Context.Request.ServerVariables[“REMOTE_ADDR”];
if (IPAddr == null || IPAddr.Length == 0)
{
return;
}

//Block the PHPBB worm and other WGET-based worms
if (app.Context.Request.QueryString[“rush”] != null
||
app.Context.Request.RawUrl.IndexOf(“wget”) != -1)
{
app.Context.Response.StatusCode = 404;
app.Context.Response.SuppressContent = true;
app.Context.Response.End();
return;
}

StringDictionary badIPs = GetBlockedIPs(app.Context);
if (badIPs != null && badIPs.ContainsKey(IPAddr))
{
app.Context.Response.StatusCode = 404;
app.Context.Response.SuppressContent = true;
app.Context.Response.End();
return;
}
}
}
}
}
With this HttpModule, now I can upload a text file called blockedips.txt with one IP address per line to my site and the changes are recognized immediately. The IP addresses are stored in ASP.NET’s cache as a StringDictionary and the cached object is invalidated if the underlying file is updated.

Notice that this module returns a 404 when an IP address is blocked. I wanted to discourage the spammers as much as possible so I decided to fool them into thinking my website had no content at all:

The assembly’s qualified name (QN) for this or any HttpModule is added to the httpModules section of the application’s web.config. A QN consists of the full namespace and class name, a comma, and then the actual assembly filename without the .dll extension.

Advertisements

Written by oneil

September 10, 2008 at 2:10 pm

Posted in ASP DOT NET

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: