Перейти к основному содержимому

Заблокированные запросы: ответ, аудит и метрики

Каждая блокировка видна в трёх местах одновременно: клиент получает HTTP-ответ с кодом отказа, оператор — событие в потоке аудита, мониторинг — приращение счётчика блокировок в метриках.

Коды ответа: 403 и 405

Код отказа зависит от того, на каком измерении политики запрос не прошёл.

КодКогда возвращаетсяЧто это значит для оператора
405 Method Not AllowedПуть совпал хотя бы с одним правилом, но ни одно из совпавших правил не разрешает этот метод.Ресурс политикой предусмотрен, запрошенная операция над ним — нет.
403 ForbiddenПуть не совпал ни с одним правилом.Ресурс политикой не предусмотрен вообще; метод в этом случае не проверяется.

Разделение кодов сделано для диагностики: 405 обычно означает, что политика описана правильно, но клиент использует незаявленную операцию, а 403 — что путь не попал в политику (опечатка в шаблоне, новая точка API, сканирование чужих путей).

Заблокированный запрос получает ответ с пустым телом:

HTTP/1.1 403 Forbidden
Content-Length: 0
Connection: close

Тело, детали правила и причина блокировки клиенту не раскрываются: внешняя сторона не должна по ответам восстанавливать структуру политики и внутреннего API. Соединение после ответа закрывается.

Что происходит с запросом внутри контура

КомпонентМомент проверкиПоследствия блокировки
netgap-gatewayСразу после разбора строки запроса и заголовков, до постановки в очередь.Запрос не попадает в очередь запросов, клиентское соединение не паркуется в пуле, исполнитель о запросе не узнаёт. Клиент получает 403/405 немедленно.
netgap-executorВ обработке полученного запроса, до вызова целевого сервиса.Целевой сервис не вызывается; шлюзу через мост ответов возвращается ответ 403/405 с пустым телом и нулевым временем вызова целевого сервиса, шлюз отдаёт его ожидающему клиенту.

Блокировка на исполнителе при разрешающей политике шлюза — штатный признак рассинхронизации конфигураций: политика уже ужесточена в доверенном сегменте и ещё не обновлена на границе (или наоборот). Разбирается по компоненту, чья метрика блокировок растёт; оба случая по шагам разобраны ниже, в разделе Сценарии блокировки.

Как блокировка отражается на остальных показателях:

  • netgap_gateway_requests и netgap_executor_requests увеличиваются и для заблокированного запроса — счётчик принятых запросов растёт до проверки политики;
  • гистограммы задержек шлюза (netgap_gateway_total_latency_seconds, netgap_gateway_processing_time_seconds) заблокированными запросами не наполняются: ответ отдаётся до постановки в очередь;
  • netgap_executor_target_call_time_seconds для заблокированного запроса не пишется — вызова целевого сервиса не было;
  • netgap_gateway_errors и netgap_executor_errors не увеличиваются: блокировка — это штатное решение политики, а не ошибка обработки.

Сценарии блокировки

Запрос заблокирован шлюзом

Обычный случай при одинаковой политике у обоих компонентов: решение принимается на границе контура, дальше запрос не идёт.

Для незнакомого пути (GET /internal/debug) картина та же, меняются только решение и коды: BlockedPath, reason=path, ответ 403 Forbidden.

Запрос заблокирован исполнителем

Случай расхождения политик: шлюз работает в mode: AllowAll (например, ограничение ещё не раскатано на границу), а у исполнителя уже настроен AllowList. Запрос доходит до доверенного сегмента, но целевого сервиса не достигает.

Отличия от блокировки на шлюзе, важные при разборе инцидента:

  • запрос занимает место в очереди шлюза и удерживает клиентское соединение в пуле до прихода ответа — блокировка на исполнителе не экономит ресурсы границы;
  • в аудите шлюза есть штатные http request и received response, а событие request blocked by http filter приходит только от исполнителя;
  • растёт netgap_executor_blocked_requests, тогда как netgap_gateway_blocked_requests остаётся нулевым — это и есть характерный признак расхождения политик;
  • гистограмма netgap_executor_target_call_time_seconds не пополняется, а target_processing_time в ответе равен нулю, поэтому в netgap_gateway_target_call_time_seconds такой запрос попадает нулевым значением; гистограммы задержек шлюза при этом заполняются как у обычного запроса.

Обратный перекос — правила на шлюзе и AllowAll у исполнителя — снаружи выглядит как первый сценарий: клиент получает отказ от шлюза, исполнитель о запросе не узнаёт. Скрытый риск здесь в том, что исполнитель перестаёт быть последним рубежом перед целевым сервисом, поэтому секцию http_filter держат одинаковой в обеих конфигурациях. Если такая асимметрия выбрана осознанно, см. разбор остающихся рисков в статье Схемы размещения фильтра.

Событие аудита

Каждая блокировка фиксируется как событие уровня warn в потоке аудита (target_id: Audit) и дублируется в технологический лог. Событие формируется обоими компонентами независимо, поэтому запрос, заблокированный шлюзом, даёт одну запись, а редкий случай блокировки на исполнителе — запись со стороны исполнителя.

КомпонентСобытиеКогда формируется
netgap-gatewayrequest blocked by http filterЗапрос не прошёл фильтр на границе контура и не был поставлен в очередь.
netgap-executorrequest blocked by http filterЗапрос не прошёл фильтр перед вызовом целевого сервиса.

Поля события:

ПолеНазначение
methodHTTP-метод запроса, как его прислал клиент.
pathПуть запроса из строки запроса, вместе с query-строкой, если она была.
reasonПричина блокировки: path — путь не совпал ни с одним правилом, method — метод не разрешён для совпавшего пути.
status_codeКод ответа: 403 для reason=path, 405 для reason=method.

Заголовки и тело запроса в событие не попадают: аудит фиксирует факт и причину отказа, а не содержимое трафика. Для промышленной эксплуатации события удобно писать в отдельный файл в format: Json и/или отправлять в SIEM — настройка описана в статьях События и Аудит.

observability:
service_name: netgap-gateway
event_targets:
- level: info
target_id: Audit
target_destination: File
target_args: /var/log/netgap/audit.log
format: Json
siem:
endpoint: 192.0.2.10:514
log_types: [Audit]
level: info

Событие имеет уровень warn, поэтому оно проходит в цели с порогом info и warn, но отбрасывается целью с уровнем error. Если в SIEM нужны только блокировки и ошибки без штатных событий прохождения запросов, достаточно поднять порог до level: warn.

Метрики блокировок

Каждый компонент публикует собственный счётчик заблокированных запросов через функцию Метрики.

МетрикаТипЧто показывает
netgap_gateway_blocked_requestscounterЗапросы, заблокированные фильтром на стороне шлюза.
netgap_executor_blocked_requestscounterЗапросы, заблокированные фильтром на стороне исполнителя.

Метки серий:

МеткаЗначенияНазначение
methodHTTP-метод запросаПоказывает, какая операция запрашивалась.
pathПуть запросаПоказывает, какой ресурс запрашивался.
reasonpath, methodПричина блокировки: неизвестный путь или неразрешённый метод.

Важно: метка path содержит путь запроса так, как его прислал клиент, включая query-строку. На потоке произвольных или сканирующих запросов это даёт высокую кардинальность серий. Если Netgap открыт в недоверенную сеть, ограничьте кардинальность на стороне сбора метрик — например, metric_relabel_configs в Prometheus, который отбрасывает или обобщает метку path, оставляя разбивку по method и reason.

Примеры PromQL:

rate(netgap_gateway_blocked_requests[5m])

Блокировки по причинам за 5 минут:

sum by (reason) (rate(netgap_gateway_blocked_requests[5m]))

Топ-10 путей, которые чаще всего блокируются:

topk(10, sum by (path) (rate(netgap_gateway_blocked_requests[5m])))

Доля заблокированных запросов в общем входящем потоке шлюза:

sum(rate(netgap_gateway_blocked_requests[5m])) / sum(rate(netgap_gateway_requests[5m]))

Блокировки на исполнителе — признак расхождения политик компонентов (кандидат в правило алертинга):

sum(rate(netgap_executor_blocked_requests[5m])) > 0

Диагностика

СимптомВероятная причинаЧто сделать
Весь трафик получает 403, метрика блокировок растёт с reason=pathПолитика не покрывает фактические пути целевого сервиса (опечатка, лишний или недостающий префикс, регистр)Сверить пути в событиях аудита с правилами; см. Правила фильтра
Часть операций получает 405 после включения фильтраМетод не перечислен для совпавшего пути (частый случай — HEAD и OPTIONS)Добавить недостающие методы в правило
Растёт netgap_executor_blocked_requests, а netgap_gateway_blocked_requests — нетПолитики шлюза и исполнителя различаютсяПривести секции http_filter к одинаковому виду и перезапустить оба компонента
Блокировок нет вообще, хотя ожидалисьКомпонент запущен с mode: AllowAllПроверить фактическую конфигурацию запуска: режим задан в ней явно, а политика читается один раз при старте
Метрики блокировок отсутствуют в /metricsНи одной блокировки ещё не было либо не включена секция observability.metricsПроверить настройку метрик; серии появляются после первой блокировки
Резкий рост уникальных значений метки pathСканирование внешним источникомОграничить кардинальность на стороне Prometheus и разобрать источник по событиям аудита

Ссылки