環境
私の IIS は、WebService リソースを使用して WebApp をホストします。
- ...
- myWebService.asmx
- myWebService.svc
- ...
問題
同じ悪者、彼らのボットで公開リソースにアクセスするサーバーをブロックしてみてください。
応用ソリューション
フィルターを作成します。
public class BadGuysFilter { private class BadGuy { public BadGuy() { Visits = 0; FirstSuspiciousVisit = DateTime.Now; } public int Visits; public DateTime FirstSuspiciousVisit; } private static volatile Dictionary<string, BadGuy> _blackList = new Dictionary<string, BadGuy>(); private static int _visitsLimit = 10; private static int _minutsLimit = 10; private static int _removeFromBlackListMinutesLimit = 30; public static void Init(int visitsLimit = 10, int minutsLimit = 10, int removeFromBlackListMinutesLimit = 30) { _visitsLimit = visitsLimit; _minutsLimit = minutsLimit; _removeFromBlackListMinutesLimit = removeFromBlackListMinutesLimit; } public static bool IsBadGuy() { return IsBadGuy(HttpContext.Current.Request.UserHostAddress); } public static bool IsBadGuy(string ip) { if (HttpContext.Current.Request.IsAuthenticated /*|| HttpContext.Current.Request.HttpMethod.ToUpper() == "POST"*/) return false; if (_blackList.Keys.Any(k => k == ip)) { _blackList[ip].Visits++; if (_blackList[ip].FirstSuspiciousVisit < DateTime.Now.AddMinutes(-_removeFromBlackListMinutesLimit)) _blackList.Remove(ip); else if (_blackList[ip].FirstSuspiciousVisit < DateTime.Now.AddMinutes(-_minutsLimit)) { _blackList[ip].Visits = 0; _blackList[ip].FirstSuspiciousVisit = DateTime.Now; } else if (_blackList[ip].Visits > _visitsLimit) { _blackList[ip].FirstSuspiciousVisit = DateTime.Now; return true; } } else _blackList.Add(ip, new BadGuy()); return false; } public static void Punish() { var res = HttpContext.Current.Response; res.Clear(); res.StatusCode = 429; res.StatusDescription = "TOO MANY REQUESTS: Your application is sending too many simultaneous requests."; res.End(); } }
Global.asaxでフィルターを使用する
void Application_BeginRequest(object sender, EventArgs e) { if(BadGuysFilter.IsBadGuy()) BadGuysFilter.Punish(); // do stuff // } void Application_EndRequest(object sender, EventArgs e) { var app = (HttpApplication)sender; if (app.Context.Response.StatusCode == 429) // "TOO MANY REQUESTS" return; // do stuff // }
質問
これは十分に安全な解決策ですか?それとも別の方法がありますか?
Edite: 「リソース自体でブロックしないでください。さらに上流、たとえばファイアウォールでブロックしてください。– Marc B」 はい、その通りです。これは最終的な解決策ですが、適用する前にサーバーを防御するための中間的な解決策が必要です。このことについて言及するのを忘れていました。– アルティオム