Проверка DNS и защиты почты своего домена командами dig: SPF, DKIM, DMARC, CAA, DNSSEC

0
13
Обложка статьи: Проверка DNS и защиты почты своего домена командами dig: SPF, DKIM, DMARC, CAA, DNSSEC

Защита почтового домена и сертификатов начинается с записей DNS, а проверить их можно одной командой без онлайн-сервисов. Типичная картина у небольших организаций: есть SPF от почтового провайдера, но нет DMARC, поэтому письма от вашего имени подделываются, а получатели не знают, что с ними делать; нет CAA, и сертификат может выпустить любой центр; нет DNSSEC. Ниже набор проверок командой dig с разбором результата и скрипт, который считает DNS-запросы в SPF и находит превышение предела.

Статья опирается на логику направления «Сетевая безопасность» из методики зрелости Группы Сбер (источник); это методика для крупных компаний, мы используем её как ориентир и пересказываем своими словами. Команды выполнены на Debian 12 с публичным резолвером; примеры результатов получены на реальных записях, имена вашего домена заменены на example.com. Проверяйте только свои домены. Настройка самих записей: SPF, DKIM и DMARC.

Что должно получиться

Уровень Что это значит на практике
2. Гигиенический Публичные сервисы и домены защищены от типовых атак, конфигурация контролируется

Критерии сформулированы нами по мотивам методики, это ориентир, а не оценка соответствия.

Что проверять

Запись Команда Хороший результат
MX (куда идёт почта) dig +short MX example.com Серверы вашего почтового провайдера
SPF dig +short TXT example.com Ровно одна запись v=spf1 ..., не более 10 DNS-запросов
DKIM dig +short TXT СЕЛЕКТОР._domainkey.example.com Запись v=DKIM1; k=rsa; p=...
DMARC dig +short TXT _dmarc.example.com Запись v=DMARC1; p=quarantine или reject
CAA dig +short CAA example.com Перечень центров, которым разрешён выпуск (например, 0 issue "letsencrypt.org")
DNSSEC dig +short DS example.com и dig example.com +dnssec Запись DS у родительской зоны; флаг ad в ответе валидирующего резолвера
NS (у кого DNS) dig +short NS example.com Не менее двух серверов у надёжного провайдера

Селектор DKIM зависит от провайдера: у многих используется default, mail, selector1 или google; точное значение смотрите в настройках почтового сервиса или в заголовке DKIM-Signature (поле s=) полученного от вас письма. Запись с публичным ключом в ответе выглядит так: "v=DKIM1; k=rsa; t=s; p=MIGfMA0GCSqGSIb3...". Если для типичных селекторов ответ пуст, а письма подписываются, значит вы просто не нашли селектор, а не записи нет.

SPF: смотрим, не превышен ли предел запросов

Проверка SPF по стандарту допускает не более десяти DNS-запросов; каждый include, a, mx, exists, ptr и redirect считается как запрос, причём вложенные записи провайдеров учитываются тоже. При превышении получатель выдаёт permerror и письма могут не доставляться. Скрипт раскрывает записи рекурсивно через dig и считает запросы:

#!/usr/bin/env python3
"""Считает DNS-запросы, которые нужны для проверки SPF-записи домена (предел по RFC 7208: 10).
Раскрывает include и redirect рекурсивно; механизмы a, mx, ptr, exists и модификатор redirect считаются как запросы.
Использует команду dig. Проверяйте свои домены.
Запуск: python3 spf_lookups.py example.com [резолвер, по умолчанию 1.1.1.1]"""
import re
import subprocess
import sys

LIMIT = 10


def txt(domain, resolver):
    out = subprocess.run(['dig', '+short', '+time=3', '+tries=1', 'TXT', domain, '@' + resolver],
                         capture_output=True, text=True).stdout
    records = [''.join(re.findall(r'"([^"]*)"', line)) for line in out.splitlines() if line.strip()]
    return [r for r in records if r.lower().startswith('v=spf1')]


def walk(domain, resolver, seen, depth=0):
    if domain in seen or depth > 10:
        return 0, [f'{domain}: повтор или слишком глубокая вложенность']
    seen.add(domain)
    recs = txt(domain, resolver)
    if not recs:
        return 0, [f'{domain}: SPF-записи нет']
    if len(recs) > 1:
        return 0, [f'{domain}: ошибка, найдено {len(recs)} записей SPF (должна быть одна)']
    rec = recs[0]
    notes = [f'{"  " * depth}{domain}: {rec}']
    count = 0
    for term in rec.split()[1:]:
        t = term.lstrip('+-~?')
        low = t.lower()
        if low.startswith('include:') or low.startswith('redirect='):
            count += 1
            target = t.split(':', 1)[1] if ':' in t else t.split('=', 1)[1]
            c, n = walk(target, resolver, seen, depth + 1)
            count += c
            notes += n
        elif low.startswith(('a:', 'mx:', 'exists:', 'ptr')) or low in ('a', 'mx'):
            count += 1
    return count, notes


def main():
    if len(sys.argv) < 2:
        sys.exit('Использование: spf_lookups.py домен [резолвер]')
    domain = sys.argv[1]
    resolver = sys.argv[2] if len(sys.argv) > 2 else '1.1.1.1'
    count, notes = walk(domain, resolver, set())
    print('\n'.join(notes))
    status = 'в пределах нормы' if count <= LIMIT else 'ПРЕВЫШЕН предел, проверка SPF даст permerror'
    print(f'Всего DNS-запросов для проверки: {count} из {LIMIT}: {status}')
    return 0 if count <= LIMIT else 1


if __name__ == '__main__':
    sys.exit(main())
python3 spf_lookups.py example.com

Пример результата для домена, который делегирует SPF почтовому провайдеру через redirect:

example.com: v=spf1 redirect=_spf.provider.example
  _spf.provider.example: v=spf1 redirect=_spf.provider2.example
    _spf.provider2.example: v=spf1 include:_spf-ipv6.provider2.example include:_spf-ipv4-a... ~all
      _spf-ipv6.provider2.example: v=spf1 ip6:2a02:.../40 ... ~all
      ...
Всего DNS-запросов для проверки: 8 из 10: в пределах нормы

Результат этого скрипта на нескольких реальных доменах: домен с политикой «никому нельзя» (v=spf1 -all) требует 0 запросов; домен, использующий провайдера почты через две цепочки redirect и шесть include, укладывается в 8; крупная организация с большим числом внешних сервисов (облачная почта, поддержка, рассылки) оказалась ровно на пределе 10. Это показывает, как быстро добавление сервисов выбирает запас. Скрипт даёт оценку: он считает механизмы a и mx как один запрос каждый, не раскрывая их, и не проверяет доступность серверов. Код возврата 1, если предел превышен: удобно для регулярной проверки.

Если предел превышен, сократите список: уберите неиспользуемые сервисы, замените include явными подсетями ip4: (но следите за их актуальностью), разделите почтовые потоки по поддоменам (рассылки с отдельного поддомена с собственной записью SPF).

Что означает redirect

Запись v=spf1 redirect=_spf.провайдер означает «вся политика берётся у указанного домена»: ваша политика полностью определяется провайдером, включая его завершающий механизм (~all — мягкая неудача, -all — жёсткая). Это допустимо и удобно, но отдельно от DMARC не заменяет вашу политику: даже при мягком ~all от провайдера подделки не отклоняются, а помечаются. Поэтому нужен DMARC.

DMARC: самое частое отсутствие

Если запрос dig +short TXT _dmarc.example.com ничего не вернул, DMARC не настроен. Последствия: получатели сами решают, что делать с письмами, не прошедшими SPF и DKIM; нет отчётов о том, кто отправляет почту от вашего имени; домен проще использовать для подделок. Минимальная запись для начала сбора отчётов:

_dmarc.example.com.  IN TXT  "v=DMARC1; p=none; rua=mailto:dmarc-reports@example.com"

Затем ужесточайте политику по этапам, как описано в статье про SPF, DKIM и DMARC. Пример рабочей записи крупной организации: "v=DMARC1; p=quarantine; sp=reject; pct=100; rua=mailto:dmarc@...; fo=1": политика для основного домена — карантин, для поддоменов — отклонение, действует на все письма.

CAA: кто может выпускать сертификаты

Запись CAA ограничивает список центров сертификации, которым разрешено выпускать сертификаты для домена. Пример: 0 issue "letsencrypt.org". Без неё сертификат может выпустить любой центр при подтверждении владения доменом, и ошибочный или вредоносный выпуск проще. Добавляйте записи для центров, которыми вы пользуетесь, и перепроверяйте после смены поставщика сертификатов. Проверка: dig +short CAA example.com; пустой ответ означает, что ограничений нет. Дополнительно: проверка TLS.

DNSSEC: подпись записей DNS

DNSSEC защищает от подмены DNS-ответов. Признаки включённого DNSSEC: у родительской зоны есть запись DS (dig +short DS example.com возвращает строку вида 2371 13 2 32996839A6D8...), а валидирующий резолвер отдаёт ответ с флагом ad (authenticated data): dig example.com @1.1.1.1 +dnssec показывает в строке flags: значение qr rd ra ad. Если записи DS нет, DNSSEC не включён. Включение зависит от DNS-провайдера и регистратора (подписание зоны и публикация DS у регистратора); при ошибке в настройке домен перестаёт разрешаться у валидирующих резолверов, поэтому включайте по инструкции провайдера и проверяйте.

Регулярная проверка

  • Раз в квартал и после смены почтового или DNS-провайдера выполняйте набор команд из таблицы.
  • Добавьте в мониторинг проверку наличия и неизменности записей SPF, DMARC, CAA и NS: изменение записи без вашей заявки — признак компрометации аккаунта DNS-провайдера.
  • Защитите аккаунт регистратора и DNS-провайдера: MFA, ограниченный круг лиц, блокировка переноса домена.
  • Записи DNS и ответственные за них — часть реестра активов: реестр ИТ-активов.

Диагностика

Симптом Причина и что делать
Две записи SPF Неправильно: допускается одна. Объедините в одну запись
SPF показывает 11 и более запросов Слишком много сервисов. Сократите, разнесите потоки по поддоменам, замените часть include подсетями
DMARC в режиме p=none месяцами Политика не ужесточается. Разберите отчёты, исправьте источники и перейдите на quarantine, затем reject
Нет ответа на DKIM Неверный селектор. Найдите его в заголовке письма (s=) и проверьте запись
Разные результаты на разных резолверах Кэш или изменения не распространились. Подождите время жизни записи (TTL) или запросите авторитетный сервер: dig @СЕРВЕР_NS example.com TXT

Где это в модели зрелости

Материал относится к направлению «Сетевая безопасность» (материалы направления, карта зрелости). Контроль DNS-записей, защита почтового домена и ограничение выпуска сертификатов относятся к управляемому периметру, который требуется на уровне 2.

Как проверить

  1. У домена одна запись SPF с числом запросов не более 10, есть DKIM и DMARC (не слабее p=quarantine для рабочих доменов).
  2. Для неиспользуемых доменов опубликованы v=spf1 -all и DMARC p=reject.
  3. Есть запись CAA с центрами, которыми вы пользуетесь; DNSSEC включён или его отсутствие осознанное решение.
  4. Проверки выполнены после последнего изменения провайдеров; регулярная проверка и оповещение об изменениях настроены.

Источники

  • Методика оценки уровня зрелости кибербезопасности компании, Группа Сбер: sberbank.ru.
  • RFC 7208 (SPF): rfc-editor.org; RFC 8659 (CAA): rfc-editor.org; RFC 4033 (DNSSEC): rfc-editor.org. Проверьте, не заменены ли документы новыми редакциями.
  • Руководство man dig для вашей версии.

Оставьте свой ответ