Что происходит с письмом, когда сканер не ответил
При выборе почтового шлюза этот вопрос почти никто не задаёт. А атакующий проверяет именно этот путь.
При выборе почтового шлюза этот вопрос почти никто не задаёт. А атакующий проверяет именно этот путь.
Про шлюз обычно думают в двух исходах: письмо чистое или письмо вредоносное. На практике есть третий, и он самый интересный: сканер не ответил.
Вышел таймаут движка, файл зашифрован, архив повреждён, структура некорректна, внутри документа объект, который не открывается, формат контейнера не опознан — ничто из этого не означает «чисто». Но большинство шлюзов решают именно так.
Это решение нигде не записано. Его не видно и в настройках; это просто состояние логики по умолчанию. Кто работал с ClamAV, узнает картину: в ответе `clamd`, кроме `OK` и `FOUND`, есть ещё `ERROR`, и код интеграции нередко проверяет `FOUND`, а всё остальное читает как «не вредонос».
Поэтому узнать его можно только проверкой. В документации может быть написано «у нас многоуровневая защита», и это одновременно правда и не имеет значения.
Причина не техническая, а организационная. Заблокированное письмо видно сразу: пользователь звонит, руководитель спрашивает, виноват администратор. Пропущенное вредоносное письмо не видно — оно всплывает инцидентом через месяцы, и связать его с настройкой шлюза уже некому.
Поэтому настройки постепенно смягчаются. Каждое смягчение по отдельности выглядит разумным: этот отправитель надёжный, этот формат у нас используют часто, это правило слишком шумит, этот отдел пожаловался.
Через год результат один: шлюз пропускает всё, в чём не уверен. Никто не делал этого намеренно. Защита теперь срабатывает только при точной сигнатуре — то есть только против уже известного.
Сам этот процесс тоже измерим: сколько исключений добавлено за последние полгода и сколько снято? Если первое число в разы больше второго, направление вы уже знаете.
Если политика «в сомнении пропускать», задача атакующего не спрятать вредоносный код, а вывести сканер из строя. Это заметно проще, потому что не требует обхода антивирусных баз.
Список инструментов короткий и полностью публичный: архив больше лимита, зашифрованный документ Office, намеренно повреждённый центральный каталог ZIP, вложенные друг в друга контейнеры, нагрузка с медленным разбором. Кое-что вообще не файл — например, письмо с намеренно неверной границей MIME: разбор останавливается, а вложение у клиента видно.
Ничему из этого не нужна сигнатура антивируса, и ничто не несёт метку «атака». Им нужно одно: чтобы при ответе «не знаю» письмо прошло.
И на проверку этого условия у атакующего уходит несколько минут. Он отправляет вам один безобидный тест и смотрит на результат — доставлено или нет. Сам ответ и есть информация, и он бесплатный.
Fail-closed не означает «блокировать». Выполненный правильно, это временный отказ — SMTP 451. Сервер отправителя держит письмо в очереди и присылает его снова.
Это не добровольное поведение: RFC 5321 определяет ответы 4yz как временные и требует повтора. Postfix, Exim, Microsoft Exchange — все работают так. В Postfix первая повторная попытка обычно происходит после `minimal_backoff_time`, дальше интервал растёт и продолжается до `maximal_queue_lifetime`; в стандартной настройке это несколько суток.
Если к тому моменту сканер здоров, письмо проверяется обычным порядком и доставляется. Пользователь чаще всего не замечает и задержки, потому что повтор выполняется автоматически на стороне отправителя и ни от кого ничего не требует.
5xx — постоянный отказ — только для явной угрозы. Различие принципиально: 451 не теряет письмо, а откладывает; 5xx говорит отправителю «не присылай снова», и письмо теряется совсем. Страх «fail-closed сломает почту» вырастает именно из смешения этих двух ответов.
Граница здесь такая: fail-closed срабатывает, когда сканер не работает, а не когда есть подозрение. Это разные вещи, и их смешение делает политику неработоспособной.
Для подозрения нужен другой механизм — накопление нескольких слабых сигналов в одно решение. Этот подход десятилетиями работает в SpamAssassin и rspamd: каждый признак даёт свой вес, решение принимается по сумме.
Один слабый сигнал не должен приводить к блокировке. Незнакомый отправитель — сигнал. Провал SPF — сигнал. Свежезарегистрированный домен — сигнал. Вместе они дают надёжный вывод; по отдельности каждый заблокирует заметную часть обычной почты.
Если смешать эти два случая, fail-closed действительно сломает почту — но причина будет не в политике, а в том, что её поставили не туда.
Список нужно записать заранее, иначе каждый случай превращается в отдельный спор, а спор всегда решается в сторону пропуска.
В список входят: таймаут сканера, исчерпание памяти или диска, неоткрывшийся архив, документ с повреждённой структурой, нераспознанный формат контейнера, ошибка разбора и падение самого процесса сканера. В некоторых системах последнее вообще не фиксируется — процесс перезапускается, и следующее письмо проходит как ни в чём не бывало.
Архив под паролем — отдельный случай. Технически это не сбой, но результат тот же: внутрь не посмотрели. Поэтому он тоже попадает в список — после попыток найти пароль в тексте письма.
Нужен и обратный список: что сбоем не является. Незнакомый отправитель, странная тема, имя из смеси кириллицы и латиницы — это подозрение, а не сбой, и 451 к нему не применяется. Без этой границы через месяц 451 применяется ко всему, и политику выключают.
У политики 451 есть одна практическая цена: письмо задерживается. Поэтому бюджет задержки определяется заранее — сколько повторов и с каким интервалом вы готовы ждать и в какой момент это считается инцидентом.
С другой стороны, серверы отправителей тоже не пробуют бесконечно. Большинство повторяет несколько суток, но некоторые слабо настроенные системы — особенно скрипты, отправляющие письма из веб-приложений, — сдаются после одной-двух попыток. Поэтому долгий сбой сканера всё равно приводит к потерям.
Особенно опасный случай — транзакционные письма: восстановление пароля, код подтверждения, подтверждение заказа. У них короткий срок жизни, и десятиминутная задержка делает их бесполезными. Для таких потоков нужен отдельный маршрут и отдельное решение.
Вывод: 451 даёт время починить сканер, но не заменяет починку. Именно поэтому оповещение о неработающем шлюзе должно иметь высокий приоритет — и оно не должно уходить по почте, потому что почта в этот момент и не работает.
Достаточно двух тестов. Первый: отправьте архив под паролем, не указывая пароль в тексте письма. Второй: отправьте файл больше лимита сканера или такой, разбор которого заведомо медленный.
Если оба легли в ящик с пометкой «чисто» — у вас fail-open шлюз. Посмотрите и на заголовки: `X-Spam-Status`, `Authentication-Results` и собственный заголовок поставщика нередко прямо пишут решение, и там можно увидеть слова `error` или `skipped`.
Третий тест самый надёжный: намеренно остановите сканер и отправьте обычное письмо. Оно потеряется, доставится или получит 451? Одним действием вы узнаёте политику, и на тестовом стенде это несложно.
И последний вопрос поставщику: где настраивается поведение при сбое? Если такой настройки нет вовсе, политику выбрали не вы, а состояние программы по умолчанию — и оно почти всегда на стороне пропуска.
Покажите домен — дадим первичный анализ вашего текущего внешнего состояния. На этом этапе ничего не меняется.

