Posts Tagged IIS
Blocking IP addresses by country on IIS shared hosting
On a shared hosting environment you often won’t have access to ban IP addresses on the IIS level and my shared host didn’t offer the Firewall module for Plesk so I had to come up with a programmatic way of blocking large blocks of IPs. You can setup in your web.config file something called a HTTPModule that works before the page is delivered to the client computer. For this sample I added a key and value to my web.config file that holds my comma separated IP list that I want to block. Since I’m running a site that is focused on the United States there isn’t much overlap on the /24 block area 255.255.255.* so I am only checking the first 3 digit blocks for matches. When a request comes in IpTwentyFourBlockingModule will check the users IP address against the key value blockiptwentyfour to see if there is a match and if it is a match will return 403 forbidden to the client browser, banned!
Coming up with a IP list is another problem. I found IP Location Tools that gives out an API that generates a updated list of IPs for a given country. The problem is the list gets broken out into IP blocks other than /24, you’ll see all ranges of IP blocks that get very complicated very fast and more than I wanted to try and pull off in a days work. I wrote a Flash ActionScript 3 application to consume this data and give me a list of unique IPs 255.255.255 that I could then drop in as the value for blockiptwentyfour. I then added IP tracking for new users and have had to ban some rogue /24 blocks that escaped this list but its kept them at bay and more manageable for now. I’ve already had a colleague suggest that this is still only a stopgap at best and I should develop some kind of throttling system to help prevent spam when I’m not around to watch the site like a hawk.
web.config
1 2 3 4 5 6 7 8 9 10 | <configuration> <appSettings> <add key="blockiptwentyfour" value="41.210.29,41.210.28" /> </appSettings> <system.web> <httpModules> <add name="IpTwentyFourBlockingModule" type="IpTwentyFourBlockingModule" /> </httpModules> </system.web> </configuration> |
IpTwentyFourBlockingModule.cs – put this is in your App_Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | #region Using using System; using System.Web; using System.Configuration; using System.Collections.Specialized; #endregion /// <summary> /// Block the response to certain IP addresses /// </summary> public class IpTwentyFourBlockingModule : IHttpModule { #region IHttpModule Members void IHttpModule.Dispose() { // Nothing to dispose; } void IHttpModule.Init(HttpApplication context) { context.BeginRequest += new EventHandler(context_BeginRequest); } #endregion /// <summary> /// Checks the requesting IP address in the collection /// and block the response if it's on the list. /// </summary> private void context_BeginRequest(object sender, EventArgs e) { string ip = HttpContext.Current.Request.UserHostAddress; string[] tempIpArray = ip.Split('.'); string iptwentyfour = tempIpArray[0] + "." + tempIpArray[1] + "." + tempIpArray[2]; if (_IpAdresses.Contains(iptwentyfour)) { HttpContext.Current.Response.StatusCode = 403; HttpContext.Current.Response.End(); } } private static StringCollection _IpAdresses = FillBlockedIps(); /// <summary> /// Retrieves the IP addresses from the web.config /// and adds them to a StringCollection. /// </summary> /// <returns>A StringCollection of IP addresses.</returns> private static StringCollection FillBlockedIps() { StringCollection col = new StringCollection(); string raw = ConfigurationManager.AppSettings.Get("blockiptwentyfour"); foreach (string ip in raw.Split(',')) { col.Add(ip.Trim()); } return col; } } |
collectipaddresses.as
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | import flash.events.*; import flash.net.*; var myRequest:URLRequest = new URLRequest("http://iplocationtools.com/country_query.php?country=CI,SN,GH,NA,NG") var loader:URLLoader = new URLLoader(); loader.dataFormat = URLLoaderDataFormat.TEXT; loader.addEventListener(Event.COMPLETE, handleComplete); loader.load(myRequest); function handleComplete(event:Event):void { var loader:URLLoader = URLLoader(event.target); //trace(loader.data.replace(/\n/g, "|")); var ipArray:Array = loader.data.replace(/\n/g, "|").split("|"); trace(ipArray.length); setTwentyFourBlock(ipArray); } function setTwentyFourBlock(ipArray:Array) { var shortIpArray:Array = new Array(); var lastUniqueIp:String = ""; for each(var ip:String in ipArray) { var tempIpArray:Array = ip.split("."); var stringCurrentIp:String = tempIpArray[0]+"."+tempIpArray[1]+"."+tempIpArray[2]+".0"; if(stringCurrentIp != lastUniqueIp) { lastUniqueIp = stringCurrentIp; shortIpArray.push(stringCurrentIp); } } trace(shortIpArray.length); trace(shortIpArray.join(',')); } |
All of this work has really kept my free online dating site almost spam free for now but I’m adding IP blocks I’ve missed from time to time.