MAATRIX / Блог / Поставили DMARC на reject и отрезали письма от собственной CRM

Поставили DMARC на reject и отрезали письма от собственной CRM

MAATRIX

В конце августа 2026 года домен компании несколько месяцев подряд получал фишинговые письма, отправленные якобы от её же имени - клиенты жаловались на поддельные счета. Решение выглядело логично: ужесточить DMARC-политику с quarantine до reject, чтобы провайдеры отбрасывали любое письмо, не прошедшее проверку подлинности. Политику поменяли вечером в четверг, а в пятницу утром отдел продаж обнаружил, что письма из CRM - те самые, которые менеджеры шлют клиентам через встроенную рассылку - вообще не доходят. Не в спам, а именно не доходят: получатели ничего не видят, отправитель в CRM видит "отправлено", а на другом конце - тишина. Дальше был день разбирательства, две неверные гипотезы и одна деталь в SPF-записи, о которой все забыли ещё год назад.

Что сломалось: рассылка из CRM встала после перехода на reject

Компания использует один корпоративный домен для трёх разных каналов почты: обычная переписка сотрудников через корпоративный почтовый сервер, транзакционные письма (подтверждения, чеки) через собственный SMTP-релей на VPS, и коммерческая рассылка от менеджеров - через стороннюю CRM с email-модулем, которая отправляет письма от имени @company-domain.example, но физически - со своих серверов, никак не связанных с инфраструктурой компании.

До инцидента DMARC-запись домена выглядела так:

v=DMARC1; p=quarantine; pct=100; rua=mailto:dmarc-reports@company-domain.example; adkim=r; aspf=r

Через DNS-панель политику поменяли на:

v=DMARC1; p=reject; pct=100; rua=mailto:dmarc-reports@company-domain.example; adkim=r; aspf=r

Изменение казалось безопасным: quarantine уже несколько месяцев отправлял часть неавторизованных писем в спам без единой жалобы от легитимных отправителей. Логика была простая - раз при quarantine всё работает штатно, reject просто ужесточит то же самое поведение. Это оказалось неверным допущением, и именно оно стоило дня расследования: quarantine и reject реагируют на непрошедшие DMARC письма принципиально по-разному, а разница проявляется только на реальном трафике получателей.

Через двенадцать часов после смены политики в CRM начали копиться письма со статусом "не доставлено" у получателей на Gmail и Microsoft 365. У части получателей на Mail.ru и Yandex письма продолжали доходить - но с пометкой о непройденной проверке отправителя. Собственная переписка сотрудников и транзакционные письма с VPS проблем не показывали вообще.

Как устроен DMARC: alignment, quarantine и reject простыми словами

Прежде чем идти в логи, стоит закрепить механику, потому что без неё гипотезы расследования не имеют смысла. DMARC не проверяет письмо сам - он говорит принимающему серверу, что делать с результатами двух других проверок, SPF и DKIM, и добавляет к ним третье условие - alignment (выравнивание).

  • SPF проверяет, что IP-адрес сервера, который физически отправил письмо, входит в список, разрешённый TXT-записью домена в поле MAIL FROM (envelope from).
  • DKIM проверяет криптографическую подпись письма и то, что домен в подписи (d= в заголовке DKIM-Signature) соответствует ожиданиям.
  • Alignment - это отдельная, третья проверка: домен, который прошёл SPF или DKIM, должен совпадать (строго или "гибко" - в зависимости от aspf/adkim) с доменом в заголовке From:, который видит получатель. Про сами механизмы SPF, DKIM и DMARC по отдельности у нас есть базовый разбор - SPF, DKIM и DMARC простыми словами.

Ключевой момент: письмо может пройти SPF (IP отправителя разрешён) или DKIM (подпись валидна), но провалить DMARC - потому что домен в SPF/DKIM не совпал с доменом в From:. Именно так ведут себя многие сторонние ESP и CRM: они отправляют письма со своих IP, подписывают DKIM своим доменом (например, d=mail.crm-vendor.example), а в From: подставляют домен клиента, чтобы получатель видел привычный адрес компании. Без выравнивания DMARC не проходит - независимо от того, как давно работает такая связка.

Разница между quarantine и reject - в том, что происходит с письмом, которое не прошло DMARC:

ПолитикаЧто делает принимающий серверВидимость проблемы
p=noneНичего, письмо доставляется как обычноПроблема видна только в отчётах rua, получатель ничего не замечает
p=quarantineПомечает письмо как подозрительное - чаще всего папка "Спам"Получатель может найти письмо сам, часть провайдеров игнорирует рекомендацию
p=rejectОтклоняет письмо на этапе SMTP-диалога, до вручения получателюПисьмо не существует для получателя вообще, без возможности его найти

Здесь и была ловушка: провайдеры не обязаны исполнять quarantine буквально - многие крупные почтовые системы довольно мягко относятся к письмам без выравнивания при хорошей репутации IP и просто теряют приоритет, а не гарантированно уходят в спам. reject же - жёсткая директива, которую соблюдают почти все: это явное указание владельца домена "не доставляйте, если не прошло проверку". Поэтому при quarantine письма от CRM без выравнивания долетали без жалоб, а при reject те же письма стали отклоняться систематически.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Хронология расследования: сначала грешили на сам почтовый сервер

Первая мысль дежурного инженера была вполне логичной для пятничного утра: раз что-то не отправляется, значит сломался сервер, который отправляет почту. Смотрели именно на транзакционный VPS-релей и корпоративный почтовый сервер:

sudo journalctl -u postfix --since "-12 hours" | grep -iE "reject|bounce|error"
sudo tail -n 200 /var/log/mail.log | grep -i "status=bounced"

Оба лога были чистыми - никаких отказов, потому что оба этих канала вообще не были причиной. Через полчаса кто-то из отдела продаж прислал скриншот из CRM: там был отдельный внутренний лог доставки с полным SMTP-ответом принимающего сервера, и в нём фигурировал явный DMARC-отказ:

550 5.7.1 Unauthenticated email from company-domain.example is not accepted due to domain's DMARC policy

Это сразу сузило круг: проблема не в собственной инфраструктуре, а в письмах именно от CRM. Транзакционные письма с VPS и переписка сотрудников проходили DMARC нормально - для них SPF и DKIM настроены под этот домен корректно, об этом ниже. Ошибка 550 5.7.1 с прямой ссылкой на DMARC-политику - самая полезная информация из возможных: сервер прямым текстом называет причину отказа, реконструировать её по косвенным признакам не пришлось.

Что показали логи и DMARC-отчёты

Параллельно с текстом ошибки от CRM подняли агрегированные DMARC-отчёты (rua), которые собирались уже больше года. За сутки после смены политики в отчётах резко выросла доля записей с disposition: reject - и почти все они группировались вокруг диапазона IP, который не принадлежал ни VPS-релею компании, ни почтовому серверу. Разобрать XML вручную неудобно - у нас есть отдельный материал про то, что делать с XML из DMARC-отчётов.

Ключевой фрагмент одной записи выглядел так (упрощённо):

<record>
  <row>
    <source_ip>203.0.113.44</source_ip>
    <count>187</count>
    <policy_evaluated>
      <disposition>reject</disposition>
      <dkim>fail</dkim>
      <spf>fail</spf>
    </policy_evaluated>
  </row>
  <identifiers>
    <header_from>company-domain.example</header_from>
  </identifiers>
  <auth_results>
    <dkim>
      <domain>mail.crm-vendor.example</domain>
      <result>pass</result>
    </dkim>
    <spf>
      <domain>company-domain.example</domain>
      <result>fail</result>
    </spf>
  </auth_results>
</record>

Здесь видно всё, если знать, куда смотреть. DKIM реально прошёл (result: pass) - но для домена mail.crm-vendor.example, а не company-domain.example. В блоке policy_evaluated, где DMARC уже учёл alignment, DKIM показан как fail - домен подписи не совпал с доменом в From:. SPF провалился и в исходном виде: IP 203.0.113.44 (адрес CRM) вообще не входил в SPF-запись домена.

Гипотезы, которые отбросили

Прежде чем дойти до реальной причины, проверили и отбросили две версии, каждая из которых казалась правдоподобной в моменте.

Гипотеза 1: DNS ещё не обновился после смены записи. Первая мысль - изменение DMARC-записи ещё не разошлось по резолверам, и часть серверов видит старую политику. Проверили TTL и актуальное состояние напрямую:

dig +short TXT _dmarc.company-domain.example @8.8.8.8
dig +short TXT _dmarc.company-domain.example @1.1.1.1

Оба резолвера уже больше суток отдавали новую запись с p=reject, TTL 3600 секунд давно истёк. Гипотезу закрыли за пятнадцать минут - расхождение DNS не объясняло, почему отказы шли систематически, а не хаотично у случайных получателей.

Гипотеза 2: у CRM закончился лимит отправки или её IP попал в блок-лист. Вторая версия - проблема на стороне провайдера, репутационная блокировка IP или исчерпанный лимит тарифа. Проверили через панель CRM и публичные blacklist-чекеры её исходящих IP - ни блокировок, ни превышения лимитов не нашли. К тому же формулировка 550 5.7.1 ... due to domain's DMARC policy прямым текстом указывала не на репутацию, а на политику DMARC - этот текст стоило прочитать внимательнее с самого начала.

После этих двух версий стало ясно, что искать нужно не снаружи, а в собственной настройке домена - в том, что именно разрешено отправлять от его имени.

Настоящая причина: CRM не входила ни в SPF, ни в DKIM домена

SPF-запись домена на момент инцидента:

v=spf1 mx include:_spf.google.com include:mailrelay-vps.example -all

IP-адреса CRM в этой записи не было ни напрямую, ни через include. DKIM для CRM тоже не был настроен: чтобы её письма подписывались от имени домена компании, нужно было сгенерировать пару ключей, добавить публичный ключ CRM отдельной TXT-записью с уникальным селектором (например, crm._domainkey.company-domain.example) и включить подпись в настройках самой CRM. Ничего из этого не сделали - CRM подключили полтора года назад, письма "просто заработали", потому что при p=none, а затем quarantine непройденный DMARC не приводил к видимым последствиям, и на шаг "настроить SPF/DKIM для нового отправителя" никто не вернулся.

Формально письма от CRM никогда не проходили DMARC-выравнивание - ни в момент подключения, ни всё последующее время. Их доставляемость держалась не на корректной аутентификации, а на терпимости провайдеров к письмам без выравнивания при мягких политиках. p=reject эту терпимость отключил полностью - именно для этого он и существует: остановить любые письма, которые технически не могут доказать, что отправлены от имени домена легитимно. С точки зрения DMARC разницы между фишингом и незарегистрированной в SPF корпоративной CRM нет: и то, и другое - "письмо от домена, не прошедшее проверку".

Что изменили: инвентаризация отправителей и поэтапный переход

Откатывать p=reject обратно на quarantine не стали - это устраняло симптом, но возвращало исходную уязвимость к спуфингу, ради закрытия которой всё и затевалось. Вместо этого сделали три вещи.

Первое - полная инвентаризация легитимных отправителей. Составили список всех сервисов, которые отправляют почту от имени домена: VPS-релей, корпоративный почтовый сервер, CRM, платёжный шлюз (чеки), система мониторинга (алерты) и HR-платформа для офферов кандидатам. До инцидента список нигде не был зафиксирован централизованно - каждый сервис подключали отдельно, без единого реестра.

Второе - для каждого отправителя настроили выравнивание. Для CRM это означало два шага: добавить её диапазон IP в SPF через include её собственного SPF-домена (большинство CRM и ESP публикуют такой домен в документации, чтобы не терять актуальность при смене IP на стороне провайдера) и включить в настройках CRM DKIM-подпись от имени company-domain.example с отдельным селектором - сама CRM в админке выдаёт нужную DNS-запись. Результат проверили до возврата в продакшн:

dig +short TXT crm-vendor._domainkey.company-domain.example

и отправили тестовое письмо, посмотрев заголовки Authentication-Results на принимающей стороне - там должно быть dmarc=pass для домена company-domain.example, а не для домена CRM-провайдера.

Третье - процесс перехода политик закрепили формально. Договорились, что любое ужесточение DMARC в будущем идёт только по схеме none → quarantine → reject, с периодом наблюдения не короче двух-трёх недель на каждом шаге и постоянным мониторингом rua-отчётов на предмет fail от известных отправителей. Добавили параметр pct, который применяет политику не ко всем письмам сразу, а к указанному проценту:

v=DMARC1; p=reject; pct=25; rua=mailto:dmarc-reports@company-domain.example; ruf=mailto:dmarc-forensic@company-domain.example; adkim=r; aspf=r

Такая постепенность даёт заметить незамеченного отправителя на 25% трафика, а не на всём объёме, и включить ruf (forensic-отчёты по отдельным письмам) для детальной диагностики. Порядок действий при настройке DMARC с нуля - SPF и DKIM для всех известных отправителей, затем p=none с мониторингом отчётов и только потом поэтапное ужесточение - подробно расписан в материале как установить и настроить SPF, DKIM и DMARC на VPS. Для похожего по формату инцидента, но с виновником в виде опечатки в записи, а не в структуре политики, см. одна опечатка в SPF положила рассылку на неделю.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.

Частые вопросы

Почему quarantine не показал проблему, а reject показал сразу?

quarantine - рекомендация принимающему серверу, а не жёсткое требование: часть провайдеров всё равно доставляет такие письма, просто с меньшим приоритетом или в спам. reject - явная директива "не доставлять", и её исполняют почти все крупные почтовые системы без исключений.

Можно ли было заранее узнать, что CRM не проходит DMARC, не дожидаясь p=reject?

Да - для этого и существуют rua-отчёты: даже при p=none или p=quarantine в них видно dkim: fail и spf: fail для реальных отправителей домена. Регулярный просмотр отчётов до перехода на reject вскрыл бы несоответствие CRM заранее, без простоя в пятницу.

Достаточно ли добавить IP CRM в SPF, не настраивая DKIM отдельно?

Для DMARC достаточно совпадения (alignment) хотя бы по одному механизму - SPF или DKIM. Но полагаться только на SPF рискованно: он завязан на IP, а у облачных CRM и ESP исходящие адреса периодически меняются без предупреждения. DKIM привязан к ключу, а не к IP, и не ломается при смене инфраструктуры провайдера.

Что делать, если у сервиса вообще нет опции подписывать DKIM от чужого домена?

Такое встречается у простых email-модулей в CRM. Остаётся только SPF-выравнивание - добавить IP-диапазон сервиса в запись. Если и такой возможности нет, стоит поставить вопрос о смене отправителя: устойчиво пройти p=reject без хотя бы одного выровненного механизма невозможно.

Сколько держать p=quarantine перед переходом на p=reject?

Жёсткого правила нет, но ориентир - не переходить, пока в rua-отчётах минимум две-три недели подряд не останется ни одного fail от отправителей, которых вы считаете легитимными. Без регулярного чтения отчётов сам факт "прошло время" ни на что не влияет.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →