На первый взгляд, SPF (Sender Policy Framework) кажется простым — владелец домена публикует список IP-адресов и серверов, имеющих право отправлять письма от его имени, а принимающий сервер сопоставляет входящее соединение с этим списком. Однако, за лаконичным синтаксисом скрываются критические ограничения, которые могут негативно сказаться на доставляемости сообщений в сложных инфраструктурах. Одним из таких ограничений является лимит в 10 DNS-запросов, установленный в RFC 7208. В этом руководстве мы подробно рассмотрим механизмы, квалификаторы и модификаторы SPF, объясним, как считать реальные запросы, и подробно разберем, как SPF взаимодействует с выравниванием DMARC.
- Как работает SPF
- Коды результатов SPF
- Синтаксис SPF-записи: механизмы, квалификаторы и модификаторы
- Лимит в 10 DNS-запросов
- Лимит пустых запросов
- Пример SPF-записи с подсчётом DNS-запросов
- Директивы include провайдеров
- SPF, DKIM и DMARC: выравнивание и совместная работа
- Пользовательский Return-Path
- Техники выравнивания SPF
- Как правильно настроить SPF-запись: лучшие практики и чеклист
- Распространённые ошибки
- Инструменты для проверки и генерации SPF-записи онлайн
- Источники и ссылки
- Ответы на эти вопросы могут быть для вас полезными
Как работает SPF
Когда принимающий почтовый сервер принимает входящее SMTP-соединение, он извлекает домен из команды MAIL FROM (отправитель конверта, также называемый Return-Path) и выполняет DNS TXT-запрос к этому домену. Если запись SPF найдена, получатель сверяет подключающийся IP с авторизованными механизмами, перечисленными в записи.
📖 Определение — SPF (Sender Policy Framework) — это основанный на DNS протокол аутентификации электронной почты (RFC 7208), позволяющий владельцу домена публиковать список IP-адресов и имён хостов, авторизованных для отправки электронной почты с использованием этого домена в качестве отправителя конверта.
# Поток оценки SPF
1. Отправитель подключается с IP 198.51.100.42
2. SMTP MAIL FROM: user@example.com
3. Получатель запрашивает TXT-запись для example.com
4. Запись: "v=spf1 ip4:198.51.100.0/24 include:_spf.google.com -all"
5. 198.51.100.42 соответствует ip4:198.51.100.0/24 → Результат: PASS
Коды результатов SPF
RFC 7208 §2.6 определяет семь возможных результатов оценки:
| Результат | Значение |
|---|---|
| Pass | IP авторизован записью SPF |
| Fail | IP явно не авторизован |
| SoftFail | IP, вероятно, не авторизован (тестовый режим) |
| Neutral | Домен не делает утверждений об IP |
| None | Запись SPF не найдена |
| TempError | Временная ошибка DNS (повторить позже) |
| PermError | Постоянная ошибка конфигурации (например, превышен лимит запросов) |
🚫 PermError — это тихая и серьезная ошибка. Если ваша запись SPF превышает 10 DNS-запросов, получатели возвращают PermError, который может быть ошибочно воспринят как сбой системы. В таких случаях законная почта может блокироваться или попадать в спам, и вы не получите уведомлений о возврате.
Синтаксис SPF-записи: механизмы, квалификаторы и модификаторы
Механизмы SPF определяют, каким образом запись сопоставляет IP-адрес отправителя с авторизованными источниками.
| Механизм | Синтаксис | DNS-запросы | Описание |
|---|---|---|---|
| ip4 | ip4:192.0.2.0/24 | 0 | Прямое сравнение IPv4-адреса или диапазона |
| ip6 | ip6:2001:db8::/32 | 0 | Прямое сравнение IPv6-адреса или диапазона |
| include | include:_spf.example.com | 1+ | Рекурсивно оценивает запись SPF другого домена |
| a | a / a:example.com | 1 | Совпадает, если IP соответствует A/AAAA-записи домена |
| mx | mx / mx:example.com | 1+ | Совпадает, если IP является одним из MX-хостов домена |
| exists | exists:%{i}.example.com | 1 | Совпадает, если DNS-запрос возвращает любой результат |
| redirect | redirect=_spf.example.com | 1 | Заменяет всю оценку записью другого домена |
| ptr | ptr / ptr:example.com | 1 | Устарело; не использовать |
| all | all | 0 | Соответствует любому IP; финальный перехватчик |
💡 Механизм ptr существует в спецификации, но RFC 7208 §5.5 явно не рекомендует его использование: «Этот механизм НЕ ДОЛЖЕН публиковаться». Он медленный, ненадёжный и засчитывается как DNS-запрос.
Лимит в 10 DNS-запросов
RFC 7208 §4.6.4 устанавливает жёсткий лимит: оценка SPF не должна вызывать более 10 DNS-механизмов/модификаторов, требующих запросов. Это включает include, a, mx, exists, redirect и ptr. Не включает ip4, ip6 и all.
# Засчитываются в лимит 10 запросов:
Каждый механизм оценки SPF имеет свои особенности: include: требует 1 запроса, a и mx - по 1 запросу каждый, с добавлением дополнительных запросов для каждого MX-хоста, exists - 1 запрос, и redirect - тоже 1 запрос. Помните, что механизм ptr, который считается устаревшим, также требует отдельного запроса.
# НЕ засчитываются:
ip4: → 0 запросов (прямое сравнение IP)
ip6: → 0 запросов (прямое сравнение IP)
all → 0 запросов (финальный перехватчик)
10 — максимальное количество DNS-запросов, разрешённых при одной оценке SPF (RFC 7208 §4.6.4)
Лимит пустых запросов
RFC 7208 §4.6.4 также устанавливает лимит пустых запросов (void lookup), который равен 2. Пустой запрос — это DNS-запрос, который возвращает либо NXDOMAIN, либо пустой ответ. Если в процессе оценки происходит более 2 пустых запросов, это приводит к PermError.
Пример SPF-записи с подсчётом DNS-запросов
Я часто вижу, как команды добавляют нового вендора и не замечают, что запись уже давно превысила лимит. Вот реальный пример того, как накапливаются запросы для домена, использующего Google Workspace, Mailchimp и SendGrid:
v=spf1 include:_spf.google.com include:servers.mcsv.net include:sendgrid.net -all
Разбивка подсчёта запросов:
┌─ include:_spf.google.com → 1
│ ├─ include:_netblocks.google.com → 2
│ ├─ include:_netblocks2.google.com → 3
│ └─ include:_netblocks3.google.com → 4
├─ include:servers.mcsv.net → 5
│ └─ include:mcsv.net → 6
├─ include:sendgrid.net → 7
│ └─ include:u12345.wl.sendgrid.net → 8
└─ Итого: 8 запросов ✅ (меньше 10)
🚫 Теперь добавьте Salesforce (include:_spf.salesforce.com → 1) и Zendesk (include:mail.zendesk.com → 2 вложенных). Это доводит счётчик до 11 запросов — PermError. Электронная почта ломается незаметно, без каких-либо явных сигналов об ошибке.
Директивы include провайдеров
Перед добавлением нового include: всегда проверяйте количество его вложенных запросов с помощью инструмента проверки SPF. Один include может потребовать от 1 до 5 запросов в зависимости от собственной цепочки SPF провайдера.
| Провайдер | Директива include | Примерное число запросов |
|---|
⚡ Совет: цепочки вложенных запросов у провайдеров меняются без предупреждения. Число запросов в таблице — ориентировочное; всегда проверяйте актуальное значение инструментом.
SPF, DKIM и DMARC: выравнивание и совместная работа
Чтобы DMARC считал SPF прошедшим методом аутентификации, должны быть выполнены два условия:
- SPF должен давать результат Pass для домена MAIL FROM.
- Домен MAIL FROM должен совпадать с доменом заголовка From: (расслабленное или строгое совпадение согласно тегу aspf в DMARC).
Пользовательский Return-Path
Чтобы добиться выравнивания SPF со сторонними отправителями, настройте пользовательский return-path (обратный путь) с использованием вашего поддомена:
# Пример: пользовательский return-path для SendGrid
Стандартный return-path: bounces.sendgrid.net → SPF проходит для sendgrid.net
Пользовательский return-path: em.yourdomain.com → SPF проходит для yourdomain.com
DNS-запись:
em.yourdomain.com CNAME u12345.wl.sendgrid.net
На практике я рекомендую настраивать пользовательский return-path для каждого стороннего отправителя — это единственный способ обеспечить надёжное выравнивание SPF без зависимости от DKIM как единственного пути аутентификации.
Техники выравнивания SPF
Когда вы достигаете лимита в 10 запросов, выравнивание SPF (SPF flattening) заменяет директивы include: их разрешёнными адресами ip4: и ip6:, сводя количество запросов для этих записей к нулю.
# До выравнивания (8 запросов):
# После выравнивания (0 запросов для IP Google):
v=spf1 ip4:209.85.128.0/17 ip4:172.217.0.0/16 ip4:108.177.8.0/21 include:servers.mcsv.net include:sendgrid.net -all
🚫 Выравнивание ненадёжно. IP-адреса провайдеров меняются без предупреждения. Если Google добавит новый диапазон IP, а ваша выровненная запись его не включает, почта с этого IP не пройдёт SPF. Необходимо автоматизировать выравнивание с помощью инструмента, который регулярно повторно разрешает адреса и обновляет вашу DNS-запись.
🎯 Более безопасной альтернативой выравниванию является использование модификатора redirect= для указания на динамически управляемую запись SPF на поддомене или использование сервиса вроде управления SPF от Cloudflare, который выполняет выравнивание автоматически.
Как правильно настроить SPF-запись: лучшие практики и чеклист
Завершайте записью -all. Используйте жёсткий отказ (-all) в продакшене. ~all (мягкий отказ) предназначен только для тестирования; он пропускает несанкционированную почту.
Следите за количеством запросов. Проверяйте общее количество DNS-запросов после каждого изменения. Добавление одного вендора может превысить лимит в 10. Мой совет — автоматизировать эту проверку в CI-пайплайне или настроить мониторинг через dmarcian.
Одна запись на домен. RFC 7208 §3.2: домен не должен иметь несколько записей SPF. Две записи вызывают PermError.
Избегайте устаревших механизмов. Никогда не используйте ptr. Он медленный, ненадёжный и тратит один запрос. RFC 7208 явно не рекомендует его.
Используйте ip4/ip6 для статических IP. Выделенные серверы с фиксированными IP должны использовать ip4: / ip6: — без затрат на запросы.
Соблюдайте лимит в 255 символов на строку. DNS TXT-записи ограничены строками по 255 байт. Длинные записи должны быть разбиты на несколько строк в рамках одного набора TXT-записей.
Распространённые ошибки
🚫 Несколько записей SPF на одном домене. Публикация двух TXT-записей, начинающихся с v=spf1, вызывает PermError (RFC 7208 §3.2). Объедините их в одну запись.
🚫 Превышение лимита в 10 запросов. Это ошибка конфигурации SPF №1. Каждый include: добавляет запросы рекурсивно. Используйте инструмент проверки SPF для валидации общего числа.
Инструменты для проверки и генерации SPF-записи онлайн
Проверяйте и создавайте свои записи SPF с помощью этих инструментов:
| Инструмент | Назначение |
|---|---|
| MXToolbox SPF Record Lookup | Проверка записи и подсчёт запросов |
| dmarcian SPF Surveyor | Визуализация дерева include и подсчёт запросов |
| Google Admin Toolbox — Check MX | Диагностика DNS и SPF для Google Workspace |
| Kitterman SPF Tester | Тестирование результата SPF для конкретного IP |
| Cloudflare SPF Management | Автоматическое выравнивание и мониторинг |
Источники и ссылки
📄 RFC 7489 — DMARC
🎯 Ключевой вывод: SPF сообщает миру, каким IP разрешено отправлять электронную почту от имени вашего домена — но он проверяет только отправителя конверта, а не видимый заголовок From:. Строго соблюдайте лимит в 10 DNS-запросов, всегда завершайте записью -all и сочетайте SPF с DKIM, чтобы у DMARC был надёжный путь выравнивания, который выдерживает пересылку. Проверяйте количество запросов после каждого изменения.
Ответы на эти вопросы могут быть для вас полезными
Что произойдёт, если у домена две SPF-записи?
Наличие двух TXT-записей, начинающихся с v=spf1, вызывает PermError согласно RFC 7208 §3.2. Принимающий сервер не может определить, какую из них использовать, и аутентификация завершается ошибкой. Объедините все механизмы в одну запись.
Почему SPF проходит, но DMARC всё равно не выравнивается?
Скорее всего, сторонний отправитель использует собственный Return-Path (например, bounces.sendgrid.net). SPF проходит для домена провайдера, а не вашего — выравнивание не выполняется. Решение: настройте пользовательский return-path на поддомене вашего домена или убедитесь, что DKIM настроен и выравнивание идёт через него.
Можно ли использовать redirect= вместо include:?
Да, но с ограничением: redirect= заменяет всю оценку SPF записью другого домена и не может сосуществовать с механизмом all. Используйте redirect= только тогда, когда хотите полностью делегировать политику SPF другому домену, например управляемой записи на поддомене.
Как безопасно добавить нового почтового провайдера, не превысив лимит запросов?
Перед добавлением include: нового провайдера проверьте его цепочку запросов инструментом вроде dmarcian SPF Surveyor или MXToolbox. Если лимит близок к 10, рассмотрите выравнивание SPF для существующих провайдеров с фиксированными IP-диапазонами или используйте сервис автоматического управления SPF.
Чем SoftFail (~all) отличается от Fail (-all) на практике?
При SoftFail принимающий сервер получает сигнал «вероятно, не авторизовано», но большинство серверов всё равно доставляют письмо — возможно, с пометкой в заголовках. При Fail (-all) сервер получает явный сигнал отклонить письмо. В продакшене всегда используйте -all; ~all оставьте только для начального тестирования новой записи.



