2

我想以编程方式保护我的 ASP.Net 4.0 网站免受有害的重复请求。如果我注意到来自 IP 的请求数很高,那么我想阻止该 IP 一段时间(例如,如果有人编写 FOR 循环并一遍又一遍地请求网页)。我知道最好的防御措施不是将数据提供给未经身份验证的用户,但不幸的是,一些公共页面数据量很大,我对此无能为力。

我今天看了一些解决方案,但没有一个让我满意。我猜这是一个非常普遍的问题,我不想从头开始实施这样的事情。

我看到了一个作为模块实现的解决方案,我想做同样的事情,但做得更好。我需要以下功能:

  • 在检测到非人类模式后阻止 IP
  • 最好实现为 HttpModule
  • 允许爬虫通过
  • 块应该在一定的时间间隔后过期
  • 轻量级:该模块不应减慢网站或访问数据库
4

1 回答 1

3

针对上述问题有两种方法:

  1. 使用 IIS 动态 IP 限制模块
  2. 在 Github 上使用 HackerSpray 库

对于第一种方法,

IIS 的动态 IP 限制扩展为 IT 专业人员和主机提供了一个可配置的模块,该模块通过临时阻止遵循以下模式的 HTTP 客户端的 Internet 协议 (IP) 地址来帮助减轻或阻止拒绝服务攻击或通过暴力破解密码有利于其中一种攻击。可以配置此模块,以便可以在 Web 服务器或网站级别进行分析和阻止。


来源https ://www.iis.net/downloads/microsoft/dynamic-ip-restrictions :

对于第二种方法,

HackerSpray 使用 Redis 为操作和源 IP 维护高性能计数器。你调用 Hacker.Defend(key, ip) 来检查某个键或 IP 是否有太多的点击。您可以维护密钥、IP 或 IP 范围的黑名单。HackerSpray 会检查是否有过多的按键点击、过多的 IP 点击或 IP 落入黑名单。它还允许将某个 IP 的某个密钥列入黑名单或即时阻止所有 IP 的某个密钥。当您想阻止用户访问某些 URL 时很方便。

它带有一个 HttpModule,可以保护您的整个网站。

示例调用:

var result = await Hacker.DefendAsync("/Account/LogOn", Request.UserHostAddress);

if (result == Hacker.Result.TooManyHitsFromOrigin) 
    await Hacker.BlacklistOriginAsync(Request.UserHostAddress, TimeSpan.FromMinutes(10)); 

else if (result == Hacker.Result.TooManyHitsOnKey) 
    await Hacker.BlacklistKeyAsync("/Account/LogOn", TimeSpan.FromMinutes(10));


 Hacker.DefendAsync("/Account/PasswordReset", Request.UserHostAddress, TimeSpan.FromMinutes(5), 100);
 Hacker.DefendAsync("Username" + username, Request.UserHostAddress);
 Hacker.DefendAsync("Comment", Request.UserHostAddress);

登录控制器示例:

[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
{
    if (!ModelState.IsValid)
    {
        return View(model);
    }
   return await Hacker.DefendAsync<ActionResult>(async (success, fail) =>
   {
       // This doesn't count login failures towards account lockout
       // To enable password failures to trigger account lockout, change to       shouldLockout: true
        var result = await SignInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, shouldLockout: false);
    switch (result)
    {
        case SignInStatus.Success:
            return await success(RedirectToLocal(returnUrl));
        case SignInStatus.LockedOut:
            return await fail(View("Lockout"));
        case SignInStatus.RequiresVerification:
            return await success(RedirectToAction("SendCode", new { ReturnUrl = returnUrl, RememberMe = model.RememberMe }));
        case SignInStatus.Failure:
        default:
            ModelState.AddModelError("", "Invalid login attempt.");
            return await fail(View(model));
    }
},
blocked => new HttpStatusCodeResult(HttpStatusCode.Forbidden),
    "ValidLogin:" + model.Email, 3, TimeSpan.FromMinutes(5),
    "InvalidLogin:" + model.Email, 4, TimeSpan.FromMinutes(5),
    Request.GetClientIp()
); }

在 web.config 中,您需要使用 HttpModule 指定要保护的路径。

<HackerSprayConfig redis="localhost" prefix="AuthTest:">
<keys>
  <add name="/Account/LogOn/" post="true" maxAttempts="100" interval="00:10:00" mode="perkeyperorigin" />
  <add name="/Home/" post="false" maxAttempts="10000" interval="00:01:00" mode="perorigin" />
  <add name="/" post="false" maxAttempts="10000" interval="00:01:00" mode="perorigin" />
</keys> </HackerSprayConfig>
  • redis - 这是到 Redis 服务器的连接字符串。
  • prefix - 在 redis 中创建的所有键都以此为前缀。
  • 密钥 - 您要保护的每个路径一个条目
  • name - 要匹配的路径
  • 发布 - 真 = 发布,假 = 获取
  • maxAttempts - 允许的最大命中数
  • 间隔 - 点击多长时间?
  • mode - 如何计算命中数并应用阻塞
    • perkey - 计算从所有 IP 到此键的点击次数。例如,在 10 分钟内允许最多 1000000 次主页点击。
    • perorigin - 在检查此键的命中时,如果源 IP 产生的任何键的总命中次数超过了 maxAttempts,则阻止。例如,对于任何键,每个 IP 允许 1000 次点击,但在登录页面点击时执行此检查。
    • perkeyorigin - 按 IP 计算对该键的点击次数。例如,登录页面上每个 IP 有 1000 次点击。

学分/来源https ://github.com/oazabir/HackerSpray

于 2017-06-19T16:01:02.473 回答