コード例 #1
0
        /// <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));
        }
コード例 #2
0
        /// <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
        }
コード例 #3
0
ファイル: AntiBot.cs プロジェクト: loreps-all-site/ISPCore
        /// <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
        }