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)); }
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)); }
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; }
public static void Run(CoreDB coreDB, JsonDB jsonDB, IMemoryCache memoryCache) { if (IsRun || !jsonDB.AntiDdos.IsActive || Platform.Get != PlatformOS.Unix) { return; } IsRun = true; #region Переносим данные TCP/UPD с кеша в базу (за прошлый час) var TimeAntiDdosNumberOfRequestDay = DateTime.Now.AddHours(-1); if (memoryCache.TryGetValue(KeyToMemoryCache.AntiDdosNumberOfRequestDay(TimeAntiDdosNumberOfRequestDay), out NumberOfRequestDay dataLastHour)) { // Меняем режим доступа к SQL SqlToMode.SetMode(SqlMode.Read); // Записываем данные в базу coreDB.AntiDdos_NumberOfRequestDays.Add(dataLastHour); // Сохраняем базу coreDB.SaveChanges(); // Меняем режим доступа к SQL SqlToMode.SetMode(SqlMode.ReadOrWrite); // Сносим кеш (статистика за час) memoryCache.Remove(KeyToMemoryCache.AntiDdosNumberOfRequestDay(TimeAntiDdosNumberOfRequestDay)); } #endregion #region Очистка баз + перенос NumberOfRequestDay в NumberOfRequestMonth if (memoryCache.TryGetValue("CronAntiDdosClearDB", out DateTime CronClearDB)) { // Если дата отличается от текущей if (CronClearDB.Day != DateTime.Now.Day) { // Меняем режим доступа к SQL SqlToMode.SetMode(SqlMode.Read); // Обновляем кеш memoryCache.Set("CronAntiDdosClearDB", DateTime.Now); #region Очищаем NumberOfRequestMonth foreach (var item in coreDB.AntiDdos_NumberOfRequestMonths.AsNoTracking()) { // Если записи больше 90 дней if ((DateTime.Now - item.Time).TotalDays > 90) { coreDB.Database.ExecuteSqlCommand(ComandToSQL.Delete(nameof(coreDB.AntiDdos_NumberOfRequestMonths), item.Id)); } } #endregion #region Очищаем Jurnals foreach (var item in coreDB.AntiDdos_Jurnals.AsNoTracking()) { // Если записи больше 90 дней if ((DateTime.Now - item.Time).TotalDays > 90) { coreDB.Database.ExecuteSqlCommand(ComandToSQL.Delete(nameof(coreDB.AntiDdos_Jurnals), item.Id)); } } #endregion #region Очищаем NumberOfRequestDay + Переносим NumberOfRequestDay в NumberOfRequestMonth // Хранимм дату и значение var NumberOfRequestMonth = new Dictionary <int, (DateTime time, long value, int CountBlocked)>(); // Собираем статистику за прошлые дни foreach (var item in coreDB.AntiDdos_NumberOfRequestDays.AsNoTracking()) { // Пропускаем статистику за сегодня if (item.Time.Day == DateTime.Now.Day && item.Time.Month == DateTime.Now.Month) { continue; } #region Переносим значения в NumberOfRequestMonth if (NumberOfRequestMonth.TryGetValue(item.Time.Day, out (DateTime time, long value, int CountBlocked)it)) { NumberOfRequestMonth[item.Time.Day] = (it.time, (item.value > it.value ? item.value : it.value), (item.CountBlocked + it.CountBlocked)); } else { NumberOfRequestMonth.Add(item.Time.Day, (item.Time, item.value, item.CountBlocked)); } #endregion // Удаляем значения из базы coreDB.Database.ExecuteSqlCommand(ComandToSQL.Delete(nameof(coreDB.AntiDdos_NumberOfRequestDays), item.Id)); } // Переносим временные данные с NumberOfRequestMonth в базу foreach (var item in NumberOfRequestMonth) { // Добовляем в базу coreDB.AntiDdos_NumberOfRequestMonths.Add(new NumberOfRequestMonth() { Time = item.Value.time, value = item.Value.value, CountBlocked = item.Value.CountBlocked }); } #endregion // Сохраняем базу coreDB.SaveChanges(); // Меняем режим доступа к SQL SqlToMode.SetMode(SqlMode.ReadOrWrite); // Раз в сутки GC.Collect(GC.MaxGeneration); } } else { // Создаем кеш задним числом memoryCache.Set("CronAntiDdosClearDB", DateTime.Now.AddDays(-1)); } #endregion #region Очистка IPTables/IP6Tables if (jsonDB.AntiDdos.BlockToIPtables) { Bash bash = new Bash(); foreach (var comandTables in "iptables,ip6tables".Split(',')) { // Список IP foreach (var line in bash.Run(comandTables + " -L INPUT -v --line-numbers | awk '{print $1,$2,$9,$12}'").Split('\n').Reverse()) { // Разбираем строку var gr = new Regex("^([0-9]+) ([^ ]+) [^ ]+ ISPCore_([^\n\r]+)$").Match(line).Groups; if (string.IsNullOrWhiteSpace(gr[1].Value) || !DateTime.TryParse(gr[3].Value, out DateTime time)) { continue; } // Если время блокировки истекло if (DateTime.Now > time) { if (jsonDB.AntiDdos.ActiveLockMode) { if (gr[2].Value == "0") { bash.Run($"{comandTables} -D INPUT {gr[1].Value}"); } else { bash.Run($"{comandTables} -Z INPUT {gr[1].Value}"); } } else { bash.Run($"{comandTables} -D INPUT {gr[1].Value}"); } } } } } #endregion IsRun = false; }