Почта и доставляемость

SPF и DMARC для домена только на приём: против подделки

Домен, направленный сюда, принимает почту, но ничего не отправляет — а значит, это самый простой в мире домен для защиты, и самый простой, чтобы про него забыть. Три записи, самые строгие из существующих настроек — и никакого полугодового поэтапного внедрения, которое нужно всем остальным.

  • Средний
  • 19 мин на чтение
Синий конверт скользит в серый почтовый ящик, а синий щит отражает второй конверт.

Два направления, а настроено — одно

Чтобы направить домен сюда, нужна одна DNS-запись. Эта запись — MX — отвечает ровно на один вопрос: куда идёт почта, адресованная этому домену? Это всё, что нужно catch-all-домену, и как только запись резолвится, домен уже работает. Но в этот момент он настроен лишь наполовину: имя домена используется в двух направлениях, а MX-запись ничего не говорит о втором из них.

Почта, адресованная вамчто-угодно@ваш-доменВаш ящик здесьдоставлено, хранитсяэто решает ваша MX-записьПодделка от вашего имениваш домен в поле FromЧужой почтовый ящикникогда не дошлоэто решают ваши SPF и DMARCДва направления, два набора записей. Публикация одного не влияет на другое.
Обе полосы — это одно и то же имя домена. Опубликованная вами запись управляет верхней; на нижнюю отвечают записи, которые вы ещё не написали, а на неотвеченный вопрос каждый принимающий сервер отвечает по-своему, на глазок.

Интересно как раз второе направление. Ничто в почтовом протоколе не мешает постороннему вписать ваш домен в строку From: письма, отправленного с его собственной машины. Ему не нужен доступ ни к вашему DNS, ни к регистратору, ни к вашему ящику: адрес в письме — утверждение, а не удостоверение, и так было всегда. Поверят ли этому утверждению, решает то, что ваш домен говорит о том, кому позволено его делать:

Домен, который молчит
Принимающий сервер не находит ни SPF, ни политики DMARC и вынужден полагаться на собственную эвристику: репутацию, содержимое, то, как домен вёл себя раньше. Совершенно новый домен без истории и без политики — это едва ли не идеальная мишень для подделки: опровергнуть подделку нечем, и спросить потом не с кого.
Домен, который говорит нет
Тот же сервер находит опубликованную политику: ни одной машине нигде не разрешено отправлять почту от имени этого домена, а всё, что не прошло проверку, нужно отклонять. Решение перестаёт быть вопросом усмотрения. Письмо отклоняют прямо на пороге — обычно оно даже не долетает до папки со спамом.

Это не гипотетический сценарий про крупные бренды. Домены без исходящей почты выбирают в качестве мишени именно потому, что у них нет политики, — имя, которое никто не защищает, используют пару недель и бросают: такое имя ценнее для отправителя нежелательной почты, чем имя, которое сопротивляется.

Почему вам можно пропустить то, на что у всех остальных уходит полгода

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

  1. Опубликовать политику, которая ничего не делает. p=none просит принимающие серверы присылать отчёты, но ничего не менять, — чтобы забытый отправитель не оказался отрезан самой политикой.
  2. Неделями читать отчёты. Система выставления счетов, служба поддержки, инструмент рассылок, платформа для найма, на которую кто-то зарегистрировался ещё в 2019 году, — каждая всплывает как источник, не проходящий проверку, и каждую нужно либо авторизовать, либо вывести из строя.
  3. Ужесточать поэтапно. Перейти на quarantine, подождать, понаблюдать и только потом — на reject, потому что каждый шаг ужесточения может тихо остановить почту, от которой кто-то зависит.

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

Есть и аргумент второго порядка в пользу того, чтобы сразу перейти к конечному состоянию. Домен, застрявший на p=none, публикует политику, которая ни о чём не просит, и принимающий сервер обращается с ним почти так же, как с доменом вообще без политики. Запись существует, поэтому выглядит, будто всё сделано, — а это хуже, чем очевидно незавершённое, потому что никто не возвращается, чтобы это доделать.

Три записи

Все три — TXT-записи, и все три добавляются рядом с уже существующей у вас MX-записью. Имена записаны так, как их обычно хотят видеть панели DNS, — относительно зоны, где @ означает сам домен. Если ваша панель требует полное имя, пишите вместо этого yourdomain.com, _dmarc.yourdomain.com и *._domainkey.yourdomain.com.

ИмяТипЗначениеЧто она решает
@TXTv=spf1 -allНи одной машине не разрешено отправлять почту с этим доменом в конверте. Не некоторым машинам — вообще ни одной.
_dmarcTXTv=DMARC1; p=reject; sp=reject; adkim=s; aspf=sВсё, что приходит с заявкой на этот домен и не может её подтвердить, должно быть отклонено, и то же самое касается каждого субдомена.
*._domainkeyTXTv=DKIM1; p=Каждый DKIM-ключ, о котором могут спросить применительно к этому домену, отозван, поэтому поддельную подпись невозможно заставить пройти проверку.

Если ваш провайдер требует заключать значение в кавычки, заключайте. Некоторые панели добавляют кавычки сами и в итоге сохраняют их дважды — получается запись, которую не может прочитать ни одна проверка: если значение возвращается из dig в двойных кавычках с обеих сторон, значит, произошло именно это.

Три значения, готовые к вставке. Копируйте их, а не перепечатывайте: пропущенная точка с запятой в записи DMARC делает весь список тегов нечитаемым, а нечитаемая политика считается полным отсутствием политики.

SPF — на самом доменеv=spf1 -all

DMARC — на имени _dmarcv=DMARC1; p=reject; sp=reject; adkim=s; aspf=s

DKIM — на имени *._domainkeyv=DKIM1; p=

Что на самом деле делает каждое слово в этих записях

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

-all
Конец записи SPF, и единственная её часть, которая здесь важна. Она означает: всё, что не перечислено выше, — подделка, а выше не перечислено ничего. Распространённая альтернатива, ~all, означает вероятно подделка, но всё равно доставить и пометить, — это правильный ответ, пока вы ещё ищете своих отправителей, и неправильный, когда вы уверены, что их нет.
p=reject
Что должен делать принимающий сервер с почтой, которая заявляет права на этот домен и не проходит проверку. none означает только отчёт, quarantine — обращаться как с подозрительным, reject — отказать прямо в ходе SMTP-сессии. Именно reject не даёт письму вообще попасться на глаза человеку.
sp=reject
То же самое, но для каждого субдомена — включая те, что вообще не существуют. Без этого тега мошенник использует billing.yourdomain.com, у которого нет собственных записей и который ничего не наследует, что могло бы его остановить. По умолчанию этот тег принимает значение p, так что без него запись ведёт себя точно так же; он указан явно, потому что политику, которую не видно при чтении записи, вы будете считать отсутствующей.
adkim=s, aspf=s
Строгое выравнивание. Оно требует, чтобы аутентифицированный домен совпадал с доменом в строке From: в точности, а не просто был с ним в родстве, — так что письмо от anything.yourdomain.com не может одолжить пропуск, принадлежавший родительскому домену. По умолчанию используется мягкое выравнивание, а строгое — это то, что должен заявлять домен, которому нечего авторизовывать.
v=DKIM1; p=
Публичный ключ DKIM, в котором нет самого ключа. Спецификация прямо говорит, что пустой ключ означает отозван, поэтому любая подпись, называющая любой селектор в этом домене, не проходит проверку, а не просто игнорируется. Wildcard охватывает любое имя селектора, какое только может придумать мошенник, — ведь имя выбирает он.

И запись, которую нужно оставить точно такой, какая она есть

Ничто из вышеперечисленного не затрагивает входящую почту, и не должно затрагивать. Именно MX-запись превращает каждый адрес на домене в ящик здесь, и ничего из сказанного выше её не меняет:

MX-запись — без изменений10 smtp.grabmail.io

Три новые записи и эта отвечают на разные вопросы, поэтому не взаимодействуют друг с другом: SPF и DMARC читают серверы, решающие, стоит ли принять почту, заявляющую права на вас, а MX читают серверы, решающие, куда доставить почту, адресованную вам. Домен со всеми четырьмя записями — это домен, который принимает всё и не ручается ни за кого.

Проверка результата тремя командами

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

shell
$ dig +short TXT      yourdomain.com
dig +short TXT _dmarc.yourdomain.com
dig +short MX       yourdomain.com

Подставьте свой домен. Вот что должно получиться — плюс-минус другие TXT-записи, которые уже могли быть у вас на этом имени:

ожидаемый ответ
"v=spf1 -all"
"v=DMARC1; p=reject; sp=reject; adkim=s; aspf=s"
10 smtp.grabmail.io.

Четыре способа, которыми это может пойти не так, примерно в порядке частоты:

Первая команда вообще ничего не отвечает
Запись ещё не распространилась, либо её добавили не на то имя. TXT-записи на самом домене должны стоять на @, а не на www, — обычный виновник здесь панель, которая по умолчанию подставляет то имя, что вы редактировали последним.
В ответ приходят две SPF-записи
Домену разрешена ровно одна. Две — это не строже, чем одна, это постоянная ошибка, и принимающий сервер, обнаруживший две записи, сочтёт проверку SPF не проваленной, а сломанной. Если у вас уже была SPF-запись, отредактируйте именно её, вместо того чтобы добавлять вторую.
Строка DMARC возвращается, но она ничего не обеспечивает
Внимательно прочитайте значение: оно должно начинаться с v=DMARC1, а теги разделяться точкой с запятой. Запись без тега версии или запись, где точка с запятой превратилась в запятую, — это не более слабая политика, это нечитаемая запись, а нечитаемая запись равна полному отсутствию политики.
Ответ по MX изменился
А не должен был. Если строка MX теперь отсутствует, показывает голую точку или указывает на хост, отличный от smtp.grabmail.io, — остановитесь и верните её на место прежде, чем делать что-либо ещё: от этой записи зависит ваш почтовый ящик.

То, что упускают почти все: субдомены

DMARC и SPF делят пространство имён по-разному, и именно в этом различии течёт тщательно защищённый домен. sp=reject действительно охватывает каждый субдомен, существующий или нет. SPF работает совсем иначе: он ищется по точному имени в конверте, и у имени без собственной SPF-записи попросту нет SPF-записи — оно не наследует родительскую.

Что использует мошенникSPF на этом имениЧто это останавливает
yourdomain.comНайдена: -all, поэтому проверка не пройдена.SPF и DMARC вместе. Это как раз тот случай, для которого написаны три записи выше.
billing.yourdomain.comНет, если вы её не опубликуете. SPF возвращает не провал, а отсутствие результата.Только DMARC, через sp=reject, — этого достаточно, и именно поэтому этот тег не опционален.
yourdomaln.com, похожий доменНеважно. Это не ваш домен.Тут нечего публиковать. Другое имя, другой владелец, другие записи.

DMARC сам по себе покрывает вторую строку, так что это скорее подстраховка, чем дыра, — но wildcard-запись SPF стоит одной строки и закрывает пробел ещё и на уровне SPF, а это важно для тех получателей, которые проверяют SPF, но не реализуют DMARC:

Wildcard SPF — ещё одна TXT-запись* TXT v=spf1 -all

DNS-wildcard отвечает только за имена, у которых нет собственных записей. Если у mail.yourdomain.com уже есть хоть какая-то TXT-запись, wildcard для этого имени не учитывается, и вам придётся опубликовать SPF-запись там явно. Для домена, который используется только как catch-all, такая ситуация достаточно редка, чтобы о ней стоило знать, но не стоило специально планировать.

Отчёты, и стоит ли их вообще получать

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

DMARC с отчётностью — замените доменv=DMARC1; p=reject; sp=reject; adkim=s; aspf=s; rua=mailto:dmarc@yourdomain.com

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

  • Это XML, сжатый gzip, во вложении. Не сводка, которую читаешь за кофе. Небольшие домены получают от крупных почтовых провайдеров по нескольку штук в день, каждая на пару килобайт; вам понадобится чем их распаковать и прочитать.
  • Пустой отчёт — это хороший результат. Домен, который ничего не отправляет, должен получать отчёты, где перечислены одни только провалы, а тихая неделя означает, что вас сейчас никто не подделывает, — это информация, и получить её больше неоткуда.
  • Они приходят как обычная почта. Здесь это значит — в обычный ящик: его можно читать в браузере и через API, как и всё остальное, и он удаляется через 5 дней вместе со всем остальным.

Если вы предпочитаете вообще их не собирать, просто не добавляйте тег. Запись DMARC без rua совершенно корректна и защищает ровно так же; отчётность — это способ узнать, что происходит, а не способ, которым обеспечивается политика.

Чего это не делает

Эти записи узко нацелены, и чёткое понимание их границ — это разница между мерой защиты, на которую полагаются правильно, и той, на которую полагаются неправильно. Четыре вещи, которые они не покрывают:

Они не фильтруют ваш собственный ящик
SPF и DMARC на вашем домене — это инструкции для серверов, принимающих почту от вас. Их читают чужие почтовые системы, а не ваша, и они никак не влияют на то, что оказывается в catch-all. В ящик по-прежнему попадает всё, что мир отправляет на адрес, единственным пропуском к которому служит знание этого адреса.
Они не останавливают имя в строке From
Письмо вида Your Company <attacker@gmail.com> проходит все проверки, потому что аутентифицированный домен и правда принадлежит атакующему. DMARC защищает домен, а не отображаемое имя перед ним, — а на телефоне зачастую видно только это имя.
Они не затрагивают похожий домен
Домен, отличающийся от вашего на один символ, — это чужой домен с чужими записями. Ничто из того, что вы публикуете, до него не дотягивается. Это задача регистратора и мониторинга, и это действительно другая задача.
Они не делают ящик приватным
У адреса здесь по-прежнему нет пароля: кто знает адрес, тот может его читать, — на этой сделке построен весь сервис. Собственный домен убирает угадывание, но не чтение — честная версия этого изложена в руководстве про catch-all-домены.

Делаем всё от начала до конца

Вся работа целиком, в том порядке, который на каждом шаге оставляет домен рабочим:

  1. Сначала подтвердите MX. dig +short MX yourdomain.com должен отвечать smtp.grabmail.io и ничем больше. Исправьте это прежде, чем добавлять что-либо ещё, — всё остальное бесполезно на домене, который не принимает почту.
  2. Добавьте SPF-запись на @, если там уже нет ни одной, — а если есть, отредактируйте её: две записи — это ошибка, а не более строгая настройка.
  3. Добавьте DMARC-запись на _dmarc, сразу со строгой политикой. Здесь нечего внедрять поэтапно, и, пропустив этапы, вы ничего не сломаете.
  4. Добавьте wildcard-запись DKIM на *._domainkey, а также wildcard-запись SPF, если хотите закрыть уровень субдоменов дважды.
  5. Прочитайте все четыре записи обратно через dig, обратившись к публичному резолверу, после того как истечёт TTL.
  6. Отправьте себе что-нибудь. Напишите письмо на один из своих адресов на этом домене откуда угодно и откройте ящик. Если письмо дошло, входящая сторона пережила изменения, — а это единственная регрессия, которую стоит проверять.

На этом домен готов: он принимает любой адрес, какой вы на нём когда-либо придумаете, и не ручается ни за кого. Если вы ещё не подключили домен, начните с руководства про catch-all — это одна запись и те же пять минут, — а потом возвращайтесь на эту страницу: такой порядок не оставляет ничего недоделанным.

Вопросы

Действительно ли мне нужна DKIM-запись, если я ничего не подписываю?

Для работы вашей собственной почты она не нужна — самой почты попросту нет. Вы публикуете её, чтобы мошенник не мог придумать имя селектора, подписать письмо собственным ключом и заставить это пройти проверку, — пустой ключ это постоянный ответ отозван на любое имя селектора, какое он бы ни выбрал. Это одна запись, она никогда не требует обслуживания, и она закрывает единственную лазейку, которую оставляют открытой SPF и DMARC.

Уменьшит ли всё это количество спама, приходящего в мой catch-all?

Нет, и об этом стоит сказать прямо, потому что это самое частое ожидание. Эти записи регулируют почту, которая заявляет, что пришла от вашего домена. На почту, приходящую на ваш домен, они не влияют — каждый адрес на нём по-прежнему принимает всё, в этом и состоит catch-all. Если проблема в нежелательной почте на конкретном адресе, решение — перестать использовать этот адрес, а не менять эти записи.

А если позже я захочу отправлять почту с этого домена?

Тогда вы меняете две вещи, в таком порядке: сначала авторизуете нового отправителя в записи SPF, прежде чем отправлять хоть что-то, и добавляете его DKIM-ключ на нужном ему селекторе. Wildcard *._domainkey не блокирует настоящий селектор — явная запись на точном имени находится первой, а wildcard учитывается только для имён, у которых своей записи нет. Ничто здесь не загоняет вас в угол — это просто означает, что домен по умолчанию закрыт, а не открыт.

Стоит ли для безопасности начать с p=none или p=quarantine?

Эти этапы существуют, чтобы защитить отправителей, которых вы ещё не нашли. У вас нет отправителей, так что защищать этапам нечего, и ломать строгой политике тоже нечего. Начать с none на домене только на приём — не значит снизить риск: это публикация записи, которая просит принимающие серверы ничего не делать, и домен остаётся таким же уязвимым для подделки, каким был раньше, — с дополнительным недостатком выглядеть завершённым.

Повлияет ли добавление этих записей на мою MX-запись или на мой ящик?

Ни капли. Это отдельные записи, отвечающие на отдельные вопросы, и ни один принимающий сервер не сверяется с вашими SPF или DMARC, решая, куда доставить адресованную вам почту. Единственное, что действительно сломало бы ящик, — это изменение самой MX-записи, и именно поэтому нулевой MX-записи, которую рекомендуют руководства про припаркованные домены, выше посвящён отдельный раздел.

Через сколько времени это начнёт действовать?

Новые записи становятся пригодны к использованию, как только распространятся, — обычно это минуты. Изменение уже существующей записи занимает столько же, сколько её старый TTL, потому что резолверы, получившие прежнее значение, хранят его до истечения срока. Если вы только собираетесь редактировать существующую запись, снизить её TTL за день до этого — приём, который делает изменение быстрым; а если вы уже отредактировали её, остаётся только ждать.

Нужна ли отдельная запись для каждого субдомена?

Для DMARC — нет: sp=reject покрывает их все, включая субдомены, которые никогда не существовали. Для SPF, строго говоря, да — субдомен не наследует SPF-запись родителя, — но одна wildcard-запись TXT на * отвечает за каждое имя без собственных записей, а на catch-all-домене это все имена.

Можно ли вместо этого направить отчёты DMARC на адрес Gmail?

Можно, но тогда это должен разрешить другой домен: адрес rua вне вашего собственного домена требует записи на yourdomain.com._report._dmarc.gmail.com, которую вы не можете опубликовать, потому что это имя не ваше. Именно поэтому в примере выше отчёты отправляются на адрес вашего же домена, где авторизация не нужна и почта просто попадает в catch-all.

Как понять, что всё действительно работает?

Прямое доказательство — отчёт: включите rua, и сводки назовут каждый источник, пытавшийся отправлять почту от вашего имени, и то, что сделал с этим каждый получатель. Без отчётов практическая проверка — это прочитать записи обратно через dig с публичного резолвера: политику обеспечивают серверы, которые её читают, так что запись, которая корректно резолвится для посторонних, — это работающая запись.

Читать дальше

Попробуйте, пока свежо

Адрес — это один клик, без аккаунта и карты. Всё из этого руководства сразу заработает на нём.

С возвращением

Ваши ящики и ваши домены в одном месте.