Если вы хотите украсть мои данные, то начните с этой статьи! В ней подробно рассказывается, какие правила файрволла я использую, чтобы упростить вам их обход.
Конечно, я шучу. Мне даже неизвестно, читают ли веб‑краулеры посты, чтобы узнавать такую информацию.
Но я целый год занимался борьбой с ботами в своей базе данных филантропов PatronView. Когда пишешь код при помощи ИИ‑агентов, такому никто не научит, поэтому я решил поделиться полученными знаниями.
Вот некоторые факты, о которых ниже будет рассказано подробнее:
-
Всего за один день к моему сайту обратились 3,6 миллиона запросов китайских ботов.
-
Cloudflare сообщает, что краулеры Anthropic выполняют примерно три тысячи операций краулинга на однго приведённого посетителя. У меня этот показатель составил 35 тысяч:1.
-
Два дня назад я заблокировал поисковый ИИ‑краулер Amazon. Он считывал по 117 тысяч страниц в день, но не направил мне ни одного посетителя.
-
Показатель решения моей CAPTCHA равен 0,24%. Боты даже не пытаются её решать.
-
В конце перечислены все используемые мной правила файрволла.
214 загрузок страниц ботами на каждого человека
На неделе публикации этого поста мой сервер ответил на 2,5 миллиона запросов из внешнего мира и передал 1,28 миллиона целых страниц. Но в моей статистике посетителей зафиксировано всего 5977 просмотров страниц.
На каждую фиксируемую мной загрузку страницы приходится примерно 214 загрузок, которые я не вижу.
Отсюда и взялось название статьи. 5977 просмотров страниц людьми из 1,28 миллиона переданных страниц — это меньше половины процента. То есть я даже округлил долю ботов в меньшую сторону.

Синий квадрат — это наблюдаемый мной трафик. Серые квадраты — это то, что ломится ко мне на сервер. Для аналитики я использую Plausible Community Edition на собственном хостинге, а она считает только посетителей, у которых выполняется JavaScript. Почти ни у одного бота его нет.
Судя по статистике посетителей, мой сайт довольно скромный, примерно 500 посетителей в день. Но мой сервер каждую неделю отвечает на миллионы реальных запросов.
Если смотреть только на статистику посетителей из JavaScript‑инструмента наподобие Plausible, Fathom или Google Analytics, то вы понятия не будете иметь, кто обращается к вашему серверу. Не знал этого и я.
Первый ботнет
PatronView — это база данных американских филантропов, которую я собрал при помощи разведки разного уровня. Она состоит из 1,5 миллиона страниц уникальных профилей, созданных по данным форм 990 Налогового управления США, публичным спискам доноров и ежегодным отчётам.
И да, мой сайт получает эти данных скрейпингом публичных документов. То есть я скрейпер, который написал пост с жалобами на скрейперов. Я знаю, как это звучит. Для протокола скажу, что скрейпинг своих источников я выполняю несколько раз в год, а не тысячи раз в день.
С самого открытия сайта его одолевали SEO‑краулеры наподобие SemrushBot, AhrefsBot, MJ12bot и DataForSEOBot, снова и снова обыскивающие каждую страницу. Я заблокировал их в robots.txt, а затем на уровне Cloudflare при помощи правил безопасности, и это стало моим первым шагом в этом приключении.
В ноябре 2025 года за несколько дней у меня появилось четыре тысячи «посетителей». Каждый из них посетил ровно одну страницу с показателем отказов в 99%. Ещё более наглядным было то, что у них не было источника ссылки, что обычно бывает самым очевидным признаком бота. И они краулили только страницы моего фонда (наподобие этой, этой и этой), на которые заходили только 10% реальных посетителей. Но эти четыре тысячи ботов были только разогревом.
День, когда пришёл Китай
22 апреля мой сайт получил 3,6 миллиона запросов. Они поступили с 361 844 уникальных IP‑адресов, и почти все из них находились в Китае.
Cloudflare Managed Challenge (невидимая CAPTCHA) защитила от 1,18 миллионов запросов за первые десять часов. Тем не менее, пугающая доля этих китайских ботов проходила защиту.
Поэтому я сделал то, что делать не рекомендуется: заблокировал весь Китай в edge‑сети. Спустя несколько дней началась копия этой волны из Вьетнама, поэтому я заблокировал и Вьетнам. А потом был Сингапур.
Мой сайт — это база данных доноров произведений искусства в американские музеи на английском языке. Реальный поисковый трафик состоит на 95,9% из США и на 1,3% из Канады.
Когда я написал твит о шквале китайского веб‑трафика, ответы показали, что с этим борются все:
-
Мэтт Полсон из MarketBeat: «Не забудьте добавить в список Россию».
-
Джек Эллис из Fathom Analytics: «Последние полгода мы наблюдаем огромный трафик спама из Китая. Скажу, что сейчас наши клиенты наблюдают абсолютное снижение китайского трафика».
-
Джереми Брандт: «Наш список заблокированных стран для всех наших сайтов на Cloudflare весьма… длинный».
-
Крис Левицки: «Я решил перестать бороться с этим. Меры защиты сильно повышали сложность моей жизни».
-
Родриго Рокко: «В последнее время творится настоящее безумие, они используют тысячи резидентских IP, каждый из которых делает по одному вызову, поэтому их сложно остановить».
Запомните последнее сообщение, оно мне ещё аукнется.
Коэффициент Claude
Cloudflare заявила, что соотношение краулеров Anthropic составляет примерно три тысячи скрауленных страниц на одного посетителя. В июне я замерил свои показатели: 35 тысяч к 1.
Поясню, что это значит: на каждого пользователя, которого мне отправил Claude, его краулер прочитал 35 тысяч моих страниц.
Этот показатель я нашёл в дэшборде ИИ‑краулеров Cloudflare, см. изображение ниже. Поисковый краулер Anthropic Claude-SearchBot запросил за одну неделю 420 680 страниц. За ту же неделю Claude отправил мне 12 живых посетителей, что замерено Claude-User — отдельным user‑agent, которого Anthropic отправляет мне, когда живой человек просит Claude загрузить страницу. Это вот та плоская линия внизу.
Ситуация во вкладке трафика была ещё хуже. На этой неделе я передал 4,63 ГБ боту и 175 КБ людям, которых он мне отправил:
Как и многие, я люблю Anthropic и Claude. Мой веб‑сайт был создан с помощью Claude Code, и я пользуюсь Claude Code для улучшения правил безопасности Cloudflare API. Жалобы на то, что Claude скрейпит сайт, который я создал с его помощью Claude — это тот уровень иронии, с которым я смирился.
Но Anthropic и Claude не отправляли мне трафик, поэтому я заблокировал Claude-SearchBot в файрволле.
И они уважают это решение! Усилия краулера упали с 60 тысяч запросов в день до примерно 25 попыток в день. Вежливые компании‑разработчики ИИ действительно согласны на 403. (Это веб‑ответ «доступ запрещён».)
Отношение скрауленных страниц к привлечённым посетителям
Эта блокировка дала мне метрику, которую я теперь использую для всего: отношение скрауленных страниц к привлечённым посетителям. Google поступает по справедливости, Bing в девять раз хуже, но всё равно оправдывает себя. ИИ‑краулеры, обучающие LLM, далеки от их показателей:
В процессе подготовки материалов к посту я обнаружил, что поисковый ИИ‑краулер Amazon Amzn-SearchBot теперь стал моим краулером номер 1: примерно 117 тысяч запросов в день. Это почти вдвое больше темпа Claude за июнь. Он собирает информацию для ответов ИИ‑помощников Rufus и Alexa, поэтому никогда не отправляет веб‑трафик и не позволяет пользователям подписаться на мой список рассылки. Я сомневаюсь даже, что он указывает авторство и обратные ссылки.
Поэтому два дня назад я аналогичным образом заблокировал его. Это заняло две минуты.
Защите сильно поспособствовал и Cloudflare AI Crawl Control. Он блокирует заявляемых ботов обучения (GPTBot, ClaudeBot, CCBot, Bytespider) даже ещё до применения моих правил.
В том же дэшборде видно, что Bingbot выполняет 158 610 запросов и приводит 680 посетителей. Мои показатели перенаправленных из Bing посетителей растут, так что я с радуюсь, когда он меня скрейпит. И ещё видно, что после моей блокировки показатели Anthropic упали до 47 запросов.
Волна американских датацентров
В июле ко мне начали стучаться новые боты (или старые скрейперы адаптировались к моим географическим правилам). Теперь они стали приходить из США.
Стабильная волна безголовых браузеров Chrome на AWS. Они выполняли JavaScript и загрязнили мою статистику тысячами фальшивых «посетителей».

Решил я проблему самой надёжным правилом: challenge для всех датацентров.
Настоящие читатели заходят с Comcast и T‑Mobile, и почти никто из них не использует IP‑адреса AWS us-east-1. Исключения из этого правила — пользователи, сидящие через облачные рабочие столы или VPN, и поэтому правило реализует challenge, а не блокировку.
День, когда я отключил CAPTCHA
Функция JavaScript Detections Cloudflare вставляла на каждую страницу скрипт challenge. Наверно, в какой‑то момент я её включил? А может, она должна была помогать? Но узнал я об этом на этой неделе, когда пытался повысить оценку скорости своего сайта.
На телефоне из среднего ценового диапазона этот скрипт стоил лишних 2875 миллисекунд. Весь собственный JavaScript сайта выполняется за 278 мс. Функция защиты стала самой веской причиной того, что оценка Lighthouse для мобильных была равна 58, а на моём тарифе Cloudflare этот вердикт даже не читаем по правилам файрволла. То есть я получал штраф в 40 очков за телеметрию, которую никто не мог прочитать.
5 августа я отключил эту функцию и за час оценка Lighthouse поднялась до 99.
Спустя пять часов скрейпер Microsoft Azure запросил за час 23 тысячи страниц с более чем 80 IP‑адресов; каждый из запросов вежливо оставался в пределах установленной мной частоты. То есть можно прийти к выводу, что JavaScript Detections работал, но теперь я его отключил, и мне нужен был новый тариф.
К тому же появился ботнет резидентных IP, выдающий себя за Chrome версий с 118 по 120. Это версии из 2023 года, навсегда сохранившиеся в тулките скрейпинга.
Резидентные ботнеты
Резидентный ботнет скрейпит трафик, маршрутизируемый через тысячи обычных домашних Интернет‑соединений, арендуемые по запросу прокси‑компаний. Каждый запрос выглядит как реальный человек, пользующийся реальным провайдером.
Я уже видел подобное. В ноябре 2025 года я заметил в статистике посетителей нечто странное: десятки стран ежедневно посещали мой сайт почти равными количествами посетителей. Вот скриншот из моей аналитики:
Такое равное распределение по сорока странам — отличительный признак арендованной прокси‑сети: тысячи выглядящих реальными соединений, работающих на одного заказчика. Именно об этом предупреждал Родриго в ответах на мой твит.
Спустя девять месяцев эта картина повторилась, но на этот раз с американскими домашними подключениями. Два моих лучших правила сортировали трафик по его источнику. Одно выполняло challenge всех, кто находится вне Северной Америки. Другое реализовывало challenge всех запросов, поступающих от крупных поставщиков облачных сервисов. Этот новый трафик не относился ни к одной из категорий. Например, он поступал от домашнего пользователя из Огайо с провайдером Spectrum, поэтому ни одно из правил не помогало. Это можно наблюдать на графике уникальных IP‑адресов, ежедневно обращающихся к моему сайту в июле:

Я отреагировал двумя новыми правилами. Во‑первых, Azure и другие крупные облачные провайдеры присоединились к списку challenge датацентров.
Ещё я добавил своё любимое тупое правило: при помощи challenge проверять древние версии браузеров. Chrome версий с 100 по 130 получает CAPTCHA, то же самое со старым Firefox. Сначала я проверил свой реальный трафик: всего 0,54% моих реальных поисковых посетителей заходит через такие старые браузеры, и большинство их них пользуется Firefox 115 ESR, который я исключил из списка. Оставшиеся в прошлом ботнеты не проходят это правило.
Мои правила Cloudflare Security
Всё работает на Cloudflare WAF. Я выбрал тариф Pro за $25 в месяц. Логику можно применить к любому современному файрволлу. Вот правила, которыми я пользуюсь сегодня:
-
Блокировка Китая и Вьетнама. См. выше. Блокировка стран добавляет нулевые задержки для всех остальных.
-
Блокировка 12 SEO‑краулеров user‑agent. Semrush, Ahrefs, MJ12bot, DotBot, BLEXBot, Barkrowler и подобные им. Они честно идентифицируют себя, спасибо им за это.
-
Блокировка ИИ‑краулеров с плохим соотношением по user‑agent. На текущий момент:
Claude-SearchBotиAmzn-SearchBot. В то же время они могут читатьrobots.txt, поэтому знают, что их здесь не ждут. Мойrobots.txtотдельно приказываетGPTBot,ClaudeBot,CCBot,Bytespiderи другим объявленным ботам обучения уйти. Вежливые боты подчиняются. -
Все правила ниже пропускаются для верифицированных ботов. Cloudflare криптографически верифицирует Googlebot, Bingbot и Applebot. Порядок здесь важен: этот пропуск находится после моих правил блокировки. Заблокированный мной «верифицированный» бот остаётся заблокированным, но ни одна challenge не отображается боту Google.
-
Challenge для всех континентов, кроме Северной Америки. Довольно тупое правило, но я считаю его крайне важным. 97% моей аудитории находится в Северной Америке. Все остальные получают по одной невидимой CAPTCHA раз в 45 минут.
-
Challenge пустых user‑agents. Ни один браузер реального посетителя не отправит пустую строку user‑agent.
-
Challenge ASN 46 датацентров. Люди не посещают сайты через AWS (обычно).
-
Challenge устаревших браузеров. Правило для застрявших в прошлом ботнетов.
-
Ограничение частоты: 30 запросов страниц за 10 секунд на один IP. Статические файлы исключаются, поэтому правило никогда не задействуется при обычной загрузке страниц.
Кроме того, в моём robots.txt поимённо заблокированы все 12 SEO‑краулеров, а Cloudflare добавляет в edge‑сети поверх собственные блокировки обучения ИИ. Актуальный файл можно посмотреть здесь: patronview.com/robots.txt.
Мешают ли эти CAPTCHA реальным людям? Практически нет.
За последние 48 часов Cloudflare отправила 106 437 challenge. Решено было 252. Доля решённых составила 0,24%.
Мои затраты на сервер
Мой сайт работает на Cloudflare Workers с базой данных D1 и кэшем KV edge‑сети. Большинство запросов ботов попадает в кэш и стоит доли цента. Обычно мой счёт за весь сайт составляет примерно $90 в месяц. В один особо плохой месяц он вырос примерно на 500%.
99% счёта потребляют боты, а на 100% оплачиваю его я.
Реальные затраты неочевидны:
-
Моя статистика посетителей настолько загрязнилась, что я не мог доверять собственным показателям. Это навредило мне больше всего. Я пытаюсь делать бизнес. Мне нужно знать, что читают на моём сайте реальные люди, чтобы знать, что создавать дальше, но я не могу отличить их от ботов.
-
В один день всплеск промахов кэша при запросах Azure привёл к тому, что реальные посетители получали ошибки 504.
Если бы я находился на традиционном VPS и платил за CPU и трафик, то миллионы еженедельных запросов, более 99% из которых составляли боты, стали бы экзистенциальной проблемой. На edge‑платформе они остаются лишь раздражающим фактором.
Честно говоря, в высоких счетах частично виноват я сам. Сейчас я продолжаю подчищать неэффективные запросы и настройки кэша, из‑за которых ситуация в месяцы пиковых запросов ухудшилась. Я всё ещё думаю о переходе на VPS и хостинге собственной локальной базы данных, но сопротивляюсь этому соблазну, потому что мне нравится экспериментировать с платформой Cloudflare.
Думаю, что проблема скрейпинга усугубляется из‑за этой асимметрии. Затраты на скрейперов упали быстрее, чем улучшилась защита.
Что делать, если это произошло с вами
-
Изучайте логи сервера, а не статистику посетителей. В статистике отображается менее половины процента от реальной картины.
-
Блокируйте по ASN, а не по IP. Ротация IP происходит постоянно, а сети остаются одними и теми же.
-
Если посетителями могут быть люди, используйте challenge, а не блокировку. Managed challenge невидима для большинства реальных людей. К тому же она позволяет замерять показатели.
-
Смотрите на долю решённых challenge. Доля в 0,2% решённых означает, что к вам заходят боты, поэтому это правило нужно оставить. Доля в 30% означает, что страдают живые люди, а значит, правило нужно менять.
-
Профилируйте затраты на функции защиты. В моём случае скрипт CAPTCHA был затратнее всего сайта.
Заключение
Сработало ли всё это?
За 24 часа после внедрения этих правил Cloudflare заблокировала 46 729 запросов. 43 150 из них поступило от одного только краулера Amazon, который всё ещё долбился в блокировку, установленную за два дня до этого.
Также сервис отправил 63 969 challenge, из которых было решено всего 552.
То есть правила работают. Надеюсь, они продолжат пропускать нужных мне ботов, а также людей. По крайней мере, какое‑то время.
Должен сказать, что это похоже на игру «Ударь крота». Каждые несколько недель мне приходится тратить время на борьбу с чем‑то новым.

Здесь есть настоящий конфликт: мне нужно, чтобы Google, Bing и DuckDuckGo краулили мой сайт и присылали мне новых читателей, но я не хочу, чтобы с него скрейпили данные все остальные. При этом резидентные ботнеты уже могут решать CAPTCHA и при этом выглядят как реальные браузеры. Блокировать их на уровне сети невозможно.
Ситуация со скрейпингом ухудшается, потому он становится дешевле, поэтому я считаю, что единственное решение проблемы — экономическое. Cloudflare создаёт систему pay‑per‑crawl, при которой краулеры платят за запрос в edge‑сети. Я с радостью продам Amazon эти 3,5 миллиона страниц в месяц по сходной цене.
А пока такой рынок не возник, я пользуюсь простым правилом: краулер, не отправляющий мне посетителей, блокируется.
Если вы тоже испытываете подобные проблемы, то напишите мне: hello@nickgray.net, хотелось бы сравнить наши показатели.
Приложение: выражения правил
А теперь информация для технарей. Вот реальные выражения описанных выше правил, скопированные из моей зоны Cloudflare с помощью API. Они написаны на языке правил Cloudflare; наверно, с небольшими доработками их можно портировать в большинство файрволлов. Я убрал лишь пару вещей, связанных с поддержанием внутреннего порядка.
Блокировка Китая и Вьетнама. Два отдельных правила, действие: Block.
(ip.src.country in {"CN"})(ip.src.country eq "VN")
Блокировка SEO‑краулеров по user‑agent. Действие: Block.
(lower(http.user_agent) contains "barkrowler") or(lower(http.user_agent) contains "thinkbot") or(lower(http.user_agent) contains "brightbot") or(lower(http.user_agent) contains "mj12bot") or(lower(http.user_agent) contains "semrushbot") or(lower(http.user_agent) contains "siteauditbot") or(lower(http.user_agent) contains "ahrefsbot") or(lower(http.user_agent) contains "ahrefssiteaudit") or(lower(http.user_agent) contains "dataforseobot") or(lower(http.user_agent) contains "dotbot") or(lower(http.user_agent) contains "blexbot") or(lower(http.user_agent) contains "splitsignalbot")
Блокировка ИИ‑краулеров с плохим соотношением. Действие: Block. Обратите внимание на небольшое исключение: заблокированный краулер может читать robots.txt — тот самый файл, сообщающий о причинах его блокировки.
(http.request.uri.path ne "/robots.txt" and (http.user_agent contains "Claude-SearchBot" or http.user_agent contains "Amzn-SearchBot"))
Пропуск для верифицированных ботов всего, что ниже. Действие: Skip (оставшиеся правила + ограничение по частоте). Одно выражение. Здесь важен порядок: правило находится после блокировок выше, поэтому заблокированный бот остаётся заблокированным, зато Googlebot никогда не видит challenge.
(cf.client.bot)
Challenge для всех континентов, кроме Северной Америки. Действие: Managed Challenge. Исключение связано с тем, что Гуам, Американское Самоа и Северные Марианские Острова — это территории США с кодами континента Океания. Там живут реальные американские читатели. T1 — это сеть Tor.
((ip.src.asnum in {212238 139341 9009}) or (ip.src.continent in {"AF" "AN" "AS" "OC" "SA" "T1" "EU"}))and not cf.client.botand not (ip.src.country in {"GU" "AS" "MP"})
Challenge пустых user‑agents. Действие: Managed Challenge.
(http.user_agent eq "") and not cf.client.bot
Challenge датацентров и облачных ASN. Действие: Managed Challenge. AWS, Azure, Google Cloud, Oracle, Alibaba, DigitalOcean, Vultr, Linode, OVH, Hetzner, Hurricane Electric и все хостинг‑сети, которые я поймал на скрейпинге.
(ip.src.asnum in {14618 16509 8987 396982 14061 20473 63949 16276 24940 213230 55286 64286 36352 18779 40676 397423 46261 399073 2914 13332 30058 11798 21769 62874 202015 55933 393886 27411 396362 395954 396190 19148 30633 8075 8070 8068 8069 31898 45102 37963 36351 136907 45090 207990 17497 6939}) and not cf.client.bot
Challenge устаревших версий браузеров. Действие: Managed Challenge. В тарифе Pro Cloudflare нет возможности использования regex в выражениях правил (эта функция есть в Business), поэтому пришлось задействовать 55 условий contains. Firefox 115 пропущен, потому что это старый релиз ESR, с которым всё ещё работают мои реальные посетители, оставшиеся на старых операционных системах. Каждый квартал при устаревании версий нужно вносить в это правило изменения.
Полное выражение
(http.user_agent contains "Chrome/100." or http.user_agent contains "Chrome/101." or http.user_agent contains "Chrome/102." or http.user_agent contains "Chrome/103." or http.user_agent contains "Chrome/104." or http.user_agent contains "Chrome/105." or http.user_agent contains "Chrome/106." or http.user_agent contains "Chrome/107." or http.user_agent contains "Chrome/108." or http.user_agent contains "Chrome/109." or http.user_agent contains "Chrome/110." or http.user_agent contains "Chrome/111." or http.user_agent contains "Chrome/112." or http.user_agent contains "Chrome/113." or http.user_agent contains "Chrome/114." or http.user_agent contains "Chrome/115." or http.user_agent contains "Chrome/116." or http.user_agent contains "Chrome/117." or http.user_agent contains "Chrome/118." or http.user_agent contains "Chrome/119." or http.user_agent contains "Chrome/120." or http.user_agent contains "Chrome/121." or http.user_agent contains "Chrome/122." or http.user_agent contains "Chrome/123." or http.user_agent contains "Chrome/124." or http.user_agent contains "Chrome/125." or http.user_agent contains "Chrome/126." or http.user_agent contains "Chrome/127." or http.user_agent contains "Chrome/128." or http.user_agent contains "Chrome/129." or http.user_agent contains "Chrome/130." or http.user_agent contains "Firefox/100." or http.user_agent contains "Firefox/101." or http.user_agent contains "Firefox/102." or http.user_agent contains "Firefox/103." or http.user_agent contains "Firefox/104." or http.user_agent contains "Firefox/105." or http.user_agent contains "Firefox/106." or http.user_agent contains "Firefox/107." or http.user_agent contains "Firefox/108." or http.user_agent contains "Firefox/109." or http.user_agent contains "Firefox/110." or http.user_agent contains "Firefox/111." or http.user_agent contains "Firefox/112." or http.user_agent contains "Firefox/113." or http.user_agent contains "Firefox/114." or http.user_agent contains "Firefox/116." or http.user_agent contains "Firefox/117." or http.user_agent contains "Firefox/118." or http.user_agent contains "Firefox/119." or http.user_agent contains "Firefox/120." or http.user_agent contains "Firefox/121." or http.user_agent contains "Firefox/122." or http.user_agent contains "Firefox/123." or http.user_agent contains "Firefox/124.")and not cf.client.bot
Ограничение частоты. Действие: Managed Challenge, когда один IP превышает 30 запросов за 10 секунд. Считаются только пути без расширений, поэтому сорок изображений и таблиц стилей при обычной загрузке страниц никогда не приводят к срабатыванию этого правила. (Строго говоря, счётчик работает для IP на каждый датацентр Cloudflare, поэтому распределённый ботнет может обойти это ограничение. Правило отлавливает только самых ленивых.)
(http.request.uri.path.extension eq "") and not cf.client.bot
И одно дополнительное правило, которое в обычном состоянии отключено: кнопка паники. То же выражение, что и для ограничения частоты, но в виде простого Managed Challenge при каждом запросе страницы от всех, кто не относится к верифицированным ботам. Когда резко возрастает нагрузка на сайт со стороны скрейперов, я включаю его, жду, пока поток схлынет, а через час снова отключаю.
ссылка на оригинал статьи https://habr.com/ru/articles/1068266/