سؤال

What tools or techniques can I use to protect my ASP.NET web application from Denial Of Service attacks

هل كانت مفيدة؟

المحلول

Try the Dynamic IP Restriction extension http://www.iis.net/download/dynamiciprestrictions

Not a perfect solution, but helps raise the bar =)

نصائح أخرى

It's a broad area, so if you can be more specific about your application, or the level of threat you're trying to protect against, I'm sure more people can help you.

However, off the bat, you can go for a combination of a caching solution such as Squid: http://www.blyon.com/using-squid-proxy-to-fight-ddos/, Dynamic IP Restriction (as explained by Jim) and if you have the infrastructure, an active-passive failover setup, where your passive machine serves placeholder content which doesnt hit your database / any other machines. This is last-defence, so that you minimise the time a DDOS might bring your entire site offline for.

For sure a hardware solution is the best option to prevent DOS attacks, but considering a situation in which you have no access to hardware config or IIS settings, this is definitely why a developer must have something handy to block or at least decrease dos attack effect.

The core concept of logic relies on a FIFO (First In First Out) collection such as Queue, but as it has some limitations I decided to create my own collection.

Without discussing more details this is the complete code I use:

public class AntiDosAttack
{
  readonly static List<IpObject> items = new List<IpObject>();

  public static void Monitor(int Capacity, int Seconds2Keep, int AllowedCount)
  {
    string ip = HttpContext.Current.Request.UserHostAddress;

    if (ip == "")
    return;

    // This part to exclude some useful requesters
    if(HttpContext.Current.Request.UserAgent != null && HttpContext.Current.Request.UserAgent == "Some good bots")
      return;

    // to remove old requests from collection
    int index = -1;
    for (int i = 0; i < items.Count; i++)
    {

      if ((DateTime.Now - items[i].Date).TotalSeconds > Seconds2Keep)
      {
        index = i;
        break;
      }
    }

    if (index > -1)
    {
      items.RemoveRange(index, items.Count - index);
    }

    // Add new IP
    items.Insert(0, new IpObject(ip));

    // Trim collection capacity to original size, I could not find a better reliable way
    if (items.Count > Capacity)
    {
      items.RemoveAt(items.Count - 1);
    }

    // Count of currect IP in collection
    int count = items.Count(t => t.IP == ip);

    // Decide on block or bypass
    if (count > AllowedCount)
    {
      // alert webmaster by email (optional)
      ErrorReport.Report.ToWebmaster(new Exception("Blocked probable ongoing ddos attack"), "EvrinHost 24 / 7 Support - DDOS Block", "");

      // create a response code 429 or whatever needed and end response
      HttpContext.Current.Response.StatusCode = 429;
      HttpContext.Current.Response.StatusDescription = "Too Many Requests, Slow down Cowboy!";
      HttpContext.Current.Response.Write("Too Many Requests");
      HttpContext.Current.Response.Flush(); // Sends all currently buffered output to the client.
      HttpContext.Current.Response.SuppressContent = true;  // Gets or sets a value indicating whether to send HTTP content to the client.
      HttpContext.Current.ApplicationInstance.CompleteRequest(); // Causes ASP.NET to bypass all events and filtering in the HTTP pipeline chain of execution and directly execute the EndRequest event.
    }
  }

  internal class IpObject
  {
    public IpObject(string ip)
    {
      IP = ip;
      Date = DateTime.Now;
    }

    public string IP { get; set; }
    public DateTime Date { get; set; }
  }
}

The internal class is designed to keep the date of request.

Naturally DOS Attack requests create new sessions on each request while human requests on a website contain multiple requests packed in one session, so the method can be called in Session_Start.

usage:

protected void Session_Start(object sender, EventArgs e)
{
   // numbers can be tuned for different purposes, this one is for a website with low requests
   // this means: prevent a request if exceeds 10 out of total 30 in 2 seconds
   AntiDosAttack.Monitor(30, 2, 10);
}

for a heavy request website you may change seconds to milliseconds but consider the extra load caused by this code.

I am not aware if there is a better solution to block intentional attacks on website, so I appreciate any comment and suggestion to improve the code. By then I consider this as a best practice to prevent DOS attacks on ASP.NET websites programmatically.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top