有没有办法在ApplicationBeginRequest或任何其他事件上检测DOS?

时间:2014-06-25 12:33:20

标签: c# asp.net asp.net-mvc

从ApplicationBeginRequest等直接网站(在本例中为ASP.NET MVC)中检测DOS攻击和攻击者的最佳方法是什么。

我在这个网站上搜索过,发现了一个类似的问题,没有任何答案或例子。谷歌也没有找到任何结果。

Restrict IP's by code in Asp.net MVC

我知道IIS上的动态IP地址限制,但我希望该网站检测此类攻击并发送电子邮件警报。

很遗憾,我无法访问我的IIS日志,因为我的网站位于共享主机上。

2 个答案:

答案 0 :(得分:2)

DDOS攻击是分布式拒绝服务。如果它是以一种聪明的方式完成的(使用semisyncronized僵尸网络,不会疯狂地发送垃圾邮件,但使用间歇性的请求泛滥),那么我不确定是否确实存在检测它的好方法。检测DDoS需要大量的统计分析,而攻击者知道正在分析的内容和方式,可以修补他的僵尸网络以防止漏洞。

好吧,如果每分钟有多个请求或类似的请求(MSDNStackOverflow),您就可以检测到您的网站过载了。但是你会做什么 - 只是中止它们并在过载期间禁止IP?在没有附带损害的情况下,很难以可靠的方式分析和预防DDoS。

答案 1 :(得分:2)

随着我对你的问题的评论的警告(即,这实际上阻止了DDOS,因为DDOS可能发生在网络堆栈中的较低级别),这里是基于漏洞的速率限制器在过去的几年里,我的目的很好地实现了目标:

public class RateLimiter
{
   private readonly double numItems;
   private readonly double ratePerSecond;
   private readonly ConcurrentDictionary<object, RateInfo> rateTable = 
                             new ConcurrentDictionary<object, RateInfo>();
   private readonly double timePeriod;

   public RateLimiter(double numItems, double timePeriod)
   {
       this.timePeriod = timePeriod;
       this.numItems = numItems;
       ratePerSecond = numItems / timePeriod;
   }

   public double Count
   {
       get
       {
           return numItems;
       }
   }

   public double Per
   {
       get
       {
           return timePeriod;
       }
   }

   public bool IsPermitted(object key)
   {
       var permitted = true;
       var now = DateTime.UtcNow;

        rateTable.AddOrUpdate(
            key,
            k => new RateInfo(now, numItems - 1d),
            (k, rateInfo) => {
                var timePassedSeconds = 
                                  (now - rateInfo.LastCheckTime).TotalSeconds;
                var newAllowance = 
                                  Math.Min(rateInfo.Allowance 
                                            + timePassedSeconds 
                                            * ratePerSecond,
                           numItems);
                if (newAllowance < 1d)
                {
                    permitted = false;
                }
                else
                {
                    newAllowance -= 1d;
                }
                return new RateInfo(now, newAllowance);
            });
        var expiredKeys = rateTable
               .Where(kvp => 
                   (now - kvp.Value.LastCheckTime) > 
                   TimeSpan.FromSeconds(timePeriod))
               .Select(k => k.Key);
        foreach (var expiredKey in expiredKeys)
        {
            Reset(expiredKey);
        }

       return permitted;
   }

   public void Reset(object key)
   {
        RateInfo rr;
        rateTable.TryRemove(key,out rr);
   }


   internal struct RateInfo
   {
       private readonly double allowance;
       private readonly DateTime lastCheckTime;

       public RateInfo(DateTime lastCheckTime, double allowance)
       {
           this.lastCheckTime = lastCheckTime;
           this.allowance = allowance;
       }

       public DateTime LastCheckTime
       {
           get
           {
               return lastCheckTime;
           }
       }

       public double Allowance
       {
           get
           {
               return allowance;
           }
       }
   }
}

确保您的密钥适合存储在哈希表中(例如,它们实现相等和.GetHashCode)并像这样使用它:

void Main()
{
    var limiter=new RateLimiter(5,1);   //permit 5 items every 1 second
    AddStuff(limiter);
    Thread.Sleep(10000);
}
async Task AddStuff(RateLimiter limiter)
{
    for(var i=0;i<10000;++i)
    {
        Console.WriteLine(limiter.IsPermitted("foo"));
        await Task.Delay(10);

    }
}