Internet Security - How to block specific IP numbers on an unmanaged remote hosted IIS website.
marketing space for rent

IIS IP Blocking

Introduction

Internet is the new frontier with new opportunities and opportunists, the later do not always have your nor your websites interests at heart.

If you host your website yourself, then your firewall is the best place to stop unwelcome access. But if you host at a cheap service provider, you have no firewall and no ability to launch and host a firewall. Running PHP, .htaccess is your potential rescue, but IIS does not have an equivalent.

The solution: Include a (dynamic/editable/unloadable) agile manageable IP blocking process in the front-end of your website. Because prevention is better than cure.

Principles

We use an editable XML data file to store the detected unwanted IP addresses. This can be updated via a web service, FTP transfer or connected to automatic IP detection processes.

It must check each and every request to anything on the website, yet be fast and not cause excessive delays and burdens to normal users.

Needs to function as an agile forefront security gateway and if desired log and report all activity detected from the 'known' bad IP addresses.

Requirements

Access to be able to edit the Global.asax file. We need to place some code in the routine that fires when the web application starts up as well as intercept each request being made to the website.

A plain text editor to create and maintain the XML file that contains the IP addresses.

Sample XML Block File
<BlockedIPs>
   <ROW>
      <IP>92.48.77.10</IP>
   </ROW>
   <ROW>
      <IP>200.238.83.49</IP>
   </ROW>
   <ROW>
      <IP>164.151.131.34</IP>
   </ROW>
    <ROW>
      <IP>212.107.104.178</IP>
   </ROW>
</BlockedIPs>

Putting it together

Place the code of the two functions directly into the code section of the Global.ashx file or (preferably) create a seperate class for the IP Blocker.

In the section Application_BeginRequest place the code as shown below

Sub Application_BeginRequest(ByVal sender As Object, ByVal e As EventArgs)

    ' Do not accept out of bounds requests

    If (Request.Path.IndexOf(Chr(92)) >= 0 Or System.IO.Path.GetFullPath(Request.PhysicalPath) <> Request.PhysicalPath) Then

        Throw New HttpException(404, "Not Found")

    End If

    ' Check for Banned IP addresses

    If IpIsBlocked(HttpContext.Current.Request.UserHostAddress) Then

        '// Inform blocked IP of restricted access.

        HttpContext.Current.Response.StatusCode = 403

        HttpContext.Current.Response.Flush()

        HttpContext.Current.Response.End()

        GC.Collect()

    End If

End Sub

public void Application_BeginRequest(object sender, EventArgs e)

{

 // Do not accept out of bounds requests

 if ((Request.Path.IndexOf('\\') >= 0 | System.IO.Path.GetFullPath(Request.PhysicalPath) != Request.PhysicalPath)) {

  throw new HttpException(404, "Not Found");

 }

 // Check for Banned IP addresses

 if (IpIsBlocked(HttpContext.Current.Request.UserHostAddress)) {

  //// Inform blocked IP of restricted access.

  HttpContext.Current.Response.StatusCode = 403;

  HttpContext.Current.Response.Flush();

  HttpContext.Current.Response.End();

  GC.Collect();

 }

}

 

How It Works

Each request to the website is first passed through the 'Application_BeginRequest' method. Here we detect the IP address of the visitor and ask the IpIsBlocked function if it may go through or should be rejected.

Using regular expressions the IP address is first checked to ensure it conforms to the requirements of an IP number structure, else it will return with a false positive to allow the 'IP address'.

The first call to the website will initiate the loading of the data in the XML file into a memory cached dataset, for fast access. Should a complete xxx.xxx.xxx.xxx IP address be received, it will query the data table for its existence. If found, the return instruction to block the IP is set to true. A 403 HTTP response code is returned informing the visitor that they not authorized to continue and the connection is dropped.

An actual +/- 48 hours overview of IP addresses that are blocked, including a searchable database can be found on the Cyber Security page.

2015 banned and blockedIP address data listings

2015 - Blocked IP addresses

2014 banned and blocked IP address data listings

2014 - Blocked IP addresses

2014 - Spam IP addresses

2014 - Unwelcome robots IP addresses

Configuration and Code

Place the required library references in the header of 'Global.ashx' or the Class you place the code in.

Imports Microsoft.VisualBasic

Imports System

Imports System.Collections.Generic

Imports System.Text

Imports System.Text.RegularExpressions

Imports System.Data

Imports System.Web

Imports System.Web.Caching

Imports System.Web.Services

using Microsoft.VisualBasic;

using System;

using System.Collections;

using System.Collections.Generic;

using System.Data;

using System.Diagnostics;

using System.Text;

using System.Text.RegularExpressions;

using System.Web;

using System.Web.Caching;

using System.Web.Services;

 

The two routines IpIsBlocked and IsValidIP below are all you need to get the IP Address filter running

Public Shared Function IpIsBlocked(ByVal strIP As String) As Boolean

  ' Garbage in = garbage out

  If Not IsValidIP(strIP) Then

      Return False

  End If

 

  ' Get the list of bad IPs from the database / cache

  Dim CacheKey As String = "IPBlocklist"

  Dim DS As DataSet = CType(MyCache(CacheKey), DataSet)

 

  If DS Is Nothing Then

      Try

        ' No data = get data

        SyncLock (lock_object) ' Only one call to the database

        DS = New DataSet

        DS.ReadXml(HttpContext.Current.Server.MapPath("~") & "BlockedIPs.xml")

        Dim cd As CacheDependency = New CacheDependency(HttpContext.Current.Server.MapPath("BlockedIPs.xml"))

        DS.Tables("ROW").PrimaryKey = New DataColumn() {DS.Tables("ROW").Columns("IP")}

        MyCache.Insert(CacheKey, DS, cd, System.DateTime.Now.AddMinutes(10), Caching.Cache.NoSlidingExpiration, Caching.CacheItemPriority.Normal, Nothing)

        End SyncLock

      Catch ex As Exception

          Return False

      End Try

 End If

 

 ' Check to see if the ip is in the table

 If DS.Tables(0).Rows.Contains(strIP) Then

   Return True

 Else

   Return False

 End If

End Function

public static bool IpIsBlocked(string strIP)

{

 // Garbage in = garbage out

 if (!IsValidIP(strIP)) {

  return false;

 }

 // Get the list of bad IPs from the database / cache

 string CacheKey = "IPBlocklist";

 DataSet DS = (DataSet)MyCache(CacheKey);

 if (DS == null) {

  try {

   // No data = get data

   // Only one call to the database

   lock ((lock_object)) {

    DS = new DataSet();

    DS.ReadXml(HttpContext.Current.Server.MapPath("~") + "BlockedIPs.xml");

    CacheDependency cd = new CacheDependency(HttpContext.Current.Server.MapPath("BlockedIPs.xml"));

    DS.Tables("ROW").PrimaryKey = new DataColumn[] { DS.Tables("ROW").Columns("IP") };

    MyCache.Insert(CacheKey, DS, cd, System.DateTime.Now.AddMinutes(10), Caching.Cache.NoSlidingExpiration, Caching.CacheItemPriority.Normal, null);

   }

  } catch (Exception ex) {

   return false;

  }

 }

 

// Check to see if the ip is in the table

 if (DS.Tables(0).Rows.Contains(strIP)) {

  return true;

 } else {

  return false;

 }

}

 

Historic Result sets

Links to IP Lists we use to block and throttle access to various websites and services. You are welcome to use these as you please, but please do not automate against these list unless you want your IP listed here to.

Note: As of July 2013 the ISA listings are no longer updated nor maintained. The lists above are based on actual TMG IP Intercepts.