Недавно на Хабре уже была статья о том, как «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-подпись очень просто:
- Перейдите на страницу biz.mail.ru с авторизацией ящика администратора домена.
- Выберите подключенный домен, для которого необходимо настроить DKIM-подпись.
- Перейдите в раздел «Состояние сервера» и проверьте, правильно ли настроена MX-запись. Там же после успешной проверки MX-записи появится значение TXT-записи, которое необходимо установить в DNS-редакторе.
- Скопируйте значение TXT-записи и установите в DNS-редакторе вашего домена.
- Подождите несколько часов после установки записи, чтобы информация распространилась по всем DNS-серверам.
- Если запись настроена верно и прошла все наши проверки, мы отправим вам письмо об успешной настройке и начнем подписывать все ваши письма правильной DKIM-подписью.
Если у вас остались вопросы по поводу настройки и использования DKIM-подписи, оставляйте их в комментариях.
Автор: nikiasi