← Назад в блогРуководства

Почему пересылка почты ломает SPF и что делают SRS и ARC

Пересланные письма не проходят SPF, потому что IP пересыльщика нет в записи отправителя. Как SRS, DKIM и ARC меняют результат и что с этим делает DMARC.

Опубликовано: · 7 мин чтения

Пересылка почты ломает SPF, потому что SPF сравнивает IP-адрес подключившегося сервера с записью домена отправителя конверта, а простой пересыльщик меняет первое, не меняя второго. Конечный получатель видит, что сервер пересыльщика доставляет письмо «от» example.com, не находит этот сервер в SPF-записи example.com и возвращает fail. Ни на одной из сторон ничего не настроено неправильно: так SPF устроен. Пройдёт ли письмо DMARC, почти целиком зависит от DKIM.

В этой статье мы проследим путь одного письма через пересыльщика и посмотрим, что именно меняют SRS, DKIM и ARC.

Что на самом деле проверяет SPF

У доставки по SMTP два адреса отправителя:

  • отправитель конверта, который передаётся в команде MAIL FROM и позже записывается как Return-Path. Туда уходят возвраты (bounce).
  • заголовок From, который показывает почтовый клиент получателя.

SPF (RFC 7208) знает только о первом. Получатель берёт домен отправителя конверта (или имя из HELO как запасной вариант, например когда отправитель конверта пуст, как в возвратах), получает его SPF-запись и спрашивает: есть ли в ней IP-адрес, который подключается ко мне прямо сейчас?

Прямая доставка:

alice@example.com  ->  mail server of example.com (192.0.2.10)  ->  receiver
MAIL FROM:<alice@example.com>      connecting IP 192.0.2.10      spf=pass

Что делает простой пересыльщик

Простой пересыльщик — это алиас, файл .forward, правило «пересылать всю почту на» или пересылка почты, которая прилагается к домену у многих регистраторов. Он принимает письмо и отправляет его заново на другой адрес, сохраняя исходного отправителя конверта, чтобы возвраты уходили автору.

alice@example.com  ->  forwarder (203.0.113.7)  ->  bob's real mailbox
MAIL FROM:<alice@example.com>      connecting IP 203.0.113.7     spf=fail

203.0.113.7 принадлежит пересыльщику. example.com о нём никогда не слышал и не должен его перечислять: отправитель не может знать все адреса, на которые его получатели пересылают почту.

SRS: починка SPF для пересыльщика

Sender Rewriting Scheme меняет отправителя конверта на адрес в собственном домене пересыльщика перед повторной отправкой:

MAIL FROM:<SRS0=HHH=TT=example.com=alice@forwarder.example>

HHH — короткий хеш, TT — метка времени, а исходные домен и локальная часть сохраняются, чтобы возврат, присланный на этот адрес, можно было распаковать и передать дальше на alice@example.com. Хеш не даёт посторонним использовать пересыльщика как ретранслятор возвратов.

Теперь получатель проверяет SPF-запись forwarder.example, в которой 203.0.113.7 есть. SPF проходит.

Две вещи, которые нужно знать об SRS:

  • Это не стандарт IETF. Это спецификация сообщества, вышедшая из проекта SPF, и реализации отличаются в деталях.
  • Она чинит SPF, а не DMARC. После переписывания домен, аутентифицированный через SPF, — это forwarder.example, тогда как в заголовке From по-прежнему стоит example.com. DMARC требует, чтобы аутентифицированный домен был выровнен с доменом From, поэтому SPF-ветка DMARC всё равно не проходит. Просто проваливается она тихо, а не громко.

DKIM: часть, которая выживает

DKIM-подпись — часть письма, а не соединения. Она покрывает тело и выбранный набор заголовков и проверяется открытым ключом из DNS подписавшего. Пересыльщик, передающий письмо без изменений, оставляет подпись действительной, с какого бы IP он ни подключался. Если подписывающий домен (d=) выровнен с доменом From, DMARC проходит по одной только DKIM-ветке.

DKIM ломается, когда меняется подписанная часть:

  • список рассылки добавляет [имя-списка] в тему или подвал в тело письма;
  • шлюз переписывает тело, например добавляя дисклеймер или подменяя ссылки;
  • система перекодирует письмо так, как канонизация подписи не допускает.

Простая пересылка ничего из этого не делает. Списки рассылки делают первое постоянно.

Таблица сценариев

Допустим, example.com публикует SPF, подписывает письма с d=example.com и держит p=reject.

Сценарий Результат SPF Результат DKIM Результат DMARC
Прямая доставка pass, выровнен pass, выровнен pass
Простая пересылка, письмо не тронуто fail pass, выровнен pass (через DKIM)
Простая пересылка, у отправителя нет DKIM fail none fail
Пересылка с SRS, письмо не тронуто pass для пересыльщика, не выровнен pass, выровнен pass (через DKIM)
Пересылка с SRS, у отправителя нет DKIM pass для пересыльщика, не выровнен none fail
Список рассылки, меняющий тему или тело pass для списка, не выровнен fail (сломан) fail, если только список не переписывает From
То же, с цепочкой ARC, которой получатель доверяет как выше как выше fail, но получатель может переопределить локально

На практике важны вторая и пятая строки: SRS не спасёт отправителя без выровненного DKIM, а отправителю с выровненным DKIM SRS для прохождения DMARC не нужен.

ARC: передать дальше то, что видел посредник

Authenticated Received Chain (RFC 8617, статус Experimental) отвечает за строки со списками рассылки. Посредник, обрабатывающий письмо, записывает результаты аутентификации, которые он наблюдал при получении, и подписывает эту запись. Каждый узел добавляет набор из трёх заголовков с порядковым номером:

ARC-Authentication-Results: i=1; lists.example.org;
   spf=pass smtp.mailfrom=example.com; dkim=pass header.d=example.com;
   dmarc=pass header.from=example.com
ARC-Message-Signature: i=1; a=rsa-sha256; d=lists.example.org; s=arc1; …
ARC-Seal: i=1; a=rsa-sha256; cv=none; d=lists.example.org; s=arc1; …

Второй посредник добавляет i=2, и так далее. Конечный получатель может проверить цепочку и увидеть, что письмо проходило DMARC, когда пришло на lists.example.org, до того как список его изменил.

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

Из-за этой неопределённости списки рассылки для отправителей, чьи домены применяют DMARC, обычно поступают грубее: переписывают заголовок From на адрес в собственном домене списка, чтобы письмо было выровнено с SPF и DKIM самого списка.

Как читать заголовок Authentication-Results

Отправьте письмо через пересыльщика на ящик, которым вы управляете, откройте исходный текст и найдите заголовок Authentication-Results, добавленный конечным получателем (самый верхний):

Authentication-Results: mx.receiver.example;
   spf=pass smtp.mailfrom=forwarder.example;
   dkim=pass header.d=example.com header.s=s2026;
   dmarc=pass header.from=example.com;
   arc=pass
Return-Path: <SRS0=a1b2=XY=example.com=alice@forwarder.example>
Поле О чём говорит
smtp.mailfrom= Домен, по которому проверялся SPF. Если это домен пересыльщика, используется SRS.
spf= Результат для этого домена и подключившегося IP. fail с исходным доменом означает простого пересыльщика.
header.d= Домен, чья DKIM-подпись прошла проверку. Сравните его с header.from.
dmarc= Вердикт после выравнивания. Именно он решает.
arc= Была ли цепочка ARC и прошла ли она проверку.

Если заголовки удобнее вставить, чем читать, анализ заголовков письма разберёт их по частям.

Советы отправителям

  1. Подписывайте всё DKIM с выравниванием по домену From. Каждый сервис, отправляющий от вашего имени: почтовый провайдер, сервис рассылок, выставление счетов, служба поддержки. Именно это позволяет вашей почте пережить пересылку. Один SPF не переживёт её никогда.
  2. Не добавляйте IP-адреса пересыльщиков в свою SPF-запись. Вы не можете знать их все, они меняются, а каждый добавленный include идёт в счёт лимита в 10 запросов.
  3. Переходите на p=reject только тогда, когда отчёты DMARC показывают выравнивание DKIM у всех легитимных источников. Домену на p=reject, который опирается на один SPF, будут отказывать в доставке пересланной почты.
  4. Ожидайте небольшой остаток сбоев от списков рассылки. Порядок внедрения из статьи MX, SPF, DKIM и DMARC: как они работают вместе это учитывает.

Советы тем, кто пересылает почту

  • Используйте пересыльщика, который реализует SRS, а в идеале и подписание ARC. Без SRS каждое письмо с домена с -all приходит с spf=fail.
  • Подумайте о сборе вместо пересылки. Если целевой ящик может забирать почту из старой учётной записи по POP или IMAP, повторной отправки не происходит и аутентификация не нарушается.
  • Не пересылайте спам. Конечный получатель видит, что его доставляет IP вашего пересыльщика, и ставит это пересыльщику в вину. Фильтруйте до пересылки.
  • Подумайте о размещении ящика вместо пересылки. Домен, который только пересылает почту на бесплатный ящик, — хрупкая конфигурация, стоящая за большинством обращений «у меня пропадает почта»: см. чек-лист проверки DNS для писем, попадающих в спам.

Частые ошибки

  • Принимать spf=fail на пересланном письме за доказательство подделки. Прежде чем решать, посмотрите на dkim= и dmarc=.
  • Верить, что SRS чинит DMARC. Он чинит SPF для домена пересыльщика; выравнивание по-прежнему потеряно.
  • Добавлять записи include: для пересыльщиков получателей в собственную SPF-запись.
  • Переходить на p=reject с аутентификацией только по SPF, потому что «во всех наших тестах SPF проходит». В тестах редко участвует пересыльщик.
  • Считать, что ARC обязывает получателя принять письмо. Это свидетельство, предложенное получателю, который может доверять подписанту, а может и нет.
  • Добавлять дисклеймер на исходящем шлюзе после подписания DKIM. Так вы ломаете собственную подпись ещё до того, как письмо покинуло вас.

Проверьте в OrbitProbe

Проверка SPF в OrbitProbe показывает SPF-запись, которую публикует домен, и отмечает обычные структурные проблемы: несколько записей, +all, отсутствующий механизм all, слишком много DNS-запросов. При проблеме с пересылкой проверьте два имени: домен исходного отправителя (заканчивается ли запись на -all, из-за чего простая пересылка проваливается жёстко?) и домен пересыльщика (есть ли у него вообще действительная запись, чтобы почта, переписанная через SRS, могла пройти?). Проверка DNS читает опубликованную политику. Что случилось с одним конкретным письмом, записано только в заголовке Authentication-Results этого письма, так что читайте и то и другое.