Выравнивание в DMARC: relaxed против strict, и почему письмо проходит SPF и DKIM, но валит DMARC
Валидная подпись DKIM и spf=pass не гарантируют dmarc=pass. В большинстве случаев виноват не крипто и не PTR, а alignment — совпадение доменов. Разбираем, чем relaxed отличается от strict для adkim и aspf, почему relaxed сверяет organizational domain через Public Suffix List, и как за две минуты по одному заголовку Authentication-Results понять, какая из двух проверок упала.
EvilMail Team18 июля 2026 г.11 мин чтения
Почему письмо проходит SPF и DKIM, но валит DMARC
Типичный тикет: «У нас всё настроено, SPF зелёный, DKIM подписан и валиден, но Gmail пишет dmarc=fail и роняет письма в спам». Открываем заголовок и видим ровно это:
Обе криптопроверки прошли. И тем не менее DMARC — fail. Здесь ломается интуиция большинства админов: они считают, что DMARC — это «SPF плюс DKIM, и если хоть что-то pass, то всё хорошо». Это не так.
DMARC не переиспользует результат SPF или DKIM напрямую. Он добавляет второй, независимый тест — alignment (выравнивание). Проверка может быть криптографически безупречной и всё равно не пройти DMARC, потому что домен, который аутентифицировал SPF или DKIM, — не тот домен, который человек видит в поле From:. pass
DMARC alignment: relaxed vs strict для DKIM и SPF — почему dmarc=fail при pass — EvilMail Blog
и
aligned
— два разных состояния, и DMARC требует оба сразу.
В примере выше SPF аутентифицировал bounces.sendgrid.net, DKIM подписал от имени sendgrid.net, а в From: стоит example.com. Три разных домена. DMARC смотрит на From: и спрашивает: есть ли хоть один проверенный идентификатор, чей домен совпадает с этим? Нет. Значит fail — даже при двух pass.
Что именно сверяет DMARC: три разных домена
В одном письме живут три доменных идентификатора, и путаница между ними — корень почти всех alignment-инцидентов.
RFC5321.MailFrom — envelope-адрес, он же Return-Path, он же MAIL FROM в SMTP-диалоге. Это база для SPF: получатель проверяет, разрешён ли IP отправлять почту от имени этого домена.
DKIM d= tag — домен в заголовке DKIM-Signature. Это база для DKIM: подпись проверяется публичным ключом из selector._domainkey.<d>.
RFC5322.From — видимый заголовок From:, тот самый, что рисуется в почтовом клиенте. Это якорь DMARC.
DMARC берёт домен из From: и сравнивает его с доменом аутентифицированного идентификатора. Формулу прохождения стоит запомнить дословно: DMARC pass = хотя бы один из {SPF, DKIM} дал authenticated identifier, выровненный с From:. Достаточно одного. Если DKIM выровнен — SPF может быть невыровненным или вообще fail, DMARC всё равно pass.
Отсюда практический вывод, который многие упускают: DKIM alignment ценнее SPF alignment. При пересылке — forwarding, списки рассылки — Return-Path переписывается на домен пересылающего сервера, и SPF alignment гарантированно ломается. DKIM-подпись переживает пересылку, пока тело и подписанные заголовки не изменены. Поэтому если строить DMARC на одной опоре — стройте на DKIM.
Relaxed vs strict: где проходит граница
У alignment два режима, и задаются они двумя независимыми тегами DMARC-записи: adkim (для DKIM) и aspf (для SPF). Значения — r (relaxed, по умолчанию) и s (strict).
relaxed сравнивает organizational domain двух доменов. mail.example.com и example.com сводятся к одному org-домену example.com, значит выровнены. Поддомены проходят автоматически.
strict требует точного совпадения FQDN, символ в символ. mail.example.com ≠ example.com. Не выровнены.
Весь вопрос упирается в то, как считается organizational domain. И здесь новички делают роковую ошибку — «отрезать до второго уровня». Для mail.example.com это работает, но разваливается на example.co.uk. Правильный ответ: org-домен вычисляется через Public Suffix List (publicsuffix.org) — публично поддерживаемый список суффиксов, под которыми любой может зарегистрировать домен.
com, co.uk, com.tr, github.io — это публичные суффиксы.
Org-домен = публичный суффикс плюс один лейбл слева от него.
Отсюда неочевидные следствия. example.co.uk и other.co.uk — разные org-домены, потому что co.uk целиком в PSL, и различающий лейбл — это example против other. А a.github.io и b.github.io — тоже разные org-домены (github.io внесён в PSL как раз чтобы юзерские страницы не выдавали себя друг за друга). Наивное «срезать до второго уровня» дало бы github.io в обоих случаях и ошибочно посчитало бы их выровненными. Реализации DMARC сверяются с актуальным PSL — сверяйтесь и вы, а не считайте точки.
Сводная таблица, чтобы держать в голове:
text
Тег Сверяет relaxed (r, default) strict (s)
------ ---------- -------------------------- ----------------------
adkim DKIM d= org-домен(d) == org(From) d == From (точный FQDN)
aspf MailFrom org-домен(MF) == org(From) MailFrom == From (FQDN)
Три сценария, где relaxed спасает, а strict валит
1. ESP с собственным bounce-доменом. Тот самый инцидент из начала статьи. From: [email protected], но провайдер ставит свой Return-Path [email protected] ради обработки отскоков. SPF проверяется на sendgrid.net и даёт pass — но домен не ваш, поэтому SPF не выровнен ни в relaxed, ни в strict: sendgrid.net не сводится к example.com никак. Единственное спасение — DKIM alignment: провайдер должен подписывать письмо вашим доменом. Пока d=sendgrid.net, DMARC будет падать. Это самый частый прод-инцидент в почте, и лечится он не тегами DMARC, а настройкой на стороне провайдера.
2. Отправка с поддомена.From: [email protected], а DKIM подписан d=example.com (общая инфраструктура на корневом домене). При adkim=r org-домены совпадают → aligned, DMARC pass. Поставьте adkim=s — и mail.example.com ≠ example.com, fail. Ровно та ситуация, где strict ломает рабочий поток на пустом месте.
3. Сторонний d= у маркетинговой платформы. Вендор подписывает своим доменом d=mailer.vendor.com, From: ваш. Ни relaxed, ни strict не выровняют — org-домены принципиально разные. Чинится только делегированным DKIM (CNAME-селектор указывает на инфраструктуру вендора, но d= остаётся вашим доменом) либо выравниванием через SPF, если Return-Path тоже на вашем домене.
Во всех трёх случаях strict либо не помогает вообще, либо только вредит. Там, где relaxed уже прошёл, он не добавляет безопасности — он лишь отбраковывает легитимные поддомены и общую инфраструктуру.
Диагностика за две минуты по Authentication-Results
Гадать не нужно. Ответ всегда в заголовке Authentication-Results. Ищите три вещи:
header.d= — домен, которым подписан DKIM.
smtp.mailfrom= — домен для SPF (envelope).
header.from= — якорь DMARC.
Алгоритм на три шага:
1.dmarc=fail? Если да — идём дальше; если нет — вы не по адресу.
2.Есть ли dkim=pass, у которого org-домен header.d равен org-домену header.from? Если да — DMARC обязан быть pass; если нет — DKIM не спасает.
3.Есть ли spf=pass, у которого org-домен smtp.mailfrom равен org-домену header.from? Если и тут нет — fail абсолютно закономерен.
Тестовая отправка через свою инфраструктуру и разбор результата на принимающей стороне:
bash
swaks --to [email protected] --from [email protected] \
--server smtp.example.com --auth
# затем в Gmail: письмо → «Показать оригинал» → читать Authentication-Results
Если включён rua=, самый точный источник — агрегированные XML-отчёты. Внутри <record> сравните два блока: <auth_results> показывает сырые результаты SPF/DKIM (валидность подписи), а <policy_evaluated> — результат после alignment. Когда в <auth_results> стоит pass, а соответствующий <dkim>/<spf> в <policy_evaluated> — fail, это и есть чистый alignment-фейл: криптография в порядке, домены не сошлись.
Как чинить: DNS и делегирование, а не хаки
Bounce-домен ESP. В панели провайдера настройте verified / authenticated sending domain. Провайдер выдаст CNAME для custom return-path (em.example.com → ...sendgrid.net) — это выравнивает SPF, и CNAME-селекторы для DKIM (s1._domainkey.example.com → s1.domainkey.uXXXX.wlYYY.sendgrid.net) — это выравнивает DKIM. После этого и smtp.mailfrom, и header.d попадают в ваш org-домен, и DMARC проходит по обеим опорам.
Сторонний d=. Делегированный DKIM: CNAME селектора смотрит на инфраструктуру вендора, но d= остаётся example.com.
Поддомены. Либо оставьте adkim=r/aspf=r, либо опубликуйте отдельную запись _dmarc.mail.example.com с собственной политикой. Помните про sp=: политика поддоменов наследует `p=`, если sp= не задан явно. То есть p=reject без sp= означает reject и для всех поддоменов.
Когда strict реально оправдан? Только под конкретную threat-модель: защита точного бренд-FQDN (например транзакционного mail.bank.example) от спуфинга на этот самый FQDN, когда вы контролируете весь поток и уверены, что d= и From: совпадают символ в символ. Во всех прочих случаях adkim=s/aspf=s — это self-inflicted breakage: хрупкость без выигрыша в безопасности.
Чеклист перед выкаткой p=reject
Начните с p=none; rua=mailto:... и собирайте агрегаты, ничего не блокируя.
Убедитесь, что каждый легитимный поток (транзакционка, маркетинг, CRM, счета, саппорт) даёт хотя бы один aligned pass.
Соберите инвентарь всех отправителей от вашего домена — забытый сервис на поддомене всплывёт в RUA.
Задайте sp= явно — не полагайтесь на молчаливое наследование p=.
Не ставьте aspf=s, если используете внешний Return-Path (а вы почти наверняка используете).
Не ставьте adkim=s без делегированного DKIM с вашим d=.
Выдержите 2–4 недели на агрегатах, пока картина не станет стабильной и чистой.
Поднимайте pct постепенно: 25 → 50 → 100 (он применяется только к quarantine/reject).
Двигайтесь по политике none → quarantine → reject, не перепрыгивая.
Держите в уме порог Gmail/Yahoo: для bulk-отправителей (свыше 5000 писем в день) DMARC с рабочим alignment с 2024 года — не опция, а требование на входе.