RabbitMQ: как сообщения могут утекать без остановки сервиса
Содержание
Посторонний получатель может прочитать сообщение и вернуть его в очередь через NACK. Почему работающий сервис не гарантирует конфиденциальность сообщений. Утечка данных из RabbitMQ не обязательно сопровождается сбоем. Приложение обрабатывает задачи, очередь разгружается, пользователи не замечают отказа. Но часть сообщений могла пройти через постороннего получателя до того, как попала в приложение. Получатель (consumer) — это клиент, который получает сообщения из очереди. Механизм прост: получить сообщение → прочитать содержимое → вернуть в очередь через В этом и состоит риск: доступность сервиса и конфиденциальность сообщений — разные свойства. Успешно обработанная задача не доказывает, что её содержимое видел только нужный сервис. Речь не об обходе аутентификации и не о сетевой атаке «человек посередине» (MITM). Сценарий предполагает, что злоумышленник уже может подключиться к брокеру и имеет разрешение читать целевую очередь — например, из-за компрометации сервисной учётной записи или слишком широких прав в списках контроля доступа (ACL). Конфигурация также должна допускать ещё одного активного получателя. [1][3] Право В обычной очереди сообщения распределяются между активными получателями, а не рассылаются каждому в виде копий. Часть сообщений достаётся приложению, часть может достаться постороннему получателю. Распределение зависит от лимита prefetch (числа допустимых неподтверждённых доставок), доступности получателей и настроек очереди. Эксклюзивный получатель (exclusive consumer) или режим Single Active Consumer могут не позволить другому получателю принимать сообщения одновременно с приложением. [1] В режиме ручных подтверждений доставленное сообщение остаётся неподтверждённым, пока получатель не ответит. Если сообщение затем получает и успешно обрабатывает приложение, бизнес-операция может завершиться без видимого отказа. При этом конфиденциальность уже нарушена. Если мониторинг проверяет только доступность приложения и завершение задач, постороннее чтение может не вызвать явного сигнала тревоги. Механизм не требует менять код приложения или намеренно останавливать сервис. Но отсутствие тревоги не означает отсутствия следов. В брокере появляются дополнительные получатели и подключения, происходят повторные доставки. Эти изменения можно обнаружить. Отсутствие жалоб пользователей не заменяет их мониторинг. Нет гарантии, что сервис продолжит работать без изменений: возможны задержки, изменение порядка доставки, дополнительная нагрузка и циклы повторной доставки. Политики очереди, её тип и версия RabbitMQ также влияют на результат. [2] Ниже — локальная модель одного возможного сценария, а не клиент RabbitMQ. Она работает с синтетическим сообщением в памяти, никуда не подключается и показывает главное: сообщение можно обработать успешно, хотя его содержимое уже прочитал другой участник. Сохраните пример в Пример намеренно выбирает приложение следующим получателем. В реальном RabbitMQ Число получателей может влиять на распределение доставок, но универсальной формулы для доли сообщений, которую удастся прочитать постороннему клиенту, нет. Доля посторонних получателей не равна доле уникальных прочитанных ими сообщений: повторное получение того же сообщения не увеличивает эту долю, а уже подтверждённое приложением сообщение больше недоступно из очереди. Больше подключений означает больше участников, которых можно обнаружить, и потенциально большую нагрузку. Это не гарантирует полного перехвата и не делает вмешательство невидимым. Опасность схемы «прочитать и вернуть» не в гарантированной невидимости, а в том, что утечка может не сопровождаться явным отказом сервиса. Сообщение может вернуться в очередь и быть обработано, но отменить уже состоявшееся раскрытие данных нельзя.Сервис работает. А данные уже прочитали
NACK(requeue=true). Возврат сохраняет возможность дальнейшей обработки сообщения, но не отменяет уже состоявшееся чтение.Какие права для этого нужны
read не означает пассивный просмотр. Получатель участвует в доставке сообщений. TLS защищает соединение, но не скрывает сообщения от клиента, которому брокер разрешил их получить.Получить, прочитать, вернуть
publisher → queue → дополнительный получатель
│
├─ читает содержимое
└─ NACK(requeue=true) → queue → следующая доставкаACK подтверждает получение и позволяет брокеру удалить сообщение из очереди. NACK отклоняет доставку; с параметром requeue=true сообщение снова становится доступным для доставки. Это не создание копии и не указание брокеру обязательно передать сообщение приложению. Следующим получателем может быть приложение — или тот же посторонний клиент. [2]Почему это может остаться незамеченным
Пример кода: возврат не отменяет чтение
delivery_model.py и запустите python delivery_model.py. Внешние библиотеки не нужны.from collections import deque
# Synthetic data only: no network connection or external credentials.
queue = deque([{"id": "demo-1", "body": "synthetic payload"}])
observed = []
processed = []
# Model one possible delivery to an additional consumer.
message = queue.popleft()
observed.append(message.copy())
queue.appendleft(message) # Model NACK(requeue=True), not a broker call.
# For this trace, explicitly choose the application as the next recipient.
# A real broker does not guarantee this recipient after requeue.
message = queue.popleft()
processed.append(message["id"]) # Model successful processing and ACK.
assert observed[0]["id"] == processed[0]
assert not queue
print("Observed:", observed[0]["id"])
print("Processed:", processed[0])
print("Queue empty:", not queue)requeue этого не гарантирует. Эта модель не измеряет распределение доставок, скорость обработки или заметность подключения.А если получателей больше?
Что проверять владельцу брокера
Вывод
Источники