async public Task <JsonResult> LimitRequest(string recaptchaKey, string IP, int ExpiresToMinute, string hash) { if (string.IsNullOrWhiteSpace(recaptchaKey)) { return(Json(new Text("recaptchaKey == null"))); } if (hash != md5.text($"{IP}{ExpiresToMinute}:{PasswdTo.salt}")) { return(Json(new Text("hash error"))); } // Проверяем reCAPTCHA if (await Recaptcha.Verify(recaptchaKey, jsonDB.Base.reCAPTCHASecret)) { // Создаем кеш memoryCache.Set(KeyToMemoryCache.LimitRequestToreCAPTCHA(IP), (0, ExpiresToMinute), TimeSpan.FromMinutes(ExpiresToMinute)); // Отдаем ответ return(Json(new TrueOrFalse(true))); } // Ошибка return(Json(new Text("Verify == false"))); }
public JsonResult Remove(int Id) { #region Демо режим if (Platform.IsDemo) { return(Json(new Text("Операция недоступна в демо-режиме"))); } #endregion // Удаляем домен if (coreDB.WhitePtrIPs.FindItem(i => i.Id == Id) is WhitePtrIP item) { // Удаляем IP в кеше memoryCache.Remove(KeyToMemoryCache.WhitePtrIP(item.IPv4Or6)); // ISPCore.Models.Triggers.Events.Base.SqlAndCache.WhitePtrIP.OnRemove((item.IPv4Or6, item.PTR)); // Удаляем запись в SQL coreDB.WhitePtrIPs.Remove(item); coreDB.SaveChanges(); // Отдаем результат return(Json(new TrueOrFalse(true))); } // Ошибка return(Json(new Text("Ошибка ;("))); }
public JsonResult Open(string host, string IP, int AccessTimeToMinutes, AccessType accessType) { #region Демо режим if (Platform.IsDemo) { return(Json(new Modal("Операция недоступна в демо-режиме"))); } #endregion // Проверка IP if (string.IsNullOrWhiteSpace(IP) || (!IP.Contains(".") && !IP.Contains(":")) || (IP.Contains(".") && !Regex.IsMatch(IP, @"^[0-9]+\.[0-9]+\.[0-9]+\.([0-9]+|\*)$"))) { return(Json(new Modal("Поле 'IP-адрес' имеет недопустимое значение"))); } // ППроверка домена if (accessType != AccessType.allDomain && string.IsNullOrWhiteSpace(host)) { return(Json(new Modal("Поле 'Домен' не может быть пустым"))); } // Коректор времени if (AccessTimeToMinutes <= 0) { AccessTimeToMinutes = 2160; } // Достаем IMemoryCache var memoryCache = Service.Get <IMemoryCache>(); // Добавляем данные в список разрешенных IP, для вывода информации и отмены доступа AccessIP.Add(IP, accessType == AccessType.allDomain ? "все домены" : host, DateTime.Now.AddMinutes(AccessTimeToMinutes), accessType); // IP для кеша string ipCache = IP.Replace(".*", "").Replace(":*", ""); // Добовляем IP в белый список switch (accessType) { case AccessType.all: memoryCache.Set(KeyToMemoryCache.CheckLinkWhitelistToAll(host, ipCache), (byte)1, TimeSpan.FromMinutes(AccessTimeToMinutes)); break; case AccessType.Is2FA: memoryCache.Set(KeyToMemoryCache.CheckLinkWhitelistTo2FA(host, ipCache), (byte)1, TimeSpan.FromMinutes(AccessTimeToMinutes)); break; case AccessType.allDomain: memoryCache.Set(KeyToMemoryCache.CheckLinkWhitelistToAllDomain(ipCache), (byte)1, TimeSpan.FromMinutes(AccessTimeToMinutes)); break; } // Отдаем ответ return(Json(new Modal($"Разрешен доступ для '{IP}' на {AccessTimeToMinutes} {EndOfText.get("минуту", "минуты", "минут", AccessTimeToMinutes)}", true))); }
/// <summary> /// Получить html для AntiBot /// </summary> /// <param name="tplName">Имя шаблона</param> /// <param name="conf">Настройки AntiBot</param> /// <param name="CoreApiUrl">Ссылка на /core/</param> /// <param name="IP">IPv4/6</param> /// <param name="HostConvert">Домен</param> /// <param name="reCAPTCHASitekey">Секретный ключ reCAPTCHA</param> /// <param name="CacheAntiBot">Кеширование ответа</param> /// <param name="AntiBotHashKey">Дополнительный хеш для проверки "SignalR/JS"</param> static string Html(AntiBotType tplName, AntiBotBase conf, string CoreApiUrl, string IP, string HostConvert, string reCAPTCHASitekey, int CacheAntiBot, string AntiBotHashKey) { #region Базовые параметры string tplToUrl = string.Empty; var mass = new Dictionary <string, string>(); mass.Add("IP", IP); mass.Add("CoreApiUrl", CoreApiUrl); mass.Add("HourCacheToUser", conf.HourCacheToUser.ToString()); mass.Add("WaitUser", conf.WaitUser.ToString()); mass.Add("AddCodeToHtml", conf.AddCodeToHtml != null ? conf.AddCodeToHtml : string.Empty); mass.Add("JsToRewriteUser", JsToRewriteUser(conf.RewriteToOriginalDomain, HostConvert)); #endregion #region Хеш и куки switch (tplName) { case AntiBotType.SignalR: mass.Add("host", HostConvert); mass.Add("AntiBotHashKey", AntiBotHashKey); mass.Add("HashToSignalR", md5.text($"{IP}:{HostConvert}:{conf.HourCacheToUser}:{AntiBotHashKey}:{PasswdTo.salt}")); tplToUrl = File.Exists($"{Folders.Tpl.AntiBot}/{tplName}.html") ? "/statics/tpl/AntiBot/SignalR.html" : "/statics/tpl/AntiBot/default/SignalR.html"; break; case AntiBotType.reCAPTCHA: mass.Add("reCAPTCHASitekey", reCAPTCHASitekey); mass.Add("HashToreCAPTCHA", md5.text($"{IP}:{conf.HourCacheToUser}:{PasswdTo.salt}")); tplToUrl = File.Exists($"{Folders.Tpl.AntiBot}/{tplName}.html") ? "/statics/tpl/AntiBot/reCAPTCHA.html" : "/statics/tpl/AntiBot/default/reCAPTCHA.html"; break; case AntiBotType.CookieAndJS: string cookie = GetValidCookie(conf.HourCacheToUser, IP, "js", AntiBotHashKey); mass.Add("ValidCookie", cookie); mass.Add("AntiBotHashKey", AntiBotHashKey); Trigger.OnSetValidCookie((IP, HostConvert, cookie, "js", conf.HourCacheToUser)); tplToUrl = File.Exists($"{Folders.Tpl.AntiBot}/{tplName}.html") ? "/statics/tpl/AntiBot/CookieAndJS.html" : "/statics/tpl/AntiBot/default/CookieAndJS.html"; break; } #endregion // Сериализуем данные string json = JsonConvert.SerializeObject(mass); #region Создаем кеш if (CacheAntiBot != 0) { //IMemoryCache var memoryCache = Service.Get <IMemoryCache>(); memoryCache.Set(KeyToMemoryCache.AntiBotToCache(IP), (tplToUrl, json, tplName), TimeSpan.FromMilliseconds(CacheAntiBot)); } #endregion // Успех return(Html(tplToUrl, json)); }
public JsonResult StatsDay() { var DtNumberOfRequestDay = coreDB.AntiDdos_NumberOfRequestDays.AsNoTracking().ToList(); if (memoryCache.TryGetValue(KeyToMemoryCache.AntiDdosNumberOfRequestDay(DateTime.Now), out NumberOfRequestDay dataHour)) { DtNumberOfRequestDay.Add(dataHour); } return(Json(DtNumberOfRequestDay)); }
/// <summary> /// Неудачная авторизация /// </summary> /// <param name="Settings"></param> /// <param name="memoryCache"></param> /// <param name="RemoteIpAddress">IP адрес пользователя</param> /// <param name="typeBlockIP">Блокировка IP в 'Брандмауэр' глобально или только для домена</param> /// <param name="host"></param> public static void FailAuthorization(string RemoteIpAddress, TypeBlockIP typeBlockIP, string host = null) { var memoryCache = Service.Get <IMemoryCache>(); string key = KeyToMemoryCache.LimitLogin(RemoteIpAddress); if (memoryCache.TryGetValue(key, out List <DateTime> TimeArray)) { // Актуальные записи var array = (from time in TimeArray where (DateTime.Now - time).TotalMinutes < 10 select time).ToList(); // База JsonDB var jsonDB = Service.Get <JsonDB>(); // Блокировка IP if ((array.Count + 1) >= jsonDB.Security.CountAccess) { // Где именно блокировать IP string keyIPtables = typeBlockIP == TypeBlockIP.domain ? KeyToMemoryCache.IPtables(RemoteIpAddress, host) : KeyToMemoryCache.IPtables(RemoteIpAddress); // Записываем IP в кеш IPtables memoryCache.Set(keyIPtables, new IPtables("Перебор паролей", DateTime.Now.AddMinutes(jsonDB.Security.BlockingTime)), TimeSpan.FromMinutes(jsonDB.Security.BlockingTime)); // Удаляем ключ LimitLogin memoryCache.Remove(key); // Дублируем информацию в SQL WriteLogTo.SQL(new BlockedIP() { IP = RemoteIpAddress, BlockingTime = DateTime.Now.AddMinutes(jsonDB.Security.BlockingTime), Description = "Перебор паролей", typeBlockIP = typeBlockIP, BlockedHost = host }); return; } // Обновление записей array.Add(DateTime.Now); memoryCache.Set(key, array, TimeSpan.FromMinutes(10)); } else { memoryCache.Set(key, new List <DateTime>() { DateTime.Now }, TimeSpan.FromMinutes(10)); } }
public IActionResult Index(bool ajax, bool IsJurnal, int page = 1) { // Данные для вывода статистики var DtNumberOfRequestDay = coreDB.AntiDdos_NumberOfRequestDays.AsNoTracking().ToList(); if (memoryCache.TryGetValue(KeyToMemoryCache.AntiDdosNumberOfRequestDay(DateTime.Now), out NumberOfRequestDay dataHour)) { DtNumberOfRequestDay.Add(dataHour); } // База и остальные параметры ViewData["DtNumberOfRequestDay"] = DtNumberOfRequestDay; ViewData["jsonDB"] = jsonDB; ViewData["ajax"] = ajax; ViewData["page"] = page; ViewData["IsJurnal"] = IsJurnal; return(View("~/Views/Security/AntiDdos.cshtml", coreDB)); }
/// <summary> /// Разблокировать IPv4/6 /// </summary> /// <param name="IP">IPv4/6</param> /// <param name="target">Цель</param> /// <param name="BlockedHost">Заблокированный домен</param> public static void RemoveIPv4Or6(string IP, TypeBlockIP target, string BlockedHost) { if (target == TypeBlockIP.domain) { memoryCache.Remove(KeyToMemoryCache.IPtables(IP, BlockedHost)); Trigger.OnRemoveIPv4Or6((IP, BlockedHost)); } else if (target != TypeBlockIP.UserAgent) { if (IPNetwork.CheckingSupportToIPv4Or6(IP, out var ipnetwork)) { // IPv6 if (IP.Contains(":")) { string ipRegex = IPNetwork.IPv6ToRegex(ipnetwork.FirstUsable); IPv6ToRegex = Regex.Replace(IPv6ToRegex, $@"^\^\({ipRegex}\|?", "^("); IPv6ToRegex = Regex.Replace(IPv6ToRegex, $@"\|{ipRegex}", ""); if (IPv6ToRegex == "^()") { IPv6ToRegex = "^$"; } if (IPv6ToModels.TryRemove(ipRegex, out _)) { Trigger.OnRemoveIPv4Or6((IP, BlockedHost)); } } // IPv4 else { if (IPNetwork.IPv4ToRange(ipnetwork.FirstUsable, ipnetwork.LastUsable) is var item && item.FirstUsable != 0) { IPv4ToRange.RemoveAll(i => i.FirstUsable == item.FirstUsable && i.LastUsable == item.LastUsable); if (IPv4ToModels.TryRemove(item.FirstUsable, out _)) { Trigger.OnRemoveIPv4Or6((IP, BlockedHost)); } } } } } }
public IActionResult Index(int Id, bool ajax) { ViewData["Id"] = Id; ViewData["ajax"] = ajax; // Статистика запросов за прошлую минуту if (!memoryCache.TryGetValue(KeyToMemoryCache.IspNumberOfRequestToMinutes(DateTime.Now.AddMinutes(-1)), out IDictionary <string, NumberOfRequestMinute> NumberOfRequestsPerMinute)) { NumberOfRequestsPerMinute = new Dictionary <string, NumberOfRequestMinute>(); } // Настройки домена var domain = FindAndInclude(coreDB.RequestsFilter_Domains.AsNoTracking(), Id); ViewBag.host = domain.host; // Список алиасов List <AliasView> Aliases = new List <AliasView>(); // Alias To AliasView foreach (var alias in domain.Aliases) { // Base Alias var model = new AliasView() { DomainId = alias.DomainId, Folder = alias.Folder, host = alias.host, Id = alias.Id }; // Количество запросов для алиаса if (NumberOfRequestsPerMinute.TryGetValue(alias.host, out NumberOfRequestMinute dt)) { model.ReqToMinute = dt.NumberOfRequest; } Aliases.Add(model); } // Выводим результат return(View("~/Views/RequestsFilter/Domain/Aliases.cshtml", Aliases.OrderByDescending(i => i.ReqToMinute))); }
public static bool CheckIP(string RemoteIpAddress, IMemoryCache memoryCache, out IPtables data, string BlockedHost = null) { string[] mass; string patch, tmp = ""; // IPv6 if (RemoteIpAddress.Contains(":")) { mass = RemoteIpAddress.Split(':'); patch = ":"; } // IPv4 else { mass = RemoteIpAddress.Split('.'); patch = "."; } // Проверяем IP в кеше foreach (var ip in mass) { tmp += patch + ip; if (BlockedHost == null) { if (memoryCache.TryGetValue(KeyToMemoryCache.IPtables(tmp.Remove(0, 1)), out data)) { return(true); } } else { if (memoryCache.TryGetValue(KeyToMemoryCache.IPtables(tmp.Remove(0, 1), BlockedHost), out data)) { return(true); } } } data = new IPtables(); return(false); }
async public Task <JsonResult> LimitRequest(string recaptchaKey, string IP, int ExpiresToMinute, string hash) { var res = await Verify(recaptchaKey, IP, ExpiresToMinute, hash); if (res.res) { // Создаем кеш memoryCache.Set(KeyToMemoryCache.LimitRequestToreCAPTCHA(IP), (0, ExpiresToMinute), TimeSpan.FromMinutes(ExpiresToMinute)); // Trigger.LimitRequest.OnRecaptchaVerify((true, IP, HttpContext.Request.Host.Host, ExpiresToMinute)); // Отдаем ответ return(Json(new TrueOrFalse(true))); } // Ошибка Trigger.LimitRequest.OnRecaptchaVerify((false, IP, HttpContext.Request.Host.Host, ExpiresToMinute)); return(Json(res.ob)); }
/// <summary> /// Выполнить запрос в API /// </summary> /// <param name="uriPath">/add/requests-filter/aliases</param> /// <param name="args">"DomainId=1", "aliases[1].host=test.com"</param> public string API(string uriPath, params string[] args) { try { using (HttpClient client = new HttpClient()) { // Уникальный ключ string apiKey = Generate.Passwd(24); // Добавляем ключ в память var memoryCache = Service.Get <IMemoryCache>(); memoryCache.Set(KeyToMemoryCache.ApiToLocalKey(apiKey), (byte)0, TimeSpan.FromSeconds(90)); // Отправляем запрос в API client.DefaultRequestHeaders.Add("ApiKey", apiKey); string arg = args.Length > 0 ? $"?{String.Join('&', args)}" : string.Empty; return(client.GetStringAsync($"http://127.0.0.1:4538/api{uriPath}{arg}").Result); } } catch (Exception ex) { return(ex.ToString()); } }
public JsonResult Remove(string IP, string host, AccessType accessType) { #region Демо режим if (Platform.IsDemo) { return(Json(new Text("Операция недоступна в демо-режиме"))); } #endregion // Удаляем IP из списка AccessIP.Remove(IP, host, accessType); // Достаем IMemoryCache var memoryCache = Service.Get <IMemoryCache>(); // IP для кеша string ipCache = IP.Replace(".*", "").Replace(":*", ""); // Удаляем запись с кеша switch (accessType) { case AccessType.all: memoryCache.Remove(KeyToMemoryCache.CheckLinkWhitelistToAll(host, ipCache)); break; case AccessType.Is2FA: memoryCache.Remove(KeyToMemoryCache.CheckLinkWhitelistTo2FA(host, ipCache)); break; case AccessType.allDomain: memoryCache.Remove(KeyToMemoryCache.CheckLinkWhitelistToAllDomain(ipCache)); break; } // Отдаем результат return(Json(new TrueOrFalse(true))); }
public JsonResult Remove(int Id) { #region Демо режим if (Platform.IsDemo) { return(Json(new Text("Операция недоступна в демо-режиме"))); } #endregion // Поиск ip var item = coreDB.BlockedsIP.Find(Id); if (item == null) { return(Json(new Text("Запись не найдена"))); } string IP = item.IP.Replace(".*", "").Replace(":*", ""); // Удаляем IP с кеша memoryCache.Remove(KeyToMemoryCache.IPtables(IP)); memoryCache.Remove(KeyToMemoryCache.IPtables(IP, item.BlockedHost)); // Удаляем IP coreDB.BlockedsIP.Remove(item); // Сохраняем базу coreDB.SaveChanges(); // Очистка кеша IPtables if (item.typeBlockIP == TypeBlockIP.UserAgent) { IPtablesMiddleware.ClearCache(); } // Отдаем результат return(Json(new TrueOrFalse(true))); }
public JsonResult Add(string value, string Description, int BlockingTimeDay, TypeBlockIP typeBlockIP = TypeBlockIP.global, bool IsAPI = false) { #region Демо режим if (Platform.IsDemo) { return(Json(new Text("Операция недоступна в демо-режиме"))); } #endregion // Коректировка if (typeBlockIP == TypeBlockIP.domain) { typeBlockIP = TypeBlockIP.global; } // Коректор времени if (BlockingTimeDay <= 0) { BlockingTimeDay = 1; } #region Проверка IP/UserAgent if (typeBlockIP == TypeBlockIP.global) { // IP-адрес string IP = value; // Проверка IP if (string.IsNullOrWhiteSpace(IP) || (!IP.Contains(".") && !IP.Contains(":"))) { return(Json(new Models.Response.Text("Поле 'Значение' имеет недопустимое значение"))); } // IP для кеша и проверки string IPshort = IP.Replace(".*", "").Replace(":*", ""); // Проверка IP на дубликат if (IPtablesMiddleware.CheckIP(IPshort, memoryCache, out _)) { return(Json(new Models.Response.Text("Данный IP-адрес уже заблокирован"))); } // Записываем IP в кеш IPtables memoryCache.Set(KeyToMemoryCache.IPtables(IPshort), new IPtables(Description, DateTime.Now.AddDays(BlockingTimeDay)), TimeSpan.FromDays(BlockingTimeDay)); } else { // Проверка UserAgent if (string.IsNullOrWhiteSpace(value)) { return(Json(new Models.Response.Text("Поле 'Значение' имеет недопустимое значение"))); } } #endregion // Дублируем информацию в SQL var blockedIP = new BlockedIP() { IP = value, Description = Description, BlockingTime = DateTime.Now.AddDays(BlockingTimeDay), typeBlockIP = typeBlockIP }; coreDB.BlockedsIP.Add(blockedIP); // Сохраняем SQL coreDB.SaveChanges(); // Очистка кеша IPtables if (typeBlockIP == TypeBlockIP.UserAgent) { IPtablesMiddleware.ClearCache(); } if (IsAPI) { return(Json(new TrueOrFalse(true))); } // Отдаем результат return(Json(new Html($@"<tr class='elemDelete'> <td class='text-left table-products'> <strong>{value}</strong> </td> <td>{(typeBlockIP == TypeBlockIP.global ? "IP-адрес" : "User Agent")}</td> <td>{Description}</td> <td>{DateTime.Now.AddDays(BlockingTimeDay).ToString("dd.MM.yyyy H:mm")}</td> <td style='text-align: right;' class='table-products btn-icons'>" + "<a onclick=\"return deleteElement(this,'/security/iptables/remove',{Id:'" + blockedIP.Id + "'});\" class=\"btn nopadding-nomargin\"><i class=\"fa fa-trash-o\"></i></a>" + @"</td> </tr>"))); }
public static Task View(HttpContext context, ViewBag viewBag, ActionCheckLink Model, TypeRequest typeResponse, bool NotCache = false) { #region Код ответа if (viewBag.IsErrorRule) { context.Response.StatusCode = 500; } else { switch (Model) { case ActionCheckLink.allow: { context.Response.StatusCode = 303; break; } case ActionCheckLink.Is2FA: { context.Response.StatusCode = 200; break; } case ActionCheckLink.deny: { context.Response.StatusCode = 403; break; } default: { context.Response.StatusCode = 500; break; } } } #endregion // Данные ответа Trigger.OnResponseView((viewBag.IP, viewBag.UserAgent, viewBag.Referer, viewBag.DomainID, viewBag.method, viewBag.host, viewBag.uri, viewBag.FormData, context.Response.StatusCode, viewBag.IsCacheView)); #region Локальный метод - "RenderTitle" string RenderTitle() { if (viewBag.IsErrorRule) { return("Ошибка"); } else { switch (Model) { case ActionCheckLink.allow: return("303"); case ActionCheckLink.deny: return("Доступ запрещен"); case ActionCheckLink.Is2FA: return("Aвторизация 2FA"); default: return("Неизвестная ошибка"); } } } #endregion #region Локальный метод - "RenderScript" string RenderScript() { if (Model == ActionCheckLink.Is2FA) { string hash = SHA256.Text($"{viewBag.host}:{viewBag.method}:{viewBag.uri}:{viewBag.Referer}:{PasswdTo.salt}"); return(@" <script> function unlock(e) { e.preventDefault(); document.getElementById('unlockError').style.display = 'none'; var password = document.getElementById('unlockPassword').value; $.post('" + viewBag.CoreAPI + "/unlock/2fa', { password: password, host: '" + viewBag.host + "', method: '" + viewBag.method + "', uri: '" + WebUtility.UrlEncode(viewBag.uri) + "', referer: '" + WebUtility.UrlEncode(viewBag.Referer) + "', hash: '" + hash + @"' }, function (data) { var json = JSON.parse(JSON.stringify(data)); if (json.msg) { document.getElementById('unlockError').style.display = 'block'; document.getElementById('unlockError').innerText = json.msg; } else if (json.result) { window.location.reload(); } else { document.getElementById('unlockError').style.display = 'block'; document.getElementById('unlockError').innerText = 'Неизвестная ошибка'; } }) } </script>"); } return(string.Empty); } #endregion #region Локальный метод - "RenderBody" string RenderBody() { if (viewBag.IsErrorRule) { return(@"<div class='code'>500</div> <div class='title'>" + viewBag.ErrorTitleException + @"</div> <pre>" + viewBag.ErrorRuleException + @"</pre>"); } else if (Model == ActionCheckLink.Is2FA) { return(@"<div class='code'>2FA</div> <div class='title'>Aвторизация</div> <pre>Введите пароль безопасности для 2FA</pre> <form method='post' action='/' onsubmit='unlock(event)'> <div class='form-group'> <div class='input-group form'> <span class='input-group-addon'><i class='fa fa-lock'></i></span> <input class='form-control' id='unlockPassword' type='password' name='password'> </div> <button type='submit' class='btn-unlock'>Unlock</button> <div id='unlockError' class='errorMsg'>eroror</div> </div> </form>"); } else if (Model == ActionCheckLink.allow) { return(@"<div class='code'>303</div> <div class='title'>Отправить в backend</div>"); } else if (Model == ActionCheckLink.deny) { return(@"<div class='code'>403</div> <div class='title'>Доступ запрещен</div>"); } else { return(@"<div class='code'>500</div> <div class='title'>Неизвестная ошибка</div>"); } } #endregion #region Локальный метод - "RenderDebug" string RenderDebug() { if (viewBag.DebugEnabled) { #region jsonDomain string jsonDomain() { if (viewBag.jsonDomain == null) { return(string.Empty); } return(Regex.Replace(viewBag.jsonDomain.Replace("\\\\", "\\"), "(<!--|-->|\"Auth2faToPasswd\": \"[^\"]+\")", r => { switch (r.Groups[1].Value) { case "<!--": return "<!--"; case "-->": return "-->"; default: { if (r.Groups[1].Value.StartsWith("\"Auth2faToPasswd\":")) { return "\"Auth2faToPasswd\": \"Используется\""; } } break; } return r.Groups[1].Value; })); } #endregion return(@" <!-- IP: " + viewBag?.IP + @" UserAgent: " + viewBag?.UserAgent + @" method: " + viewBag?.method + @" host: " + viewBag?.host + @" uri: " + viewBag?.uri + @" FormData: " + viewBag?.FormData + @" Referer: " + viewBag?.Referer + @" IsCacheView: " + viewBag.IsCacheView + @" " + viewBag.antiBotToGlobalConf?.Replace("\\\\", "\\")?.Replace("<!--", "<!--")?.Replace("-->", "-->") + @" " + jsonDomain() + @" --> "); } return(string.Empty); } #endregion #region Кешируем ответ if (jsonDB.Cache.Checklink != 0 && !NotCache && !viewBag.IsCacheView && context.Response.StatusCode != 200) { memoryCache.Set(KeyToMemoryCache.CheckLinkToCache(viewBag.method, viewBag.host, viewBag.uri), new ResponseView() { ActionCheckLink = Model, TypeResponse = typeResponse, IsErrorRule = viewBag.IsErrorRule, CacheTime = viewBag.CreateCacheView }, TimeSpan.FromMilliseconds(jsonDB.Cache.Checklink)); } #endregion #region Ответ без html if (!jsonDB.Base.DebugEnabled) { // Отдавать html ненужно if (context.Response.StatusCode == 303 || (Startup.cmd.StatusCode.Checklink && context.Response.StatusCode != 200)) { return(Task.FromResult(true)); } } #endregion // Html ответ return(context.Response.WriteAsync(@"<!DOCTYPE html> <html lang='ru-RU'> <head> <title>" + RenderTitle() + @"</title> <meta http-equiv='Content-Type' content='text/html; charset=utf-8'> <meta http-equiv='X-UA-Compatible' content='IE=edge'> <meta name='viewport' content='width=device-width, initial-scale=1, user-scalable=no'> <link rel='stylesheet' href='/statics/style.css'> " + (Model == ActionCheckLink.Is2FA ? "<script type='text/javascript' src='/statics/jquery.min.js'></script>" : string.Empty) + @" </head> <body> " + RenderScript() + @" <div class='error'> <div class='error-block'> " + RenderBody() + @" <div class='copyright'> <div> © 2018 <strong>ISPCore</strong>. All rights reserved. </div> <div> <a href='/'>Главная сайта</a> / <a href='http://core-system.org/' target='_blank'>Core System</a> </div> </div> </div> </div> </body> </html> " + RenderDebug() + @" ", context.RequestAborted)); }
public static void RunSecond(JsonDB jsonDB, IMemoryCache memoryCache) { if (IsRunSecond) { return; } IsRunSecond = true; try { Bash bash = new Bash(); byte second = (byte)DateTime.Now.Second; #region Максимальное значение TCP/UPD за текущий час int MaxTcpOrUpd = int.Parse(bash.Run("ss -ntu | wc -l")); // Записываем данные в кеш if (memoryCache.TryGetValue(KeyToMemoryCache.AntiDdosNumberOfRequestDay(DateTime.Now), out dataHour)) { Trigger.OnCountTcpOrUpd((MaxTcpOrUpd, dataHour.value)); if (MaxTcpOrUpd > dataHour.value) { dataHour.value = MaxTcpOrUpd; memoryCache.Set(KeyToMemoryCache.AntiDdosNumberOfRequestDay(DateTime.Now), dataHour); } } else { dataHour = new NumberOfRequestDay() { value = MaxTcpOrUpd, Time = DateTime.Now }; memoryCache.Set(KeyToMemoryCache.AntiDdosNumberOfRequestDay(DateTime.Now), dataHour); Trigger.OnCountTcpOrUpd((MaxTcpOrUpd, dataHour.value)); } #endregion #region Получаем список IP которые нужно заблокировать List <string> MassIP = new List <string>(); // Количиство активных соеденений MassIP.AddRange(bash.Run(@"ss -ntu | awk '{print $6}' | sed 's%\:[0-9]*$%%g' | sed 's%\:\:ffff\:\([0-9]*\.[0-9]*\.[0-9]*\.[0-9]*\)%\1%g' | sort | uniq -ic | awk '{if ($1 >= " + jsonDB.AntiDdos.MaximumBurstSize + ") {print $2}}'").Split('\n')); // Максимальное количество запросов за 120 секунд if (!memoryCache.TryGetValue("Cron_AntiDdos-tcpdump", out _)) { // Создаем кеш на 120 секунд memoryCache.Set("Cron_AntiDdos-tcpdump", (byte)0, TimeSpan.FromSeconds(120)); // Убиваем tcpdump bash.Run("pkill tcpdump"); // Считываем файл MassIP.AddRange(bash.Run(@"awk '{if ($6 > 0) {print $2}}' " + Folders.Log + @"/tcpdump.log | sed 's%\.[0-9]*$%%g' | sed 's%\:\:ffff\:\([0-9]*\.[0-9]*\.[0-9]*\.[0-9]*\)%\1%g' | sort | uniq -ic | awk '{if ($1 >= " + jsonDB.AntiDdos.NumberOfRequestsIn120Second + ") {print $2}}'").Split('\n')); // Запускаем tcpdump bash.Run($"tcpdump -i {jsonDB.AntiDdos.Interface} -nnpqSt dst port {string.Join(" or dst port ", jsonDB.AntiDdos.CheckPorts.Split(','))} > {Folders.Log}/tcpdump.log 2> /dev/null &"); } #endregion #region Блокируем IP foreach (var IP in MassIP) { // IP в белом списке if (string.IsNullOrWhiteSpace(IP) || IsWhiteIP(jsonDB, memoryCache, IP)) { continue; } // Блокируем IP Blocked(memoryCache, Regex.Replace(IP, "[\n\r\t ]+", "")); } #endregion } catch { } IsRunSecond = false; }
/// <summary> /// Успешнная авторизация /// </summary> /// <param name="memoryCache"></param> /// <param name="RemoteIpAddress">IP адрес пользователя</param> public static void SuccessAuthorization(string RemoteIpAddress) { var memoryCache = Service.Get <IMemoryCache>(); memoryCache.Remove(KeyToMemoryCache.LimitLogin(RemoteIpAddress)); }
/// <summary> /// Заблокировать IPv4/6 /// </summary> /// <param name="IP">IPv4/6</param> /// <param name="target">Цель</param> /// <param name="data">Время и причина блокировки</param> public static void AddIPv4Or6(string IP, ModelIPtables data, TypeBlockIP target, string BlockedHost = null) { if (target == TypeBlockIP.domain) { memoryCache.Set(KeyToMemoryCache.IPtables(IP, BlockedHost), data, data.TimeExpires); Trigger.OnAddIPv4Or6((IP, BlockedHost, data.Description, data.TimeExpires)); } else if (target != TypeBlockIP.UserAgent) { if (IPNetwork.CheckingSupportToIPv4Or6(IP, out var ipnetwork)) { // Крон нужно запустить раньше if (NextTimeClearDbAndCacheToIPv4Or6 > data.TimeExpires) { NextTimeClearDbAndCacheToIPv4Or6 = data.TimeExpires; } // IPv6 if (IP.Contains(":")) { string IPv6 = IPNetwork.IPv6ToRegex(ipnetwork.FirstUsable); // Время и причина блокировки IPv6ToModels.AddOrUpdate(IPv6, data, (s, e) => data); Trigger.OnAddIPv4Or6((IP, BlockedHost, data.Description, data.TimeExpires)); #region Обновляем IPv6ToRegex if (IPv6ToRegex == "^$") { IPv6ToRegex = $"^({IPv6})"; } else { IPv6ToRegex = Regex.Replace(IPv6ToRegex, @"\)$", $"|{IPv6})"); } #endregion } // IPv4 else { if (IPNetwork.IPv4ToRange(ipnetwork.FirstUsable, ipnetwork.LastUsable) is var item && item.FirstUsable != 0) { #region Находим число которое выше FirstUsable и ставим FirstUsable перед ним int index = IPv4ToRange.FindIndex(0, IPv4ToRange.Count, i => i.FirstUsable > item.FirstUsable); if (index == -1) { IPv4ToRange.Add(item); } else { IPv4ToRange.Insert(index, item); } #endregion // Время и причина блокировки IPv4ToModels.AddOrUpdate(item.FirstUsable, data, (s, e) => data); Trigger.OnAddIPv4Or6((IP, BlockedHost, data.Description, data.TimeExpires)); } } } } }
public JsonResult StatsDay(string SearchHost = null) { // Данные для вывода статистики var DtNumberOfRequestDay = new Dictionary <string, List <NumberOfRequestDay> >(); #region Локальный метод "AddOrUpdateToNumberOfRequestDay" void AddOrUpdateToNumberOfRequestDay(string _host, NumberOfRequestBase dt, DateTime time) { if (SearchHost != null && SearchHost != _host) { return; } var item = new NumberOfRequestDay() { Host = _host, Time = time, Count200 = dt.Count200, Count303 = dt.Count303, Count401 = dt.Count401, Count403 = dt.Count403, Count500 = dt.Count500, Count2FA = dt.Count2FA, }; if (DtNumberOfRequestDay.TryGetValue(_host, out List <NumberOfRequestDay> mass)) { // Добовляем данные mass.Add(item); // Перезаписываем данные DtNumberOfRequestDay[_host] = mass; } else { // Записываем новые данные DtNumberOfRequestDay.Add(_host, new List <NumberOfRequestDay>() { item }); } } #endregion #region Статистика из базы за сутки foreach (var RequestToHour in coreDB.RequestsFilter_NumberOfRequestDay.AsNoTracking()) { AddOrUpdateToNumberOfRequestDay(RequestToHour.Host, RequestToHour, RequestToHour.Time); } #endregion #region Статистика из кеша за текущий час if (memoryCache.TryGetValue(KeyToMemoryCache.IspNumberOfRequestToHour(DateTime.Now), out IDictionary <string, NumberOfRequestHour> DataNumberOfRequestToHour)) { foreach (var item in DataNumberOfRequestToHour) { AddOrUpdateToNumberOfRequestDay(item.Key, item.Value, DateTime.Now); } } #endregion // Ответ return(Json(DtNumberOfRequestDay)); }
/// <summary> /// Проверка запроса /// </summary> /// <param name="IP">IPv4/6</param> /// <param name="antiBotType">Cпособ проверки</param> /// <param name="HostConvert">Домен</param> /// <param name="method">Метод запроса</param> /// <param name="uri">Url запроса</param> /// <param name="HttpContext">Используется для проверки cookie</param> /// <param name="domain">Кеш настроек домена</param> /// <param name="DomainID">Id домена</param> /// <param name="outHtml">html для вывода пользователю</param> public static bool ValidRequest(string IP, AntiBotType antiBotType, string HostConvert, string method, string uri, HttpContext HttpContext, Models.core.Cache.CheckLink.Domain domain, int DomainID, out string outHtml) { // По умолчанию null outHtml = null; // Не выбран способ проверки if (antiBotType == AntiBotType.Off) { return(true); } #region Проверка Cookie if (IsValidCookie(HttpContext, IP, domain.AntiBot.HashKey, out string _verification)) { Trigger.OnValidCookie((IP, HostConvert, DomainID, true, _verification)); return(true); } else { Trigger.OnValidCookie((IP, HostConvert, DomainID, false, _verification)); } #endregion // IMemoryCache var memoryCache = Service.Get <IMemoryCache>(); // База var jsonDB = Service.Get <JsonDB>(); #region Отдаем данные с кеша if (jsonDB.Cache.AntiBot != 0 && memoryCache.TryGetValue(KeyToMemoryCache.AntiBotToCache(IP), out (string tplToUrl, string json, AntiBotType type)_cache)) { outHtml = Html(_cache.tplToUrl, _cache.json); Trigger.OnResponseView((IP, HostConvert, DomainID, _cache.type)); return(false); } #endregion // Достаем настройки AntiBot из кеша var antiBotToGlobalConf = GlobalConf(jsonDB.AntiBot); #region Проверка User-Agent if (HttpContext.Request.Headers.TryGetValue("User-Agent", out var userAgent)) { // Проверка пользовательского User-Agent if (WhiteUserList.IsWhiteUserAgent(userAgent)) { return(true); } string SearchBot = "(" + // https://yandex.ru/support/webmaster/robot-workings/check-yandex-robots.html "YandexBot|YandexAccessibilityBot|YandexMobileBot|YandexDirectDyn|YandexScreenshotBot|YandexImages|YandexVideo|YandexVideoParser|YandexMedia|YandexBlogs|YandexFavicons|YandexWebmaster|YandexPagechecker|YandexImageResizer|YandexAdNet|YandexDirect|YaDirectFetcher|YandexCalendar|YandexSitelinks|YandexMetrika|YandexNews|YandexCatalog|YandexMarket|YandexVertis|YandexForDomain|YandexSpravBot|YandexSearchShop|YandexMedianaBot|YandexOntoDB|YandexVerticals" + "|" + // https://support.google.com/webmasters/answer/1061943 "APIs-Google|Mediapartners-Google|AdsBot-Google|Googlebot" + "|" + // https://help.mail.ru/webmaster/indexing/robots/robot_log // https://www.bing.com/webmaster/help/how-to-verify-bingbot-3905dc26 "Mail.RU_Bot|Bingbot|msnbot" + ")"; // Проверка User-Agent на поискового бота if (Regex.IsMatch(userAgent, SearchBot, RegexOptions.IgnoreCase)) { #region Локальный метод - "DNSLookup" bool DNSLookup() { string ptr = null; string memKey = $"local-fb23a52e:DNSLookup-{IP}"; if (memoryCache.TryGetValue(memKey, out bool _cacheToDNSLookup)) { return(_cacheToDNSLookup); } // Создаем временный кеш на время проверки memoryCache.Set(memKey, true, TimeSpan.FromMinutes(5)); try { // Получаем имя хоста по IP var host = Dns.GetHostEntryAsync(IP).Result; // Получаем IP хоста по имени host = Dns.GetHostEntryAsync(host.HostName).Result; // Сохраняем PTR ptr = host.HostName; // Проверяем имя хоста и IP на совпадение if (host.AddressList.Where(i => i.ToString() == IP).FirstOrDefault() != null) { // Проверяем имя хоста на белый список DNSLookup if (Regex.IsMatch(host.HostName, @".*\.(yandex.(ru|net|com)|googlebot.com|google.com|mail.ru|search.msn.com)$", RegexOptions.IgnoreCase)) { // Добовляем IP в белый int HourCacheToBot = IsGlobalConf() ? antiBotToGlobalConf.conf.HourCacheToBot : domain.AntiBot.HourCacheToBot; WhitePtr.Add(IP, host.HostName, DateTime.Now.AddHours(HourCacheToBot)); Trigger.OnAddToWhitePtr((IP, HostConvert, DomainID, ptr, HourCacheToBot)); return(true); } } } catch { } // Записываем IP в кеш IPtables и журнал if (Check.Request.SetBlockedToIPtables(domain, IP, HostConvert, "AntiBot", DateTime.Now.AddMinutes(40), uri, userAgent, ptr)) { Trigger.OnBlockedIP((IP, ptr, HostConvert, DomainID, "AntiBot", 40)); } // Не удалось проверить PTR-запись memoryCache.Remove(memKey); return(false); } #endregion #region ежим проверки поискового бота if (IsGlobalConf() ? antiBotToGlobalConf.conf.FirstSkipToBot : domain.AntiBot.FirstSkipToBot) { // Проверяем DNSLookup в потоке ThreadPool.QueueUserWorkItem(i => DNSLookup()); } else { // Плохой бот if (!DNSLookup()) { outHtml = "Не удалось проверить PTR-запись"; return(false); } } #endregion // Бот может зайти на сайт return(true); } } #endregion // Нужна капча или нет bool IsRecaptcha = antiBotType == AntiBotType.reCAPTCHA; // Если капча установлена глобально, то нужно проверить домен в списке if (IsRecaptcha && IsGlobalConf() && antiBotToGlobalConf.conf.type == AntiBotType.reCAPTCHA) { IsRecaptcha = Regex.IsMatch(HostConvert, antiBotToGlobalConf.DomainsToreCaptchaRegex, RegexOptions.IgnoreCase); } // Выбираем настройки какого конфига использовать AntiBotBase antiBotConf = IsGlobalConf() ? (AntiBotBase)antiBotToGlobalConf.conf : (AntiBotBase)domain.AntiBot; #region Проверка пользователя в фоновом режиме if (antiBotConf.BackgroundCheck) { // Ключ для проверки запросов string memKey = $"Core:AntiBot/CountBackgroundRequest-{IP}"; if (method != "GET" && method != "HEAD") { // Если до этого был GET/HEAD запрос if (memoryCache.TryGetValue(memKey, out _)) { return(true); } } else { int CountBackgroundRequest; if (!memoryCache.TryGetValue(memKey, out CountBackgroundRequest)) { CountBackgroundRequest = 0; } // Пользователь не привысил значение if (antiBotConf.CountBackgroundRequest > CountBackgroundRequest) { // Увеличиваем количиство запросов if (!uri.Contains(".") || Regex.IsMatch(uri, antiBotConf.BackgroundCheckToAddExtensions, RegexOptions.IgnoreCase)) { // Записываем/Перезаписываем количиство запросов memoryCache.Set(memKey, ++CountBackgroundRequest, TimeSpan.FromHours(antiBotConf.BackgroundHourCacheToIP)); } // Без заглушки AntiBot return(true); } } } #endregion // reCAPTCHA, SignalR или JavaScript var tplName = (!IsRecaptcha && antiBotType == AntiBotType.reCAPTCHA) ? AntiBotType.SignalR : antiBotType; outHtml = Html(tplName, antiBotConf, jsonDB.Base.CoreAPI, IP, HostConvert, jsonDB.Security.reCAPTCHASitekey, jsonDB.Cache.AntiBot, domain.AntiBot.HashKey); Trigger.OnResponseView((IP, HostConvert, DomainID, tplName)); return(false); #region Локальный метод - "IsGlobalConf" bool IsGlobalConf() { return(antiBotToGlobalConf.conf.Enabled || domain.AntiBot.UseGlobalConf); } #endregion }
public JsonResult Index(string password, string host, string method, string uri, string referer, string hash) { // Декодируем uri, referer и FormData uri = WebUtility.UrlDecode(uri); referer = WebUtility.UrlDecode(referer); #region Проверка переданых параметров if (string.IsNullOrWhiteSpace(password)) { return(Json(new Models.Response.Text("Введите пароль"))); } if (SHA256.Text($"{host}:{method}:{uri}:{referer}:{PasswdTo.salt}") != hash) { return(Json(new Models.Response.Text("Хеш сумма не совпадает"))); } #endregion // User-Agent string userAgent = string.Empty; if (HttpContext.Request.Headers.TryGetValue("User-Agent", out var tmp_userAgent)) { userAgent = tmp_userAgent.ToString(); } // Переменные string IP = HttpContext.Connection.RemoteIpAddress.ToString(); // IP адрес пользователя string HostConvert = Regex.Replace(host.ToLower().Trim(), "^www\\.", ""); // Спецальный host TypeBlockIP typeBlockIP = TypeBlockIP.global; // Блокировка IP в 'Брандмауэр' глобально или только для домена var memoryCache = Service.Get <IMemoryCache>(); // Кеш IMemoryCache #region ModelCache.Domain ModelCache.Domain domain = new ModelCache.Domain(); int DomainID = ISPCache.DomainToID(HostConvert); if (DomainID != 0) { // Достаем данные для домена из кеша domain = ISPCache.GetDomain(DomainID); typeBlockIP = domain.typeBlockIP; } #endregion #region Проверяем IP в блокировке IPtables по домену if (IPtables.CheckIP(IP, out ModelIPtables BlockedData, HostConvert)) { // Логируем пользователя AddJurnalToIPtables(domain, IP, host, method, userAgent, referer, uri); CheckRequest.SetCountRequestToHour(TypeRequest._200, host, domain.confToLog.EnableCountRequest); // Отдаем ответ return(Json(new Models.Response.Text(BlockedData.Description))); } #endregion // Проверяем пароль if (SHA256.Text(password) == PasswdTo.FA || (!string.IsNullOrWhiteSpace(domain.Auth2faToPasswd) && SHA256.Text(password) == domain.Auth2faToPasswd)) { // Добавляем информацию о разрешеном доступе, для вывода информации и отмены доступа AccessIP.Add(IP, host, DateTime.Now.AddHours(12), domain.Auth2faToAccess == Auth2faToAccess.FullAccess ? AccessType.all : AccessType.Is2FA); // Добовляем IP в белый список на 12 часа string keyToAccess = domain.Auth2faToAccess == Auth2faToAccess.FullAccess ? KeyToMemoryCache.CheckLinkWhitelistToAll(host, IP) : KeyToMemoryCache.CheckLinkWhitelistTo2FA(host, IP); memoryCache.Set(keyToAccess, (byte)1, TimeSpan.FromHours(12)); // Записываем данные авторизации в журнал AddToJurnal2FA(domain, IP, host, method, uri, referer, "Успешная авторизация"); // Считаем статистику запросов CheckRequest.SetCountRequestToHour(TypeRequest._2fa, host, domain.confToLog.EnableCountRequest); // Удаляем список неудачных попыток LimitLogin.SuccessAuthorization(IP); // Trigger.OnUnlock2FA((IP, userAgent, referer, DomainID, method, HostConvert, uri, password, true)); // Отдаем результат return(Json(new Models.Response.TrueOrFalse(true))); } // Записываем данные авторизации в журнал AddToJurnal2FA(domain, IP, host, method, uri, referer, "Неудачная попытка авторизации"); // Считаем статистику запросов CheckRequest.SetCountRequestToHour(TypeRequest._2fa, host, domain.confToLog.EnableCountRequest); // Записываем в базу IP адрес пользователя, который ввел неправильно пароль LimitLogin.FailAuthorization(IP, typeBlockIP, HostConvert); // Trigger.OnUnlock2FA((IP, userAgent, referer, DomainID, method, HostConvert, uri, password, false)); // Отдаем результат return(Json(new Models.Response.Text("Неверный пароль"))); }
/// <summary> /// /// </summary> /// <param name="antiBotType"></param> /// <param name="HostConvert"></param> /// <param name="method"></param> /// <param name="HttpContext"></param> /// <param name="domain"></param> /// <param name="outHtml"></param> public static bool ValidRequest(AntiBotType antiBotType, string HostConvert, string method, string uri, HttpContext HttpContext, Models.core.Cache.CheckLink.Domain domain, out string outHtml) { // По умолчанию null outHtml = null; // Не выбран способ проверки if (antiBotType == AntiBotType.Off) { return(true); } //IMemoryCache var memoryCache = Service.Get <IMemoryCache>(); // IP адрес string IP = HttpContext.Connection.RemoteIpAddress.ToString(); // Проверка Cookie if (IsValidCookie(HttpContext, IP)) { return(true); } // База var jsonDB = Service.Get <JsonDB>(); // Достаем настройки AntiBot из кеша var antiBotToGlobalConf = GlobalConf(jsonDB.AntiBot); #region Проверка User-Agent string SearchBot = "(" + // https://yandex.ru/support/webmaster/robot-workings/check-yandex-robots.html "YandexBot|YandexAccessibilityBot|YandexMobileBot|YandexDirectDyn|YandexScreenshotBot|YandexImages|YandexVideo|YandexVideoParser|YandexMedia|YandexBlogs|YandexFavicons|YandexWebmaster|YandexPagechecker|YandexImageResizer|YandexAdNet|YandexDirect|YaDirectFetcher|YandexCalendar|YandexSitelinks|YandexMetrika|YandexNews|YandexCatalog|YandexMarket|YandexVertis|YandexForDomain|YandexSpravBot|YandexSearchShop|YandexMedianaBot|YandexOntoDB|YandexVerticals" + "|" + // https://support.google.com/webmasters/answer/1061943 "APIs-Google|Mediapartners-Google|AdsBot-Google|Googlebot" + "|" + // https://help.mail.ru/webmaster/indexing/robots/robot_log // https://www.bing.com/webmaster/help/how-to-verify-bingbot-3905dc26 "Mail.RU_Bot|Bingbot|msnbot" + ")"; // Достаем User-Agent if (HttpContext.Request.Headers.TryGetValue("User-Agent", out var userAgent)) { // Проверка User-Agent на поискового бота if (Regex.IsMatch(userAgent, SearchBot, RegexOptions.IgnoreCase)) { #region Локальный метод - "DNSLookup" bool DNSLookup() { try { // Получаем имя хоста по IP var host = Dns.GetHostEntryAsync(IP).Result; // Получаем IP хоста по имени host = Dns.GetHostEntryAsync(host.HostName).Result; // Проверяем имя хоста и IP на совпадение if (host.AddressList.Where(i => i.ToString() == IP).FirstOrDefault() != null) { // Проверяем имя хоста на белый список DNSLookup if (Regex.IsMatch(host.HostName, @".*\.(yandex.(ru|net|com)|googlebot.com|google.com|mail.ru|search.msn.com)$", RegexOptions.IgnoreCase)) { // Добовляем IP в белый WhitePtr.Add(IP, DateTime.Now.AddHours(IsGlobalConf() ? antiBotToGlobalConf.conf.HourCacheToBot : domain.AntiBot.HourCacheToBot)); return(true); } } } catch { } #region Блокируем IP и записываем в журнал // Данные для статистики Check.Request.SetCountRequestToHour(TypeRequest._401, HostConvert, domain.confToLog.EnableCountRequest); // Информация по блокировке DateTime Expires = DateTime.Now.AddMinutes(40); string Msg = "AntiBot"; // Записываем IP в кеш IPtables memoryCache.Set(KeyToMemoryCache.IPtables(IP, HostConvert), new IPtables(Msg, Expires), Expires); // Дублируем информацию в SQL WriteLogTo.SQL(new BlockedIP() { IP = IP, BlockingTime = Expires, Description = Msg, typeBlockIP = TypeBlockIP.domain, BlockedHost = HostConvert }); // Лог запроса if (domain.confToLog.IsActive) { var geoIP = (Country : "Disabled", City : "Disabled", Region : "Disabled"); if (domain.confToLog.EnableGeoIP) { geoIP = GeoIP2.City(IP); } // Модель Jurnal401 model = new Jurnal401() { Host = HostConvert, IP = IP, Msg = Msg, Ptr = null, UserAgent = userAgent, Country = geoIP.Country, City = geoIP.City, Region = geoIP.Region, Time = DateTime.Now }; // Записываем данные в журнал switch (domain.confToLog.Jurn401) { case WriteLogMode.File: WriteLogTo.FileStream(model); break; case WriteLogMode.SQL: WriteLogTo.SQL(model); break; case WriteLogMode.all: WriteLogTo.SQL(model); WriteLogTo.FileStream(model); break; } } #endregion // Не удалось проверить PTR-запись return(false); } #endregion #region ежим проверки поискового бота if (IsGlobalConf() ? antiBotToGlobalConf.conf.FirstSkipToBot : domain.AntiBot.FirstSkipToBot) { // Проверяем DNSLookup в потоке ThreadPool.QueueUserWorkItem(i => DNSLookup()); } else { // Плохой бот if (!DNSLookup()) { outHtml = "Не удалось проверить PTR-запись"; return(false); } } #endregion // Бот может зайти на сайт return(true); } // Достаем настройки WhiteList из кеша var whiteList = Engine.Base.SqlAndCache.WhiteList.GetCache(jsonDB.WhiteList); // Проверка пользовательского User-Agent if (Regex.IsMatch(userAgent, whiteList.UserAgentRegex, RegexOptions.IgnoreCase)) { return(true); } } #endregion // Нужна капча или нет bool IsRecaptcha = antiBotType == AntiBotType.reCAPTCHA; // Если капча установлена глобально, то нужно проверить домен в списке if (IsRecaptcha && IsGlobalConf() && antiBotToGlobalConf.conf.type == AntiBotType.reCAPTCHA) { IsRecaptcha = Regex.IsMatch(HostConvert, antiBotToGlobalConf.DomainsToreCaptchaRegex, RegexOptions.IgnoreCase); } // Выбираем настройки какого конфига использовать AntiBotBase antiBotConf = IsGlobalConf() ? (AntiBotBase)antiBotToGlobalConf.conf : (AntiBotBase)domain.AntiBot; #region Проверка пользователя в фоновом режиме if (antiBotConf.BackgroundCheck) { // Ключ для проверки запросов string memKey = $"Core:AntiBot/CountBackgroundRequest-{IP}"; if (method != "GET") { // Если до этого был GET запрос if (memoryCache.TryGetValue(memKey, out _)) { return(true); } } else { int CountBackgroundRequest; if (!memoryCache.TryGetValue(memKey, out CountBackgroundRequest)) { CountBackgroundRequest = 0; } // Пользователь не привысил значение if (antiBotConf.CountBackgroundRequest > CountBackgroundRequest) { // Увеличиваем количиство запросов if (!uri.Contains(".") || Regex.IsMatch(uri, antiBotConf.BackgroundCheckToAddExtensions, RegexOptions.IgnoreCase)) { // Записываем/Перезаписываем количиство запросов memoryCache.Set(memKey, ++CountBackgroundRequest, TimeSpan.FromHours(antiBotConf.BackgroundHourCacheToIP)); } // Без заглушки AntiBot return(true); } } } #endregion // reCAPTCHA, SignalR или JavaScript var tplName = (!IsRecaptcha && antiBotType == AntiBotType.reCAPTCHA) ? AntiBotType.SignalR : antiBotType; outHtml = Html(tplName.ToString(), antiBotConf, jsonDB.Base.CoreAPI, IP, HostConvert, jsonDB.Base.reCAPTCHASitekey); return(false); #region Локальный метод - "IsGlobalConf" bool IsGlobalConf() { return(antiBotToGlobalConf.conf.Enabled || domain.AntiBot.UseGlobalConf); } #endregion }
private string StatReguestToHours(string ShowHost = null) { // Данные для вывода статистики var DtNumberOfRequestDay = new Dictionary <int, NumberOfRequestBase>(); #region Локальный метод - "AddToNumberOfRequestDay" void AddOrUdpateNumberOfRequestDay(string host, NumberOfRequestBase dt) { // Статистика не для текущего дня // Поиск по домену if (dt.Time.Day != DateTime.Now.Day || (ShowHost != null && ShowHost != host)) { return; } if (DtNumberOfRequestDay.TryGetValue(dt.Time.Hour, out NumberOfRequestBase item)) { // Добовляем данные к статистике item.Count200 += dt.Count200; item.Count303 += dt.Count303; item.Count403 += dt.Count403; item.Count401 += dt.Count401; item.Count500 += dt.Count500; item.Count2FA += dt.Count2FA; item.CountIPtables += dt.CountIPtables; } else { // Записываем данные DtNumberOfRequestDay.TryAdd(dt.Time.Hour, new NumberOfRequestBase() { Time = dt.Time, Count200 = dt.Count200, Count303 = dt.Count303, Count403 = dt.Count403, Count401 = dt.Count401, Count500 = dt.Count500, Count2FA = dt.Count2FA, CountIPtables = dt.CountIPtables }); } } #endregion #region Статистика из базы за сутки foreach (var RequestToHour in coreDB.RequestsFilter_NumberOfRequestDay.AsNoTracking()) { AddOrUdpateNumberOfRequestDay(RequestToHour.Host, RequestToHour); } #endregion #region Статистика из кеша за текущий час if (memoryCache.TryGetValue(KeyToMemoryCache.IspNumberOfRequestToHour(DateTime.Now), out IDictionary <string, NumberOfRequestHour> DataNumberOfRequestToHour)) { foreach (var item in DataNumberOfRequestToHour) { AddOrUdpateNumberOfRequestDay(item.Key, item.Value); } } #endregion #region Переменные для статистики string tmpBase = "{x:'0:00',y:0},{x:'1:00',y:0},{x:'2:00',y:0},{x:'3:00',y:0},{x:'4:00',y:0},{x:'5:00',y:0},{x:'6:00',y:0},{x:'7:00',y:0},{x:'8:00',y:0},{x:'9:00',y:0},{x:'10:00',y:0},{x:'11:00',y:0},{x:'12:00',y:0},{x:'13:00',y:0},{x:'14:00',y:0},{x:'15:00',y:0},{x:'16:00',y:0},{x:'17:00',y:0},{x:'18:00',y:0},{x:'19:00',y:0},{x:'20:00',y:0},{x:'21:00',y:0},{x:'22:00',y:0},{x:'23:00',y:0}"; string tmp200 = tmpBase; string tmp303 = tmpBase; string tmp403 = tmpBase; string tmp401 = tmpBase; string tmp500 = tmpBase; string tmp2FA = tmpBase; string tmpIPtables = tmpBase; #endregion #region Обновляем переменные foreach (var dt in DtNumberOfRequestDay) { #region Локальный метод - "GeReplacet" string GeReplace(string s, long value) { return(s.Replace("{x:'" + dt.Value.Time.Hour + ":00',y:0}", "{x:'" + dt.Value.Time.Hour + ":00',y:" + value + "}")); } #endregion tmp200 = GeReplace(tmp200, dt.Value.Count200); tmp303 = GeReplace(tmp303, dt.Value.Count303); tmp403 = GeReplace(tmp403, dt.Value.Count403); tmp401 = GeReplace(tmp401, dt.Value.Count401); tmpIPtables = GeReplace(tmpIPtables, dt.Value.CountIPtables); tmp500 = GeReplace(tmp500, dt.Value.Count500); tmp2FA = GeReplace(tmp2FA, dt.Value.Count2FA); } #endregion #region Собираем json StringBuilder json = new StringBuilder(); json.Append("{key: '200', nonStackable: false, shifting: false, values: [ " + tmp200 + " ] },"); json.Append("{key: '303', nonStackable: false, shifting: false, values: [ " + tmp303 + " ] },"); json.Append("{key: '403', nonStackable: false, shifting: false, values: [ " + tmp403 + " ] },"); json.Append("{key: '401', nonStackable: false, shifting: false, values: [ " + tmp401 + " ] },"); json.Append("{key: 'IPtables', nonStackable: false, shifting: false, values: [ " + tmpIPtables + " ] },"); json.Append("{key: '500', nonStackable: false, shifting: false, values: [ " + tmp500 + " ] },"); json.Append("{key: '2FA', nonStackable: false, shifting: false, values: [ " + tmp2FA + " ] }"); #endregion // Успех return(json.ToString()); }
public static void SetCountRequestToHour(TypeRequest type, string host, bool EnableCountRequest) { #region Локальный метод - "SetCount" void SetCount(NumberOfRequestHour dt) { switch (type) { case TypeRequest._200: dt.Count200++; break; case TypeRequest._303: dt.Count303++; break; case TypeRequest._403: dt.Count403++; break; case TypeRequest._401: dt.Count401++; break; case TypeRequest._500: dt.Count500++; break; case TypeRequest._2fa: dt.Count2FA++; break; } } #endregion if (EnableCountRequest) { string keyNumberOfRequestToHour = KeyToMemoryCache.IspNumberOfRequestToHour(DateTime.Now); if (memoryCache.TryGetValue(keyNumberOfRequestToHour, out IDictionary <string, NumberOfRequestHour> DataNumberOfRequestDay)) { // Если хост есть в кеше if (DataNumberOfRequestDay.TryGetValue(host, out NumberOfRequestHour dtValue)) { SetCount(dtValue); } // Если хоста нету в кеше else { var dt = new NumberOfRequestHour(); dt.Time = DateTime.Now; SetCount(dt); DataNumberOfRequestDay.Add(host, dt); } } else { // Считаем запрос var dt = new NumberOfRequestHour(); dt.Time = DateTime.Now; SetCount(dt); // Создаем кеш memoryCache.Set(keyNumberOfRequestToHour, new Dictionary <string, NumberOfRequestHour>() { [host] = dt }, TimeSpan.FromHours(2)); } } }
public static void SetCountRequestToMinute(string IP, TypeRequest type, string host, int DomainID, bool EnableCountRequest) { if (type != TypeRequest.All && type != TypeRequest._303) { return; } #region Локальный метод - "SetCount" void SetCount(NumberOfRequestMinute dt) { switch (type) { case TypeRequest._303: dt.Count303++; Trigger.OnRequestToMinute((IP, type, dt.Count303, host, DomainID)); break; case TypeRequest.All: dt.NumberOfRequest++; Trigger.OnRequestToMinute((IP, type, dt.NumberOfRequest, host, DomainID)); break; } } #endregion if (EnableCountRequest) { string keyNumberOfRequestToMinutes = KeyToMemoryCache.IspNumberOfRequestToMinutes(DateTime.Now); if (memoryCache.TryGetValue(keyNumberOfRequestToMinutes, out IDictionary <string, NumberOfRequestMinute> NumberOfRequestsPerMinute)) { // Если хост есть в кеше if (NumberOfRequestsPerMinute.TryGetValue(host, out NumberOfRequestMinute dtValue)) { SetCount(dtValue); } // Если хоста нету в кеше else { var dt = new NumberOfRequestMinute(); dt.DomainID = DomainID; SetCount(dt); NumberOfRequestsPerMinute.Add(host, dt); } } else { // Считаем запрос var dt = new NumberOfRequestMinute(); dt.DomainID = DomainID; SetCount(dt); // Создаем кеш memoryCache.Set(keyNumberOfRequestToMinutes, new Dictionary <string, NumberOfRequestMinute>() { [host] = dt }, TimeSpan.FromMinutes(3)); } } }
public IActionResult Index(bool ajax, int page = 1, string search = null, string sort = null) { int pageSize = 12; #region Локальный метод - NavPageSize int NavPageSize() { int x = (page % 5); if (x == 0) { return(pageSize + 1); } return((pageSize * (5 - x)) + 1); } #endregion #region Статистика запросов за прошлую минуту Dictionary <int, ulong> numberOfRequestsPerMinute = new Dictionary <int, ulong>(); { if (memoryCache.TryGetValue(KeyToMemoryCache.IspNumberOfRequestToMinutes(DateTime.Now.AddMinutes(-1)), out IDictionary <string, NumberOfRequestMinute> data)) { foreach (var dt in data) { if (numberOfRequestsPerMinute.TryGetValue(dt.Value.DomainID, out ulong item)) { numberOfRequestsPerMinute[dt.Value.DomainID] = item + dt.Value.NumberOfRequest; } else { numberOfRequestsPerMinute.Add(dt.Value.DomainID, dt.Value.NumberOfRequest); } } #region Сортируем массив if (sort == "req") { numberOfRequestsPerMinute = numberOfRequestsPerMinute.OrderByDescending(i => i.Value).Skip((page * pageSize) - pageSize).Take(NavPageSize()).ToDictionary(i => i.Key, i => i.Value); } else { numberOfRequestsPerMinute = numberOfRequestsPerMinute.OrderByDescending(i => i.Value).ToDictionary(i => i.Key, i => i.Value); } #endregion } } #endregion // Поиск / Сортировка Func <Domain, bool> predicat = i => search == null || i.host.Contains(search); if (sort == "req") { predicat = i => numberOfRequestsPerMinute.ContainsKey(i.Id); } // Список доменов List <DomainView> domains = new List <DomainView>(); // Domain To DomainView foreach (var domain in coreDB.RequestsFilter_Domains.AsNoTracking().Include(t => t.Templates).AsEnumerable().Where(predicat).Reverse().Skip((page * pageSize) - pageSize).Take(NavPageSize())) { var model = new DomainView() { Id = domain.Id, host = domain.host, Protect = domain.Protect }; /// Количество запросов за прошлую минуту if (numberOfRequestsPerMinute.TryGetValue(domain.Id, out ulong ReqToMinute)) { model.ReqToMinute = ReqToMinute; } #region Имена шаблонов StringBuilder TemplateName = new StringBuilder(); foreach (var tpl in domain.Templates) { TemplateName.Append(coreDB.RequestsFilter_Templates.GetTemplateName(tpl.Template, "") + ", "); } model.Templates = Regex.Replace(TemplateName.ToString(), ",([ ]+)?$", ""); #endregion // Модель domains.Add(model); } // Дополнительная информация ViewBag.Info = page == 1 && search == null && sort == null ? "У вас еще нет добавленных доменов" : "Нет данных для вывода"; // Сортировка по "req/s" if (sort == "req") { return(View("~/Views/RequestsFilter/Domains.cshtml", new NavPage <DomainView>(domains.OrderByDescending(i => i.ReqToMinute).ToList(), HttpContext, pageSize, page, overrideMass: true), ajax)); } // Базовая сортировка return(View("~/Views/RequestsFilter/Domains.cshtml", new NavPage <DomainView>(domains, HttpContext, pageSize, page, overrideMass: true), ajax)); }
/// <summary> /// Проверить IPv4/6 /// </summary> /// <param name="RemoteIpAddress">IPv4/6</param> /// <param name="data">Время и причина блокировки</param> /// <param name="BlockedHost">Домен для которого делать проверку</param> public static bool CheckIP(string RemoteIpAddress, out ModelIPtables data, string BlockedHost = null) { data = null; // Блокировка по домену if (BlockedHost != null) { if (memoryCache.TryGetValue(KeyToMemoryCache.IPtables(RemoteIpAddress, BlockedHost), out data)) { Trigger.OnReturn401((RemoteIpAddress, BlockedHost, "IP")); return(true); } } // IPv6 if (RemoteIpAddress.Contains(":")) { #region Локальный метод - "IsMatch" bool IsMatch(out string matchIP) { var match = Regex.Match(RemoteIpAddress, IPv6ToRegex); if (match.Length > 0 && RemoteIpAddress.Contains(match.Groups[1].Value)) { matchIP = match.Groups[1].Value; return(true); } matchIP = null; return(false); } #endregion if (IPv6ToRegex != "^$" && IsMatch(out string matchIPv6)) { if (!IPv6ToModels.TryGetValue(matchIPv6, out data)) { data = new ModelIPtables(); } Trigger.OnReturn401((RemoteIpAddress, BlockedHost, "IP")); return(true); } return(false); } // IPv4 else { if (IPNetwork.CheckToIPv4(RemoteIpAddress, IPv4ToRange, out ulong FirstUsable)) { if (!IPv4ToModels.TryGetValue(FirstUsable, out data)) { data = new ModelIPtables(); } Trigger.OnReturn401((RemoteIpAddress, BlockedHost, "IP")); return(true); } return(false); } }
public static void Run(CoreDB coreDB, IMemoryCache memoryCache) { if (IsRun) { return; } IsRun = true; #region IspNumberOfRequestToHour // Если есть кеш за прошлый час var TimeIspNumberOfRequestDay = DateTime.Now.AddHours(-1); if (memoryCache.TryGetValue(KeyToMemoryCache.IspNumberOfRequestToHour(TimeIspNumberOfRequestDay), out IDictionary <string, NumberOfRequestHour> DataNumberOfRequestToHour)) { SqlToMode.SetMode(SqlMode.Read); coreDB.ChangeTracker.AutoDetectChangesEnabled = false; // Записываем данные в базу foreach (var item in DataNumberOfRequestToHour) { coreDB.RequestsFilter_NumberOfRequestDay.Add(new NumberOfRequestDay() { Host = item.Key, Time = TimeIspNumberOfRequestDay, Count200 = item.Value.Count200, Count303 = item.Value.Count303, Count401 = item.Value.Count401, Count403 = item.Value.Count403, Count500 = item.Value.Count500, Count2FA = item.Value.Count2FA, }); } // Сохраняем базу coreDB.SaveChanges(); // Разрешаем записывать данные в SQL SqlToMode.SetMode(SqlMode.ReadOrWrite); coreDB.ChangeTracker.AutoDetectChangesEnabled = true; // Сносим кеш (статистика за час) memoryCache.Remove(KeyToMemoryCache.IspNumberOfRequestToHour(TimeIspNumberOfRequestDay)); // Раз в час GC.Collect(GC.MaxGeneration); } #endregion #region Очистка баз + перенос NumberOfRequestDay в NumberOfRequestMonth if (memoryCache.TryGetValue("CronIspClearDB", out DateTime CronIspClearDB)) { // Если дата отличается от текущей if (CronIspClearDB.Day != DateTime.Now.Day) { SqlToMode.SetMode(SqlMode.Read); // Обновляем кеш memoryCache.Set("CronIspClearDB", DateTime.Now); #region Очищаем NumberOfRequestMonth foreach (var item in coreDB.RequestsFilter_NumberOfRequestMonth.AsNoTracking()) { // Если записи больше 30 дней if ((DateTime.Now - item.Time).TotalDays > 30) { coreDB.Database.ExecuteSqlCommand(ComandToSQL.Delete(nameof(coreDB.RequestsFilter_NumberOfRequestMonth), item.Id)); } } #endregion #region Очищаем Jurnals200 foreach (var item in coreDB.RequestsFilter_Jurnals200.AsNoTracking()) { // Если записи больше 30 дней if ((DateTime.Now - item.Time).TotalDays > 30) { coreDB.Database.ExecuteSqlCommand(ComandToSQL.Delete(nameof(coreDB.RequestsFilter_Jurnals200), item.Id)); } } #endregion #region Очищаем Jurnals303 foreach (var item in coreDB.RequestsFilter_Jurnals303.AsNoTracking()) { // Если записи больше 30 дней if ((DateTime.Now - item.Time).TotalDays > 30) { coreDB.Database.ExecuteSqlCommand(ComandToSQL.Delete(nameof(coreDB.RequestsFilter_Jurnals303), item.Id)); } } #endregion #region Очищаем Jurnals403 foreach (var item in coreDB.RequestsFilter_Jurnals403.AsNoTracking()) { // Если записи больше 30 дней if ((DateTime.Now - item.Time).TotalDays > 30) { coreDB.Database.ExecuteSqlCommand(ComandToSQL.Delete(nameof(coreDB.RequestsFilter_Jurnals403), item.Id)); } } #endregion #region Очищаем Jurnals401 foreach (var item in coreDB.RequestsFilter_Jurnals401.AsNoTracking()) { // Если записи больше 30 дней if ((DateTime.Now - item.Time).TotalDays > 30) { coreDB.Database.ExecuteSqlCommand(ComandToSQL.Delete(nameof(coreDB.RequestsFilter_Jurnals401), item.Id)); } } #endregion #region Очищаем Jurnals2FA foreach (var item in coreDB.RequestsFilter_Jurnals2FA.AsNoTracking()) { // Если записи больше 30 дней if ((DateTime.Now - item.Time).TotalDays > 30) { coreDB.Database.ExecuteSqlCommand(ComandToSQL.Delete(nameof(coreDB.RequestsFilter_Jurnals2FA), item.Id)); } } #endregion #region Очищаем Jurnals500 foreach (var item in coreDB.RequestsFilter_Jurnals500.AsNoTracking()) { // Если записи больше 30 дней if ((DateTime.Now - item.Time).TotalDays > 30) { coreDB.Database.ExecuteSqlCommand(ComandToSQL.Delete(nameof(coreDB.RequestsFilter_Jurnals500), item.Id)); } } #endregion #region Переносим NumberOfRequestDay в NumberOfRequestMonth // Хранимм дату и значение Dictionary <int, NumberOfRequestBase> NumberOfRequestMonth = new Dictionary <int, NumberOfRequestBase>(); // Собираем статистику за прошлые дни foreach (var item in coreDB.RequestsFilter_NumberOfRequestDay.AsNoTracking()) { // Пропускаем статистику за сегодня if (item.Time.Day == DateTime.Now.Day && item.Time.Month == DateTime.Now.Month) { continue; } #region Переносим значения в NumberOfRequestMonth if (NumberOfRequestMonth.TryGetValue(item.Time.Day, out NumberOfRequestBase it)) { it.Count200 += item.Count200; it.Count303 += item.Count303; it.Count403 += item.Count403; it.Count401 += item.Count401; it.Count500 += item.Count500; it.Count2FA += item.Count2FA; } else { NumberOfRequestMonth.Add(item.Time.Day, item); } #endregion // Удаляем значения из базы coreDB.Database.ExecuteSqlCommand(ComandToSQL.Delete(nameof(coreDB.RequestsFilter_NumberOfRequestDay), item.Id)); } // Переносим временные данные с NumberOfRequestMonth в базу foreach (var item in NumberOfRequestMonth) { // Добовляем в базу coreDB.RequestsFilter_NumberOfRequestMonth.Add(new NumberOfRequestMonth() { Time = item.Value.Time, allRequests = item.Value.Count200 + item.Value.Count303 + item.Value.Count403 + item.Value.Count500 + item.Value.Count401 + item.Value.Count2FA, Count200 = item.Value.Count200, Count303 = item.Value.Count303, Count401 = item.Value.Count401, Count403 = item.Value.Count403, Count500 = item.Value.Count500, Count2FA = item.Value.Count2FA, }); } #endregion // Сохраняем базу coreDB.SaveChanges(); SqlToMode.SetMode(SqlMode.ReadOrWrite); // Раз в день GC.Collect(GC.MaxGeneration); } } else { // Создаем кеш задним числом memoryCache.Set("CronIspClearDB", DateTime.Now.AddDays(-1)); } #endregion IsRun = false; }
public static bool SetBlockedToIPtables(ModelCache.Domain Domain, string IP, string host, string Msg, DateTime Expires, string uri, string userAgent, string PtrHostName) { if (Domain.typeBlockIP == TypeBlockIP.Triggers) { // Что-бы в статистике не считать лишний раз +1 к блокировке string memKey = $"local-fb482608:SetBlockedToIPtables-{IP}"; if (memoryCache.TryGetValue(memKey, out _)) { return(false); // Уже заблокирован } // Данные для статистики SetCountRequestToHour(TypeRequest._401, host, Domain.confToLog.EnableCountRequest); memoryCache.Set(memKey, (byte)0, Expires); } else { // Если IP уже заблокирован if ((Domain.typeBlockIP == TypeBlockIP.domain && memoryCache.TryGetValue(KeyToMemoryCache.IPtables(IP, host), out _)) || (Domain.typeBlockIP == TypeBlockIP.global && Engine.Security.IPtables.CheckIP(IP, out _))) { return(false); } // Записываем IP в кеш IPtables IPtables.AddIPv4Or6(IP, new ModelIPtables(Msg, Expires), Domain.typeBlockIP, host); // Данные для статистики SetCountRequestToHour(TypeRequest._401, host, Domain.confToLog.EnableCountRequest); // Дублируем информацию в SQL WriteLogTo.SQL(new BlockedIP() { IP = IP, BlockingTime = Expires, Description = Msg, typeBlockIP = Domain.typeBlockIP, BlockedHost = host }); } // Игнорирование логов if (Domain.confToLog.IsActive && !Regex.IsMatch(uri, Domain.IgnoreLogToRegex, RegexOptions.IgnoreCase)) { var geoIP = (Country : "Disabled", City : "Disabled", Region : "Disabled"); if (Domain.confToLog.EnableGeoIP) { geoIP = GeoIP2.City(IP); } // Модель Jurnal401 model = new Jurnal401() { Host = host, IP = IP, Msg = Msg, Ptr = PtrHostName, UserAgent = userAgent, Country = geoIP.Country, City = geoIP.City, Region = geoIP.Region, Time = DateTime.Now }; // Записываем данные в журнал switch (Domain.confToLog.Jurn401) { case WriteLogMode.File: WriteLogTo.FileStream(model); break; case WriteLogMode.SQL: WriteLogTo.SQL(model); break; case WriteLogMode.all: WriteLogTo.SQL(model); WriteLogTo.FileStream(model); break; } } // return(true); }