Сервер отдавал 404 только поисковым роботам: правило от прошлого админа
Сайт открывается, формы работают, в панели мониторинга всё зелёное — а органический трафик тихо ползёт вниз третью неделю подряд. Никто из команды не может это увидеть глазами, потому что проблема бьёт только по одному классу посетителей: поисковым роботам. Это разбор реального инцидента — как страницы, годами стоявшие в индексе, начали получать 404 именно от Googlebot и Яндекс.Бота, и почему причина оказалась в одной строке конфига nginx, оставленной предыдущим администратором для совсем другой задачи.
Содержание
Что заметили
Первый сигнал пришёл не от мониторинга и не от пользователей — от Search Console. В отчёте покрытия начали расти строки «Проиндексировано, но не в индексе» и «Обнаружено, не проиндексировано» — с постепенным сползанием в прямые ошибки: «Ошибка 404» на страницах, которые раньше исправно индексировались и приносили трафик. Яндекс.Вебмастер показывал похожую картину в разделе «Индексирование → Диагностика».
Дальше подключили аналитику. Сессии из органического поиска шли вниз ступеньками — не обвалом за ночь, а медленным, но устойчивым снижением на протяжении нескольких недель. Прямой трафик и переходы по ссылкам оставались стабильными, платный трафик тоже не изменился. Это сразу сузило круг подозреваемых: проблема была не в сайте как таковом (иначе просели бы все каналы), а в чём-то, что видят только поисковые системы.
Проверка руками ничего не давала. Открываешь проблемную страницу в браузере — 200, всё рендерится, контент на месте. Просишь коллегу открыть с телефона на другом провайдере — то же самое. Curl без специальных заголовков — тоже 200. На этом моменте инцидент завис почти на день: все базовые проверки говорили «сайт работает», а Search Console настаивала на обратном.
Первые гипотезы — и почему они отпали
Когда симптом «поисковики видят не то, что видят люди» подтвердился, начали перебирать стандартный список причин cloaking-подобных проблем.
- Ручные санкции или алгоритмический фильтр. Проверили раздел «Меры, принятые вручную» в Search Console — чисто. Резкого падения позиций по всем запросам разом тоже не было, падал именно трафик на конкретные URL, у которых появлялась ошибка обхода.
- Проблема с DNS или миграцией хостинга. Записи A/AAAA не менялись несколько месяцев, TTL в норме, никаких недавних переносов. Отпало быстро.
- Ошибка в sitemap.xml. Файл провалидировали построчно — все URL актуальны, никаких редиректов или отсутствующих страниц внутри самой карты сайта.
- robots.txt случайно закрыл раздел. Файл не менялся по дате модификации уже давно,
Disallowне задевал проблемные разделы. Проверили инструментом «Файл robots.txt» в Search Console — правила читаются так, как ожидалось. - Бан по IP на файрволе или в fail2ban. Посмотрели
fail2ban-client statusи активные джейлы — диапазоны IP Google и Яндекса в банах не фигурировали. Это логично: fail2ban обычно банит по числу неудачных попыток или запросов, а не по типу клиента. - Rate limiting в nginx. Проверили счётчики
limit_req_zoneи логи с пометкойlimiting requests— совпадений с обращениями поисковых роботов не нашли, лимиты были рассчитаны на явные всплески, а не на штатный обход краулером. - CDN отдаёт устаревший или неверный кеш только части клиентов. Сравнили заголовки
Cache-ControlиAgeдля проблемных URL — кеш был свежим, да и характер ошибки (404, а не устаревший контент) не укладывался в эту версию.
Каждая из этих проверок занимала от десяти минут до часа, и ни одна не била точно в цель. Общий вывод после этого круга: раз проблема воспроизводится стабильно и только для роботов, разумно перестать гадать и начать имитировать самого робота.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверКак нашли настоящую причину
Переломный момент — обычный curl, но с точным User-Agent поискового бота вместо дефолтного.
# обычный запрос — то, что видит браузер
curl -I https://example.ru/nekaya-stranica/
# запрос от имени Googlebot
curl -I -A "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)" \
https://example.ru/nekaya-stranica/
# запрос от имени Яндекс.Бота
curl -I -A "Mozilla/5.0 (compatible; YandexBot/3.0; +http://yandex.com/bots)" \
https://example.ru/nekaya-stranica/
Первый запрос вернул 200 OK. Второй и третий — 404 Not Found. Разница была только в заголовке User-Agent. На этом моменте стало ясно, что дело не в контенте, не в БД и не во внешней инфраструктуре — где-то на сервере есть логика, которая принимает решение по строке User-Agent.
Дальше — грубый, но эффективный способ подтвердить масштаб: пройтись по access-логу nginx и посмотреть, какие запросы с упоминанием ботов в User-Agent получают 4xx.
awk '$0 ~ /[Bb]ot/ {print $9, $0}' /var/log/nginx/access.log \
| grep -E '^4' | tail -n 50
Вывод показал ровный поток 404 именно на запросах с подстрокой «bot» в User-Agent — включая Googlebot, YandexBot, Bingbot и AhrefsBot вперемешку с реальными парсерами вроде GPTBot и ClaudeBot. Дальше нужно было понять, кто и когда добавил правило, которое так решает. Конфиги на сервере хранились в git (в отдельном репозитории для /etc/nginx), так что помог git log и git blame по файлам в conf.d.
cd /etc/nginx
git log --oneline -- conf.d/
git blame conf.d/block-ai-bots.conf
Файл block-ai-bots.conf появился несколько месяцев назад, автор — предыдущий администратор, сообщение коммита в духе «блокируем ИИ-краулеров, грузят сервер». Дальше — чтение самого файла.
Что было в конфиге на самом деле
Правило оказалось map-блоком в http-контексте, который вычисляет флаг блокировки по User-Agent, плюс if в нужных server-блоках, который отдаёт 404 при сработавшем флаге.
# /etc/nginx/conf.d/block-ai-bots.conf
map $http_user_agent $blocked_agent {
default 0;
"~*GPTBot" 1;
"~*CCBot" 1;
"~*ClaudeBot" 1;
"~*Bytespider" 1;
"~*Amazonbot" 1;
"~*anthropic-ai" 1;
"~*bot" 1; # добавлено позже — «на всякий случай»
# исключения для нормальных поисковиков — добавлены ещё позже
"~*googlebot" 0;
"~*yandexbot" 0;
"~*bingbot" 0;
}
и в конфиге сайта:
server {
...
if ($blocked_agent) {
return 404;
}
...
}
Идея была разумной: летом и осенью 2025–2026 года волна ИИ-краулеров (GPTBot, ClaudeBot, Bytespider, CCBot и десятки менее известных) действительно ощутимо нагружает серверы, обходя сайты целиком ради обучающих датасетов, и многие администраторы закрывают их по User-Agent как самый быстрый способ снять нагрузку. Проблема — в порядке строк и в самой логике директивы map.
Директива map в nginx проверяет шаблоны в том порядке, в котором они записаны в файле, и использует первое совпадение — а не самое точное или самое позднее. Строка "~*bot" 1 — это регулярное выражение без привязки к границам слова, оно совпадает с любой подстрокой «bot» в User-Agent, включая «googleBOT», «YandexBOT» и «bingBOT». Поскольку эта строка стоит в файле раньше строк-исключений "~*googlebot" 0 и "~*yandexbot" 0, до исключений дело просто не доходит: map уже нашёл совпадение на общей строке «bot» и вернул 1. Строки-исключения физически присутствовали в конфиге, выглядели правильно при беглом чтении и были абсолютно нерабочими.
Другими словами: кто-то дописал «заглушку про всех остальных ботов» как страховку, а через какое-то время (видимо, другой человек или тот же администратор — сообщения коммитов расходились) дописал исключения для поисковиков ниже этой заглушки, не зная, что порядок строк в map решает всё.
Почему это не заметили раньше
Несколько факторов сложились так, что баг спокойно жил в проде несколько месяцев.
- Он бил только по User-Agent с «bot» внутри строки. Реальные посетители, синтетические проверки uptime-мониторинга (обычно с обычным браузерным UA) и внутренние скрипты команды под это правило не попадали — все видели рабочий сайт.
- Правило тестировали при деплое, но не тем инструментом. Проверка «работает ли блокировка ИИ-ботов» делалась через curl с явным User-Agent известного плохого бота (например, GPTBot) — и она честно возвращала 404, как и задумано. Проверку с User-Agent Googlebot никто не запускал, потому что цель правила была прямо противоположной — не трогать поисковики.
- Эффект нарастал медленно. Googlebot и YandexBot не пересканируют весь сайт мгновенно — обход идёт волнами, по расписанию краулингового бюджета конкретного домена. Так что 404 сначала прилетали на редко обходимые страницы, потом на более частотные, и полная картина в Search Console/Вебмастере сложилась только спустя недели, с задержкой самих отчётов индексирования.
- 4xx-метрики на уровне сервера не били тревогу. Общий процент 4xx-ответов в мониторинге не выглядел аномальным — трафик роботов составлял небольшую долю от общего числа запросов, а панели мониторинга смотрели на агрегированную долю кодов ответа, а не на срез по User-Agent.
- Конфиг лежал в отдельном репозитории без code review. Правки в
/etc/nginxкоммитились напрямую в основную ветку, без пул-реквеста и без второго взгляда — доработка с исключениями для поисковиков ушла в прод так же тихо, как и первая версия правила.
Похожая механика — общее правило перекрывает более узкое из-за порядка строк — разбиралась и в другом инциденте: правило nginx поставили выше, и трафик ушёл в заглушку. Там дело было в location-блоках, здесь — в map, но природа ошибки одна: nginx делает ровно то, что написано, а не то, что имелось в виду.
Как исправили и что проверили
Первым делом переписали map-блок так, чтобы более специфичные и «разрешающие» строки шли раньше общей заглушки — благо порядок совпадений в map это позволяет использовать осознанно, если понимать правило «первое совпадение побеждает».
map $http_user_agent $blocked_agent {
default 0;
# сначала — явные исключения для легитимных поисковиков
"~*googlebot" 0;
"~*yandexbot" 0;
"~*bingbot" 0;
"~*duckduckbot" 0;
"~*applebot" 0;
# затем — известные ИИ-краулеры, которых блокируем
"~*GPTBot" 1;
"~*CCBot" 1;
"~*ClaudeBot" 1;
"~*Bytespider" 1;
"~*Amazonbot" 1;
"~*anthropic-ai" 1;
# общего "~*bot" больше нет — слишком широкий шаблон,
# рано или поздно снова заденет кого-то легитимного
}
Общую заглушку "~*bot" 1 убрали совсем — она изначально была плохой идеей именно из-за своей неточности. Вместо неё завели явный, поддерживаемый список конкретных User-Agent ИИ-краулеров, который расширяют по мере появления новых — источником служит открытый список известных ботов (например, публикуемый Cloudflare и другими CDN-провайдерами) и собственные наблюдения по логам.
Проверка после правки — тот же набор curl-запросов с User-Agent Googlebot, YandexBot, Bingbot и парой ИИ-ботов, плюс ручной прогон каждой строки map через nginx -T, чтобы увидеть итоговую сконфигурированную карту:
nginx -t && nginx -T | grep -A 20 'map \$http_user_agent'
Дальше — то, что должно было закрыть класс проблемы, а не только конкретный баг:
- Автоматическая проверка обхода поисковиками. Настроили короткий cron-скрипт, который раз в день curl'ит десяток ключевых URL с User-Agent Googlebot и YandexBot и шлёт алерт, если хоть один вернул не
200. - Code review для конфигов nginx. Ветку
conf.dв репозитории конфигов закрыли прямыми пушами в основную ветку, изменения теперь идут через pull request с обязательным вторым ревью — специально для правил, которые трогаютif,mapиreturnна уровне сервера. - Регулярный чек-лист по Search Console и Яндекс.Вебмастеру. Раз в неделю кто-то из команды смотрит разделы индексирования и ошибок обхода, а не ждёт, пока падение трафика станет заметным в общей аналитике.
- Документация по существующим правилам блокировки ботов. В репозитории появился короткий README рядом с
block-ai-bots.conf— что делает правило, почему именно так упорядочено, и памятка «не добавляй общий шаблонbot, добавляй конкретные имена».
Отдельно обсуждали переход от чистой проверки User-Agent (который легко подделать) к верификации бота через обратный DNS-запрос — это надёжнее, если важно отличить настоящего Googlebot от того, кто просто представился им в заголовке. Для задачи «не пускать известных ИИ-краулеров» такая строгая проверка избыточна, а вот для более чувствительных сценариев — тема отдельного разбора.
Если похожая история — сайт стабильно работает для людей, но что-то странное происходит именно с обходом поисковиками или другими автоматизированными клиентами, — первый шаг всегда один: воспроизвести запрос с точным User-Agent проблемного клиента и посмотреть на реальный ответ сервера, а не полагаться на «в браузере же всё работает». Читать логи в такой ситуации быстрее, чем перебирать гипотезы вслепую — как это делать, разобрано в статье как читать логи и находить причину сбоя. А если по симптомам похоже, что дело в поведении самого робота-индексатора, стоит заглянуть в разбор случая, когда робот-индексатор положил сайт — с противоположной, но связанной проблемой: не заблокированный, а слишком агрессивный обход.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверНужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.
Частые вопросы
Как быстро проверить, не блокирует ли сервер поисковых роботов прямо сейчас?
Выполните curl -I с явным User-Agent Googlebot и YandexBot на несколько ключевых страниц и сравните код ответа с обычным запросом без специального заголовка. Расхождение в коде ответа — прямой признак того, что сервер по-разному обрабатывает эти запросы.
Почему браузерные проверки и мониторинг uptime не увидели проблему?
Потому что и браузер, и большинство систем мониторинга используют обычный User-Agent, под который правило блокировки не подпадало. Проблема была видна только тем клиентам, чей User-Agent содержал специфичную подстроку — в данном случае «bot».
В чём именно ошибка в конфиге nginx, если коротко?
Директива map использует первое совпадение по порядку строк в файле, а не самое точное. Общий шаблон "~*bot" 1" стоял раньше специфичных исключений для Googlebot и YandexBot, поэтому исключения физически никогда не выполнялись.
Стоит ли вообще блокировать ИИ-краулеров на уровне nginx?
Это решение зависит от вашей ситуации: если такие боты создают заметную нагрузку или забирают контент нежелательным образом, блокировка оправдана. Главное — использовать точные, поддерживаемые списки конкретных User-Agent, а не широкие шаблоны вроде «bot», которые случайно задевают легитимные поисковые системы.
Как понять, что поисковик перестал видеть страницы именно из-за сервера, а не из-за санкций или технической ошибки в контенте?
Проверьте раздел ручных мер в Search Console (должен быть пуст), сверьте, падает ли именно органический трафик при стабильном прямом и платном, и повторите тест с curl под User-Agent робота — если код ответа отличается от обычного запроса, причина почти всегда на уровне сервера или CDN, а не в контенте.
Можно ли было поймать эту проблему раньше, до заметного падения трафика?
Да — регулярный автоматический прогон ключевых URL с User-Agent основных поисковых роботов (не только человекочитаемый мониторинг) обнаружил бы расхождение в кодах ответа в первый же день после деплоя проблемного правила, а не через несколько недель по отчётам индексирования.
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →