Компания
1 068,81
рейтинг
11 июня 2014 в 13:20

Разработка → Как мы реализовали DKIM в «Mail.Ru для бизнеса»



Недавно на Хабре уже была статья о том, как «Mail.Ru для бизнеса» становится лучше благодаря вашим комментариям: мы рассказывали, как реализовывали ваши пожелания. Сегодня я хочу остановиться на одной из воплощенных хотелок — возможности настройки собственной DKIM-подписи. Для нас она была одним из приоритетов: настройка DKIM позволяет владельцам доменов верифицировать отправителя того или иного письма. В этом посте я расскажу о том, как мы внедряли эту возможность, и о том, как настроить DKIM-подпись для своего домена.

Немного о том, зачем нужна технология DKIM

Wikipedia напоминает нам, что «технология DomainKeys Identified Mail (DKIM) объединяет несколько существующих методов антифишинга и антиспама с целью повышения качества классификации и идентификации легитимной электронной почты. Вместо традиционного IP-адреса для определения отправителя сообщения DKIM добавляет в него цифровую подпись, связанную с именем домена организации. Подпись автоматически проверяется на стороне получателя».

То есть всякий раз, когда пользователь отправляет письмо, наш сервер добавляет в него специальный заголовок с цифровой DKIM-подписью. При генерации подписи используется секретный ключ (для каждого домена свой) и выдержки из письма. Этот заголовок позволяет серверу-получателю удостовериться, что письмо действительно отправлено владельцем этого домена.

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

Кроме того, DKIM-подпись нужна для работы технологии FBL (благодаря FBL отправители рассылок могут собирать фидбек о состоянии базы клиентов и их лояльности, а также проверять, как подписчики реагируют на рассылки, и дорабатывать содержание писем).

В общем, настройка DKIM-подписей — вещь, безусловно, полезная и необходимая, так что вопроса «Делать или нет?» не возникало. Мы взялись за работу. Дальше мы будем подробно рассказывать о том, как мы реализовывали данный функционал в «Mail.Ru для бизнеса». Если не хотите деталей, советуем сразу идти в пункт «Как мне настроить DKIM?».

Как настройка DKIM-подписей появилась в «Mail.Ru для бизнеса»

Для отправки писем у нас используется очень распространенный агент передачи почтовых сообщений (MTA, Mail Transfer Agent) exim4. Он уже имеет встроенные средства для размещения DKIM-подписи в исходящих сообщениях. До недавнего времени мы все свои письма именно таким образом и подписывали. Однако проблема в том, что количество подключенных бизнес-доменов постоянно растет, и у каждого домена свой секретный ключ. Если раньше достаточно было единожды разложить ключи по всем серверам и указать exim’у путь к этим ключам, то теперь такое решение уже никуда не годится. Проблему можно было бы решить, если «научить» exim обращаться за ключом в централизованную базу данных. Так мы и решили поступить.

Сказано — сделано. Многие специалисты ценят exim за богатые возможности настройки. При помощи встроенного языка конфигурации можно легко научить exim обращаться за данными в «плоские» файлы, берклеевские базы данных и даже выполнять SQL-запросы в реляционные БД, таких как MySQL. Для нужд почтового сервера среднестатистической компании возможностей конфигурирования хватит за глаза. Если же требуется нечто большее, то в exim’е имеются возможности для написания собственного lookup-модуля, который можно использовать в конфигурациях наравне со встроенными возможностями.

Для запроса ключа из БД создается небольшой вспомогательный lookup-модуль. Он занимается установкой подключения к базе данных, авторизацией, поиском нужного шарда, реплики, дешифрацией полученных данных и т. д., предоставляя наружу простой интерфейс словаря. Ниже вкратце описан сам процесс создания модуля.

Сначала в дерево исходников добавляем файл src/lookups/dkim.c (не забываем добавить его в систему сборки по аналогии с уже существующими модулями). В нём находятся исходники нашего модуля.

Далее описываем в файле структуру новых lookup-запросов:

/* Какой приватный ключ использовать для подписи */
static lookup_info _lookup_info1 = {
  US"dkim_privkey",      /* lookup name */
  lookup_querystyle,
  _open_connection,      /* open function */
  NULL,                          /* no check function */
  _get_priv_key,             /* find function */
  _close_connection,      /* close function */
  _tidy_cache,                /* tidy function */
  NULL,                          /* no quoting function */
  NULL                           /* no version function */
};
/* Какой селектор указывать в подписи */
static lookup_info _lookup_info2 = {
  US"dkim_selector",        /* lookup name */
  …
}; 
/* Какой домен указывать в подписи */
static lookup_info _lookup_info3 = {
  US"dkim_domain",        /* lookup name */
  …
};

static lookup_info *_lookup_list[] = { &_lookup_info1, &_lookup_info2, &_lookup_info3 };
lookup_module_info dkim_lookup_module_info = { LOOKUP_MODULE_INFO_MAGIC, _lookup_list, 3 };


Коллбэк-функции в структурах имеют четкий интерфейс и предназначение. Подробности реализации этих функций выходят за рамки статьи. Замечу только, что документации и примеров хватает за глаза, чтобы во всем этом разобраться.

После реализации внутренностей модуля остается его зарегистрировать. Заходим в файл src/drtables.c и добавляем описание модуля (куда конкретно вставлять строки, понятно из контекста — по аналогии со стандартным кодом):

extern lookup_module_info dkim_lookup_module_i
void init_lookup_list(void)
{
…
  addlookupmodule(NULL, &dkim_lookup_module_info);
...
}


Вот как выглядит использование модуля в конфигурации exim’а:

begin transports
remote_smtp:
  driver = smtp
  dkim_domain = ${lookup dkim_domain{$sender_address_domain}{$value}{DKIM_DEFAULT_DOMAIN}}
  dkim_selector = ${lookup dkim_selector{$sender_address_domain}{$value}{DKIM_DEFAULT_SELECTOR}}
  dkim_private_key = ${lookup dkim_privkey{$sender_address_domain}{$value}{DKIM_DEFAULT_KEY}}


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

Схема работы следующая: администратор домена через админку добавляет существующий или генерирует новый секретный и публичный DKIM-ключ. Админка сохраняет их в хранилище ключей. При каждой отправке письма от имени бизнес-домена exim запрашивает у базы данных его секретный ключ. Если ключа нет, то для подписи используется дефолтный ключ.

Для связи с БД используется наш стандартный компонент Капрон, о котором мы уже рассказывали ранее в другой статье.

Как мне настроить DKIM?

Если вы уже пользуетесь «Mail.Ru для бизнеса», то настроить собственную DKIM-подпись очень просто:



  1. Перейдите на страницу biz.mail.ru с авторизацией ящика администратора домена.
  2. Выберите подключенный домен, для которого необходимо настроить DKIM-подпись.
  3. Перейдите в раздел «Состояние сервера» и проверьте, правильно ли настроена MX-запись. Там же после успешной проверки MX-записи появится значение TXT-записи, которое необходимо установить в DNS-редакторе.
  4. Скопируйте значение TXT-записи и установите в DNS-редакторе вашего домена.
  5. Подождите несколько часов после установки записи, чтобы информация распространилась по всем DNS-серверам.
  6. Если запись настроена верно и прошла все наши проверки, мы отправим вам письмо об успешной настройке и начнем подписывать все ваши письма правильной DKIM-подписью.

Если у вас остались вопросы по поводу настройки и использования DKIM-подписи, оставляйте их в комментариях.
Автор: @nikiasi

Комментарии (10)

  • +3
    Хорошо, что у крупных провайдеров появляется SPF, DKIM. Теперь можно и на менее крупных серверах радоваться, что спам, традиционно разлетавшийся через smtp mail.ru, можно будет как-то разделять.

    Правда, после «картины маслом», когда один оз российских банков неверно настроил SPF-проверку, и тупо не принимал письма с «разрешенных» адресов (а ИТ банков, как обычно, тратл-тикеты принимает слабо, разобраться обязанности за собой не чувствует — в общем, разговоры ни к чему не привели тогда, и пришлось свою SPF-запись убирать (!) из ДНС, чтобы обойти эту их логическую ловушку), я стал еще мечтать не только о технологии заявить, что «мое письмо — хорошее» (хотя это неверно, это лишь заявление, что письмо ушло правильно, через нужные сервера), но и технологии надавать по рукам тем, кто письма ждет, но письма отбивает.
  • +1
    Я не очень понял, вы по $sender_address_domain, т.е по RFC5321.mailfrom, подписываете сообщение? А что если пользователь в From: укажет чужой домен? Ну оно понятно что по DMARC такое письмо будет отброшено, но зачем это делать когда DMARC'а (не с none) еще толком ни у кого нет? Да и вообще отслеживать такое сложнее, чем просто неподписанные письма.

    А в DKIM_DEFAULT_DOMAIN у вас mail.ru?
    • +1
      Сообщение подписывается по домену залогиненного пользователя, и только для письма, сгенерированного пользователем. Всякие пересылки, автоответы, форвардинг не подписываются. Если обнаружите обратное — пишите, исправим, это баг.

      Дефолтным доменом для дким-подписи является mail.ru, вы совершенно правы.
      В будущем для биз-доменов сделаем дефолтным какой-нибудь отличный от mail.ru домен.
  • 0
    Не удержусь. Поплачусь и тут. Мало ли SMM поможет или ускорит.

    Ваш postmaster с Вашем же «для бизнеса» как подружить? Ругается на DKIM, который есть, но привязан к mail.ru.
    Возможно как раз по этому:
    В будущем для биз-доменов сделаем дефолтным какой-нибудь отличный от mail.ru домен.
    • 0
      Во-первых, необходимо сгенерировать для своего биз-домена собственный DKIM-ключ (как это сделать, написано в статье). Без этого биз-домен с постмастером не подружить.

      Ну а во-вторых, еще необходима доработка на нашей стороне. Которую мы как раз уже сделали и в течение месяца постараемся выложить.
  • +1
    Во-первых, необходимо сгенерировать для своего биз-домена собственный DKIM-ключ (как это сделать, написано в статье). Без этого биз-домен с постмастером не подружить.

    DKIM, который есть

    и уже несколько недель как.
    в течение месяца постараемся выложить

    Так вот сколько равняется «скоро» :)
    Более конкретный срок радует
  • 0
    Ура. 27.08 заработал postmaster… Почти месяц (на самом деле больше 2ух) :)
  • 0
    А не могли бы вы привести пример записи TXT для DNS, содержащей SPF и DKIM? С SPF я справился, но как использовать вместе пока не понял. Буду признателен за пример. Почта и DNS не у вас.
  • 0
    А что делать если регистратор не поддерживает поддомены для TXT записей. Тоесть указать:

    Имя поддомена: mailru._domainkey
    Тип записи: TXT
    Данные: v=DKIM1; k=rsa; p=BlahBlah

    Тоесть я не могу указать «Имя поддомена: mailru._domainkey» — некуда.
    • +1
      Перенесите DNS-записи куда-нибудь, где поддерживается. В яндекс, например.

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.

Самое читаемое Разработка