FreeBSD: DKIM подписание средствами Postfix и Amavisd-new

DKIM Цитата из журнала «Системный администратор»: «Несмотря на обилие различных технологий борьбы со СПАМом, последний до сих пор составляет львиную долю почтового трафика. В 2005 году на рассмотрение IETF в качестве стандарта аутентификации отправителя был предложен еще один стандарт DomainKeys Identified Mail (DKIM), разработчики которого предлагают свой способ решения этой задачи».

Постановка задачи

Технология DomainKeys Identified Mail (DKIM) предназначена для идентификации отправителя почтового сообщения с помощью цифровой подписи, связанной с именем соответствующего домена. DKIM была создана для более качественной классификации и идентификации легитимной электронной почты и широко используется крупнейшими компаниями, такими как, например, AOL, Cisco, EarthLink, Google, IBM, VeriSign, Yahoo. Последние версии Amavisd-new по умолчанию выполняют DKIM верификацию входящей корреспонденции и позволяют без каких-либо сложностей организовать DKIM подписание исходящей корреспонденции, которому и посвящена эта статья.

Исходные данные

Имеется сервер с FreeBSD, находящийся на входе подсети центрального офиса. На нем развернута почтовая система, имеющая примерно такую же подсистему защиты от СПАМа, как Почтовая система среднего офиса на базе Postfix. Для решения рассматриваемой задачи не требуется установка какого-либо программного обеспечения, однако, во избежание недоразумений следует отметить, что я использовал FreeBSD 7.2 и последние версии портов Postfix и Amavisd-new для нее. Все имена папок, файлов и пользователей соответствуют стандартным значениям, выбираемым по умолчанию при установке программного обеспечения из портов. Действия, описанные в статье, выполнялись под руководством документов amavisd-new documentation bits and pieces и RFC 4871 — DomainKeys Identified Mail (DKIM) Signatures.

Создание ключа DKIM и обновление файла зоны DNS

В связи с тем, что Amavisd-new хранит пару из открытого (публичного) и закрытого (приватного) ключей в одном PEM-файле, в этом разделе я буду использовать общий термин «ключ» и делать уточнение только в тех случаях, когда речь идет не о паре, а только об одном из ключей.
Для хранения ключей следует создать отдельную папку, которая по соображениям безопасности должна быть доступна только для чтения только пользователю vscan и группе vscan, от имени которых работает Amavisd-new:

mkdir /var/db/dkim
chown vscan:vscan /var/db/dkim
chmod 500 /var/db/dkim

Количество ключей, связанных с доменом, определяет владелец домена. В большинстве случаев для одного домена достаточно одного ключа, однако, в географически распределенных почтовых системах может потребоваться использование нескольких ключей. В любом случае для выбора необходимых ключей используются селекторы – префиксы имен ключей, которые могут содержать, например, имена подразделений, выполняющих подписание. Более подробная информация о селекторах имеется в разделе 3.1. Selectors документа RFC 4871. В этой статье рассмотрено использование одного ключа с селектором default для одного домена. Во избежание путаницы я рекомендую использовать для файлов, содержащих ключи, шаблонные имена, имеющие формат <имя домена>-<имя селектора>.key.pem.
С учетом сказанного для создания ключа домена company.com с селектором default необходимо выполнить команду:

amavisd genrsa /var/db/dkim/company-default.key.pem

По умолчанию команда amavisd genrsa генерирует 1024-битные ключи, однако, в комадной строке можно задать другую разрядность. Меня устроило значение по умолчанию, т.к. оно соответствует рекомендациям документации DKIM, призывающей использовать ключи длиной не менее 1024 бита (более короткие не достаточно устойчивы) и не более 2048 бит (более длинные могут не поместиться в DNS-пакет). Помните, что вычислительная мощность, требуемая для DKIM подписания почтовых сообщений, растет с увеличением длины ключей.
Для того, чтобы Amavisd-new мог использовать созданный ключ, нужно добавить в файл /usr/local/etc/amavisd.conf строку:

dkim_key('company.com', 'default', '/var/db/dkim/company-default.key.pem', g=>'*', h=>'sha256', k=>'rsa');

Первый аргумент определяет домен, для которого будет использоваться ключ; второй — селектор ключа; третий — имя файла, содержащего ключ; четвертый — шестой — дополнительные параметры ключа (степень детализации, хеш-алгоритм и тип ключа). Задание дополнительных параметров не является обязательной процедурой, однако, я решил последовать рекомендациям большинства руководств по настройке DKIM подписания и задал три дополнительных параметра, перечисленных выше. Более подробная информация о дополнительных параметрах ключей имеется в разделе 3.6. Key Management and Representation документа RFC 4871. Следует отметить, что Amavisd-new не проверяет синтаксис значений дополнительных параметров ключей (за исключением синтаксиса значения дополнительного параметра 'n').
После создания ключа и внесения изменений в файл /usr/local/etc/amavisd.conf следует перезапустить Amavisd-new командой amavisd reload и запросить открытый ключ командой amavisd showkeys. Если Вы не допустили ошибок, будет выведено примерно такое сообщение:

; key#1, domain company.com, /var/db/dkim/company-default.key.pem
default._domainkey.company.com. 3600 TXT (
  "v=DKIM1; g=*; h=sha256; k=rsa; p="
  "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDMknsDmaJsMaXUkc/GA4tQiFuX"
  "NhUBrIObubRxy96Mr1qSDhsYCohDokb1lw/kBrA15qx8rmqND58pFbyRmzkf8EqQ"
  "w7wclacm5YR6rm39s4C1VC5o+vfRuv8dzGEC+tHg9kK673Vb/PU8rboNnqmbhISO"
  "Wl/W0WUzM0lGaJ6ddQIDAQAB")

Первая строка данного сообщения является комментарием и содержит номер ключа, присвоенный Amavisd-new, имя домена и имя файла, содержащего ключ. Остальные строки являются определением публичного ключа, которое нужно без изменений добавить в файл зоны DNS. Также в этом файле необходимо увеличить значение, содержащееся в поле serial SOA записи. Через несколько часов после обновления файла зоны DNS следует выполнить команду amavisd testkeys. Если Вы не допустили ошибок будет выведено примерно такое сообщение:

TESTING#1: default._domainkey.company.com     => pass

На этом создание ключей DKIM заканчивается, можно перейти к добавлению второго пути обработки сообщений в Amavisd-new и Postfix.

Второй путь обработки сообщений

Напомню, что в вышеназванной почтовой системе взаимодействие Postfix и Amavisd-new выполнялось по следующей схеме: Amavisd-new прослушивал адрес localhost:10024, на который Postfix пересылал сообщения для проверки на вирусы и СПАМ, а Postfix прослушивал адрес localhost:10025, на который Amavisd-new пересылал проверенные сообщения. Назовем этот путь обработки сообщений первым. Теперь он будет применяться только для обработки входящей корреспонденции. Для обеспечения максимальной универсальности почтовой системы в конфигурацию Postfix и Amavisd-new будет добавлен второй путь обработки сообщений: Amavisd-new будет прослушивать дополнительный адрес localhost:10026, на который Postfix будет пересылать сообщения, отправленные абонентами, находящимися в доверенных сетях или прошедшими SASL-аутентификацию, для DKIM подписания, подписанные сообщения будут отправляться на адрес localhost:10025. Этот путь обработки сообщений будет применяться для всей исходящей корреспонденции.

Второй путь обработки сообщений в Amavisd-new

Обработка сообщений по первому пути определена политикой по умолчанию, по второму — будет задана политикой ORIGINATING. Для того, чтобы Amavisd-new загружал код, выполняющий DKIM подписание, одновременно прослушивал адреса localhost:10024 и localhost:10026, проверял сообщения, полученные на адрес localhost:10024, на вирусы и СПАМ, выполнял DKIM подписание сообщений, полученных на адрес localhost:10026, согласно банку политики ORIGINATING, а также отправлял обработанные сообщения на адрес localhost:10025, нужно внести следующие изменения в файл /usr/local/etc/amavisd.conf:

$enable_dkim_signing = 1;
$inet_socket_port = [10024,10026];
$forward_method = 'smtp:[127.0.0.1]:10025';
$notify_method = $forward_method;
$interface_policy{'10026'} = 'ORIGINATING';
$policy_bank{'ORIGINATING'} = {
    originating => 1,
    smtpd_discard_ehlo_keywords => ['8BITMIME'],
    os_fingerprint_method => undef,
    bypass_banned_checks_maps => [1],
    bypass_header_checks_maps => [1],
    bypass_spam_checks_maps   => [1],
    virus_admin_maps => ["virusalert\@$mydomain"],
};

Предложенный вариант политики ORIGINATING обеспечивает подписание сообщений, заставляет Postfix преобразовывать сообщения в формат 7-bit quoted-printable для сохранения целостности сигнатур DKIM при прохождении через различные почтовые серверы, находящиеся на пути к получателям, проверяет сообщения только на вирусы и оповещает администратора только об обнаружении вирусов. Преобразование в формат 7-bit quoted-printable может нарушить работу шифрования S/MIME и PGP. Для решения данной проблемы необходимо настроить почтовые клиенты так, чтобы они переводили сообщения в формат 7-bit quoted-printable до выполнения преобразований S/MIME и PGP.
На этом добавление второго пути обработки сообщений в Amavisd-new заканчивается (не забудьте выполнить команду amavisd reload).

Второй путь обработки сообщений в Postfix

Напоминаю, что в дорабатываемой почтовой системе для пересылки сообщений от Postfix к Amavisd-new используется транспорт smtp-amavis, а для приема обработанных Amavisd-new сообщений Postfix прослушивается дополнительный адрес 127.0.0.1:10025. Такое поведение Postfix обеспечено добавлением следующей строки в файл /usr/local/etc/postfix/main.cf:

content_filter=smtp-amavis:[127.0.0.1]:10024

а также следующих строк в файл /usr/local/etc/postfix/master.cf:

smtp-amavis unix -      -       n       -       4       smtp
    -o smtp_data_done_timeout=1200
    -o smtp_send_xforward_command=yes
    -o disable_dns_lookups=yes
127.0.0.1:10025 inet n  -       n       -       -       smtpd
    -o content_filter=
    -o local_recipient_maps=
    -o relay_recipient_maps=
    -o smtpd_restriction_classes=
    -o smtpd_client_restrictions=
    -o smtpd_helo_restrictions=
    -o smtpd_sender_restrictions=
    -o smtpd_recipient_restrictions=permit_mynetworks,reject
    -o mynetworks=127.0.0.0/8
    -o strict_rfc821_envelopes=yes
    -o smtpd_error_sleep_time=0
    -o smtpd_soft_error_limit=1001
    -o smtpd_hard_error_limit=1000
    -o smtpd_client_connection_count_limit=0
    -o smtpd_client_connection_rate_limit=0
    -o receive_override_options=no_header_body_checks,no_unknown_recipient_checks,no_milters

В процессе добавления второго пути обработки сообщений Вам не придется вносить какие-либо изменения в перечисленные строки.
Для того, чтобы Postfix без лишних проверок пересылал сообщения, которые были отправлены из доверенных сетей, на адрес localhost:10026 (для DKIM подписания), в файле /usr/local/etc/postfix/main.cf необходимо добавить в начало списка smtpd_recipient_restrictions (в моем случае он содержит все ограничения доступа к почтовому серверу) еще одно ограничение:

smtpd_recipient_restrictions =
  check_client_access cidr:/usr/local/etc/postfix/originating.cidr,
  все остальные ограничения

Файл originating.cidr имеет формат, описанный в cidr_table(5), каждая строка этого файла соответствует одной из доверенных сетей:

127.0.0.0/8     FILTER smtp:[127.0.0.1]:10026
192.168.0.0/24  FILTER smtp:[127.0.0.1]:10026
192.168.1.0/24  FILTER smtp:[127.0.0.1]:10026
192.168.2.0/24  FILTER smtp:[127.0.0.1]:10026

Для того, чтобы Postfix без лишних проверок пересылал сообщения, отправленные абонентами, прошедшими SASL-аутентификацию, на адрес localhost:10026 (для DKIM подписания), в файле /usr/local/etc/postfix/master.cf необходимо изменить определение сервиса smtps:

smtps     inet  n       -       n       -       -       smtpd
    -o smtpd_tls_wrappermode=yes
    -o smtpd_sasl_auth_enable=yes
    -o smtpd_client_restrictions=permit_sasl_authenticated,reject
    -o content_filter=smtp-amavis:[127.0.0.1]:10026

На этом добавление второго пути обработки сообщений в Postfix заканчивается (не забудьте выполнить команду postfix reload).

Тестирование и отладка DKIM подписания

Для проверки работоспособности DKIM подписания нужно отправить почтовое сообщение на один из адресов, содержащихся в списке Reflectors (я использовал "autorespond+dkim(at)dk(dot)elandsys(dot)com"). Через несколько минут Вы получите ответ с результатами проверки:

This is an automatic response.  Replies to this message will not generate
an automatic response.
Do not reply to this message except for reporting a problem.

The results are as follows:

DKIM Signature validation: pass (1024-bit key)
DKIM Author Domain Signing Practices: no DNS record for _adsp._domainkey.company.com
Information about DKIM is available at http://www.elandsys.com/resources/mail/dkim/opendkim.html
Information about ADSP is available at http://www.elandsys.com/resources/sendmail/dkim.html

Information about dkim-milter is available at http://www.elandsys.com/resources/sendmail/dkim.html

Information about DomainKeys is available at http://www.elandsys.com/resources/sendmail/domainkeys.html

Original message:
...

Строка "DKIM Signature validation: pass (1024-bit key)" подтверждает корректную работу DKIM подписания. Не обращайте внимение на строку "DKIM Author Domain Signing Practices: no DNS record for _adsp._domainkey.company.com", мы определим ADSP чуть позже.
Если проверка по тем или иным причинам завершилась неудачно, Вам придется повысить детальность логов Amavisd-new (определяется параметром $log_level в файле /usr/local/etc/amavisd.conf) до значения 2, перезапустить Amavisd-new командой amavisd reload, а затем отправлять сообщения и внимательно анализировать содержимое файла /var/log/maillog до выявления и устранения ошибок.

Определение практики использования DKIM в домене

Последним этапом настройки DKIM подписания является определение DKIM Author Domain Signing Practices (DKIM ADSP) — практики (в некоторых источниках — политики) использования DKIM в домене. Существует три варианта DKIM ADSP: unknown — отправка неподписанных сообщений разрешена (значение по умолчанию), all — отправка неподписанных сообщений запрещена, discardable — все неподписанные сообщения должны быть заблокированы на стороне получателя. Любые другие значения DKIM ADSP приравниваются к unknown. Более подробная информация о DKIM ADSP имеется в документе DomainKeys Identified Mail (DKIM) Author Domain Signing Practices (ADSP). Вы можете самостоятельно выбрать наиболее приемлемый вариант DKIM ADSP. (я использую вариант all). ADSP задается в том же файле зоны DNS, что и публичный ключ DKIM, с помощью записи, имеющей следующий формат:

_adsp._domainkey.company.com TXT "dkim=all"

Добавьте указанную запись в файл зоны DNS, и через некоторое время протестируйте DKIM подписание, как делали это выше. На этот раз Вы должны увидеть в ответе строку "DKIM Author Domain Signing Practices: "dkim=all" вместо строки "DKIM Author Domain Signing Practices: no DNS record for _adsp._domainkey.company.com".

Заключение

Я надеюсь, что не забыл ничего важного, и приведенной информации будет достаточно для корректной настройки и последующей отладки DKIM подписания почтовых сообщений средствами Postfix (любого универсального MTA) и Amavisd-new, на базе которых построено огромное количество почтовых систем, работающих в среде операционных систем семейства Linux/Unix. Вы можете поучаствовать в обсуждении этой статьи на форуме OpenNET, мне интересны любые замечания, комментарии и рекомендации.

Понравилась статья?

 Подпишитесь на RSS или почтовую рассылку

 Присоединиться в Twitter, Facebook или Google+

 Поделитесь ссылкой в социальной сети или блоге

6 комментариев к «FreeBSD: DKIM подписание средствами Postfix и Amavisd-new»

  1. Спасибо огромное, Сергей!
    Пользовался твоими статьями многократно, и никогда ни единого разрыва 🙂

  2. Спасибо за статью! Очень пригодилась!

    У меня в ходе настройки выяснилось одно важное дополнение, если можно:

    Если в Postfix в main.cf с помощью «smtp_header_checks = » и/или «mime_header_checks = » настроен фильтр заголовков сообщений,
    вырезающий из них «ненужные поля», чтобы на принимающей стороне не было видно в шапке ваших писем «внутреннюю кухню»:
    (с каких внутренних IP письмо отправлялось, каким сервером, какой программой и т.д.)
    -------------------------------------------------------
    /^Received:.*with ESMTPSA/ IGNORE
    /^X-Originating-IP:/ IGNORE
    /^X-Mailer:/ IGNORE
    /^Mime-Version:/ IGNORE
    -------------------------------------------------------

    То строка фильтра:
    /^Mime-Version:/ IGNORE

    ломает нам проверку DKIM-подписи ПРИНИМАЕМЫХ сообщений!

    Она режет соотв.строчку в заголовке у принимаемых писем, что влечет за собой FAIL проверку DKIM подписи отправителя.

    Например, при приеме почты с гугла, его DKIM-подпись проверку не проходит:
    dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b=h6UkTpnX;

    Если же из фильтра заголовков выкинуть строку:
    /^Mime-Version:/ IGNORE

    то проверка DKIM-подписи начинает работать корректно:
    dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b=VLS4YuBo;

    Отсутствие этой вредной строки на вычищение информации о «внутренней кухне» отправителя особо не влияет.
    Важная приватная информация будет по-прежнему вырезаться из заголовков отправляемых писем.

    • Спасибо за статью!

      На здоровье!

      У меня в ходе настройки выяснилось одно важное дополнение, если можно…

      Не можно, а нужно! Спасибо за полезное дополнение!

  3. И еще, если можно замечание к статье. Скорее даже не замечание, а рекомендация для не особо умелых админов типа меня.
    Полдня провел в попытках добиться от Amavis’a добавлять в заголовки ПРИНИМАЕМЫХ извне писем строчку «Authentication-Results: хххххх», но так и не смог победить проблему. Подписывать ИСХОДЯЩИЕ наружу письма Amavis умеет прекрасно! И на принимающей стороне подписи проходят все проверки, но вот когда дело доходит до отображения результатов проверки DKIM у ПРИНИМАЕМЫХ писем — облом. Не показывает Amavis результат верификации в заголовке письма, хоть ты тресни. Причем, что интересно, строчка «Received-SPF: Pass (sender SPF authorized) identity=…» — есть, а «Authentication-Results: …» — нету. Т.е. результат верификации SPF Amavis почему-то умеет вставлять в заголовки принимаемых писем, а результат проверки DKIM — нет.

    В общем, пришлось ставить «Opendkim» и настраивать его только на проверку подписей (переменная «Mode» в /etc/opendkim.conf должна быть = "v")
    После этого в заголовки принимаемых писем сразу же стала добавляться требуемая строчка (отправил тестовое письмо с гугла себе на Postfix):
    ...
    Authentication-Results: mail.robonuka.com;
    dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b=L/4Fki+P;
    dkim-atps=neutral
    ...

    Если все таки можно как-то заставить Amavis не только проверять DKIM-подпись, но еще и добавлять строчку о результатах проверки в заголовок принимаемого письма, то я бы очень был Вам благодарен, если бы вы добавили в свою статью совет, как это сделать?

Оставить комментарий