403 — это не 401 и не 404
401 Unauthorized означает, что серверу нужны учётные данные — либо те, что вы отправили, не приняты. Если отправить верные данные, ответ изменится.
403 Forbidden означает, что дело не в учётных данных. Запрос поняли и отказали. Авторизация может не помочь, потому что то, что вам отказало, может быть всё равно, кто вы.
404 иногда используют намеренно вместо 403, чтобы не подтверждать, что путь вообще существует. Если для одного и того же URL вы видите 403 в одном окружении и 404 в другом, это осознанный выбор конфигурации, а не баг.
Уровень 1 — отказал ваш origin
Самый простой случай. Файл существует, но веб-сервер его не отдаёт: права на директорию не включают пользователя веб-сервера, в директории нет индексного файла и листинг отключён, сработало правило deny в .htaccess или nginx, либо само приложение проверило роль и вернуло 403.
Как распознать. Страница ошибки выглядит как часть вашего стека: страница Apache или nginx по умолчанию, либо собственный оформленный экран приложения «у вас нет доступа». В логе доступа вашего origin есть этот запрос со статусом 403 — это и есть главный признак, потому что запрос вообще дошёл до origin.
Уровень 2 — сработало правило WAF
Веб-файрвол приложений (WAF) проверяет запрос и блокирует его, если тот совпадает с сигнатурой атаки. Именно этот уровень порождает самые запутанные 403, потому что человеку, отправившему запрос, он кажется совершенно безобидным.
Обычные ложные срабатывания вовсе не экзотика: редактор CMS сохраняет пост, где в примере кода встречается слово SELECT, поле формы содержит фрагмент HTML, в описании товара апостроф стоит в неудачном месте. Наборы правил, которые идут с WAF, написаны, чтобы ловить попытки инъекций, а обычный человеческий текст иногда похож на них.
На cdn.com.tr WAF — это ModSecurity с OWASP Core Rule Set, и заблокированный запрос получает брендированную страницу 403 с ID запроса. В этом ID вся суть: это идентификатор запроса, записанный в журнал аудита, так что можно точно узнать, какое правило сработало и на каком поле, вместо того чтобы гадать. Страница логов WAF в панели показывает заблокированные события с категорией атаки, страной, IP и правилом, которое сработало.
Решение, которое не снижает защиту. Исключите конкретное поле на конкретном пути — например, тело поста на URL редактора, — а не отключайте семейство правил целиком или WAF для всего сайта. Узкое исключение не стоит вам ничего; широкое — незаметно снимает защиту со всех остальных страниц.
Уровень 3 — блокировка по стране или сети
Географические и сетевые блокировки применяются до того, как запрос дойдёт до вашего приложения, и тоже дают 403. Если у вас чёрный список стран, отказ увидят все из этой страны. Если вы блокируете по ASN — номеру автономной системы, который охватывает всю сеть провайдера, — отказ получит каждый посетитель этого провайдера, а это гораздо более широкая сеть, чем кажется на слух.
Ловушка, о которой стоит знать. Мобильные операторы прячут миллионы обычных абонентов за горсткой ASN, а мобильные IP постоянно меняются. Посетитель, у которого всё было в порядке на wifi, может получить отказ на мобильном интернете и описать это как «сайт не работает у меня на телефоне». Если жалобы на 403 группируются вокруг мобильных сетей, сначала смотрите на свои блокировки, а не на приложение.
Такие блокировки стоит периодически проверять по расписанию. Правило, добавленное во время инцидента, обычно переживает сам инцидент.
Уровень 4 — защита от хотлинка и списки IP
Защита от хотлинка отказывает в запросах на ваши изображения и файлы, если заголовок Referer указывает на чужой сайт. Она делает свою работу, но заодно отказывает и легитимному трафику, о котором вы забыли: собственному staging-домену, почтовому клиенту, отображающему картинку, приложению, которое вообще не отправляет referer. Симптом узнаваем сразу — страницы грузятся, изображения нет.
Списки разрешённых и запрещённых IP — самый грубый уровень. Список разрешений на админ-пути — отличный контроль ровно до того дня, когда IP вашего офиса меняется, а про существование списка уже никто не помнит. Когда 403 касается ровно одного человека и больше никого — обычно дело именно в этом.
Как последовательно найти причину
Идите снаружи внутрь. Это займёт минуты и куда надёжнее гадания.
1. Прочитайте страницу ошибки. Брендированная страница с ID запроса означает решение на edge — правило WAF, гео- или ASN-блокировку. Стандартная страница сервера или оформление вашего собственного приложения означает, что решение принял origin.
2. Если есть ID запроса, найдите его в логах. Лог WAF даёт ID правила, поле, на котором оно сработало, и значение, которое его вызвало. Это самый быстрый путь от симптома к причине: разговор превращается из «сайт иногда меня блокирует» в «правило 942100 сработало на теле поста».
3. Проверьте, касается ли это только вас. Попробуйте зайти из другой сети или с мобильного интернета. Если это только вы — смотрите списки IP. Если это все из одной страны — смотрите гео-блокировки.
4. Проверьте, касается ли это только одного пути. Если отказывает один URL, а остальной сайт работает, дело в собственных правилах origin или в правиле WAF, привязанном именно к этому пути.
5. И только теперь смотрите на origin. Если запроса вообще нет в логе доступа вашего origin, ему отказали раньше, чем он туда дошёл, и никакие изменения на origin не помогут.
Как исправить, не потеряв защиту
Первый инстинкт, когда WAF блокирует легитимный запрос, — выключить WAF для этого сайта целиком. Это «работает» в том смысле, что симптом исчезает, — но заодно снимает защиту со всех остальных запросов, о которых вы даже не думали.
Лучшая последовательность: воспроизвести блокировку, прочитать ID правила из лога, написать исключение для этого правила на этом поле и этом пути, затем воспроизвести ещё раз, чтобы убедиться, что запрос проходит, а правило по-прежнему работает везде остальном. На cdn.com.tr именно для этого нужны правила доставки и пресеты безопасности: исключение живёт в конфигурации, разворачивается на все edge и видно в истории действий вместе с тем, кто его внёс, и значениями до и после.
Если вы не можете воспроизвести блокировку, не начинайте писать исключения. Исключение для правила, которое не было причиной, — это защита, снятая просто так.
Частые вопросы
Почему один и тот же URL работает в одном браузере и не работает в другом?
Запросы не идентичны. Разные user agent, разные cookie и, что особенно важно, разные сети — браузер на wifi и браузер на мобильном интернете уходят с разных IP-адресов. Если отказ следует за сетью, а не за браузером, смотрите блокировки по IP, стране или ASN, а не на своё приложение.
Мой WAF блокирует мой собственный редактор при сохранении поста. Что менять?
Найдите ID правила в заблокированном событии, затем исключите это правило для поля, которое отправляет редактор, на URL редактора. Не исключайте весь путь целиком и не отключайте семейство правил для сайта: те же правила защищают остальные ваши формы, а попытки инъекций приходят через те же поля, что и легитимный текст.
Может ли 403 закэшироваться?
Может, и закэшированный 403 — неприятный сюрприз: причина уже исчезла, а симптом остаётся. Ответы с ошибками в целом стоит отдавать с коротким TTL или вообще не кэшировать. Если причину уже исправили, а посетители всё ещё видят отказ, сначала очистите кэш для этого пути, а уже потом продолжайте разбираться.
Для чего нужен ID запроса на странице ошибки?
Это идентификатор именно того запроса в журнале аудита. Посетитель может прислать его вам, а вы — найти, какое правило сработало, на каком поле и с каким значением. Без него разобраться в жалобе «иногда вылезает 403» практически невозможно.
Вредит ли 403 SEO?
Да, если 403 отдаётся на странице, которую вы хотите индексировать: краулеру откажут точно так же, как любому другому клиенту, и рано или поздно URL выпадет из индекса. Особенно стоит следить за слишком широкой блокировкой, которая задевает поисковых краулеров, — проверяйте, что важные для вас страницы отвечают 200 именно краулеру, а не только вашему браузеру.