Postfix OpenDKIM

postfix_dkimDomainKeys Identified Mail (DKIM) — технология, направленная на борьбу с поддельными почтовыми сообщениями. Для почтового домена генерируется пара ключей, открытый и закрытый. Закрытым ключом подписываются исходящие сообщения. Открытый ключ добавляется на DNS сервер в виде TXT записи. Когда принимающий сервер находит в заголовке сообщения DKIM подпись, он выполняет DNS запрос для получения открытого ключа. С помощью открытого ключа сервер определяет валидность DKIM подписи и решает, что делать с письмом. В зависимости от результатов и политики проверки, письмо может быть принято, отброшено, либо отправлено в спам. Информация с результатами проверки добавляется в заголовок сообщения и в дальнейшем может быть использована анти спам фильтрами. Основное отличие DKIM проверки от описанной ранее SPF проверки заключается в том, что SPF работает с информацией, полученной из полей конверта сообщения, а DKIM с информацией, полученной  из заголовка сообщения.

message_structure

Все что перечислено до команды DATA, это поля конверта сообщения, с ними работает SPF. Все что находится после команды DATA, является заголовком сообщения, с этой информацией работает DKIM.

Для практической демонстрации будут использованы внутренние DNS с IP адресами 192.168.1.21 и 192.168.1.22. На них созданы зоны 4skill.loc и 4skill.ru.  Зону 4skill.loc будет обслуживать SMTP сервер mail.4skill.loc с IP адресом 192.168.1.35. Зону 4skill.ru будет обслуживать SMTP сервер mail.4skill.ru  с  IP адресом 192.168.1.36.

4sk-loc_and_4sk-ru

В качестве ОС для SMTP серверов будет использоваться Ubuntu Server 16.04. После установки Ubuntu Server 16.04, изменим имя сервера на mail

# hostnamectl set-hostname mail

Укажем полное и сокращенное имя сервера в файле hosts

# nano /etc/hosts

127.0.0.1       localhost
127.0.1.1       mail.4skill.loc  mail
. . .

Определим сетевые настройки

# nano /etc/network/interfaces
. . .
# The primary network interface
auto ens32
iface ens32 inet static
        address 192.168.1.35
        netmask 255.255.255.0
        gateway 192.168.1.1
        dns-nameservers 192.168.1.21 192.168.1.22
        dns-search 4skill.loc

Более подробно о настройке сети написано в статье Ubuntu Server настройка сети.

Для применения настроек выполним перезагрузку

# reboot

Обновим индексы пакетов

# apt update

Обновим систему

# apt upgrade

Более подробно об обновлении написано в статье Обновление Ubuntu Server.

Установим Postfix

# apt install postfix

Тип настройки почтового сервера оставляем без изменений и нажимаем «Ok».

postfix_setup

В поле системное почтовое имя указываем обслуживаемый домен 4skill.loc.

postfix_setup_domain_4skill.loc

Полная установка Postfix в связке с Dovecot описана в статье Postfix Dovecot LDAP.

По умолчанию Postfix не умеет подписывать и проверять сообщения с использованием технологии DKIM. Для обеспечения данной возможности, установим пакеты OpenDKIM и OpenDKIM-Tools. OpenDKIM-Tools используется для генерации ключей

# apt install opendkim opendkim-tools

Приведем конфигурационный файл OpenDKIM к следующему виду

# nano /etc/opendkim.conf

AutoRestart             yes
AutoRestartRate         10/1h

Canonicalization        relaxed/relaxed

ExternalIgnoreList      refile:/etc/opendkim/trusted_hosts
InternalHosts           refile:/etc/opendkim/trusted_hosts
KeyTable                refile:/etc/opendkim/key_table
SigningTable            refile:/etc/opendkim/signing_table
ExemptDomains           refile:/etc/opendkim/no_check_domains
PeerList                refile:/etc/opendkim/no_check_hosts

On-BadSignature         accept

ReportAddress           dkim.report@4skill.loc
SendReports             yes
RequestReports          yes

SignHeaders             From,To,Subject,Date,Message-ID

Syslog                  yes
SyslogSuccess           yes
#LogWhy                 yes

UMask                   002

Nameservers             192.168.1.21,192.168.1.22
  • AutoRestart — автоматический перезапуск сервиса в случае падения.
  • AutoRestartRate — допустимая частота падений сервиса. В данном случае не более 10 раз за 1 час.
  • Canonicalization — канонизация для заголовка/тела сообщения. Подробнее об это тут.
  • ExternalIgnoreList — список внешних хостов, которые могут производить пересылку почты от имени подписываемого домена без аутентификации.
  • InternalHosts — список внутренних хостов, чья исходящая почта не должна проверяться, но должна быть подписана.
  • KeyTable — список ключей, используемых для подписи.
  • SigningTable — список доменов, сопряженных с ключами из KeyTable.
  • ExemptDomains — список доменов, для которых не будет производиться проверка.
  • PeerList — список хостов, для которых не будет производиться проверка.
  • On-BadSignature — что делать с письмом в случае неудачной проверки. Возможны варианты:
    ∘ accept — пропустить(по умолчанию);
    ∘ discard — отбросить сообщение без уведомления;
    ∘ quarantine — поместить сообщение в спам;
    ∘ reject — отбросить сообщение;
    ∘ tempfail — выдать сообщение об ошибке.
  • ReportAddress — адрес, от имени которого будет происходить рассылка отчетов о неудачных проверках.
  • SendReports — включение рассылки отчетов о неудачных проверках.
  • RequestReports — включение в подпись тега r=y. Данный тег активирует запрос на  получение отчетов о неудачных проверках.
  • SignHeaders — набор полей заголовка сообщения, которые будут включены в создаваемую подпись.
  • Syslog — запись логов в syslog.
  • SyslogSuccess — включение в лог информации об успешных подписях и проверках.
  • LogWhy — включение более детального логирования.
  • UMask — маска прав для Socet файла.
  • Nameservers — список используемыех DNS.

Подробное описание всех параметров можно найти на странице opendkim.conf.

Параметр Nameservers не обязательно указывать. В данном примере он используются в демонстрационных целях, связанных с использованием локальных DNS. Дело в том, что любой запрос на получение открытого ключа от локальных DNS завершится ошибкой, сигнализирующей об отсутствии записи, содержащей открытый ключ

# opendkim-testkey -d 4skill.loc -s mail 
opendkim-testkey: 'mail._domainkey.4skill.loc' record not found

Это связано с тем, что OpenDKIM использует свой собственный список DNS, зашитый в код программы, а не тот, который указан в параметре dns-nameservers. Так как используемые OpenDKIM DNS являются внешними, они ничего не знают о записях, хранящихся на внутренних DNS. Чтобы заставить OpenDKIM использовать внутренние DNS, был определен параметр Nameservers, со списком локальных DNS.

Создадим каталог для хранения ключей

# mkdir -p /etc/opendkim/keys/4skill.loc

Добавим ключи для домена 4skill.loc

# opendkim-genkey -D /etc/opendkim/keys/4skill.loc -d 4skill.loc -s mail

Ключ -D определяет каталог для записи ключей. Ключ -d указывает название домена. Ключ -s указывает название селектора. Селектор может быть произвольным. Обычно селектор отражает название сервиса, дату создания ключа, или битность ключа. В данном случае это название сервиса.

Пользователь, от имени которого работает сервис OpenDKIM, должен иметь доступ к закрытому ключу

# chown opendkim /etc/opendkim/keys/4skill.loc/*.private

Открытый ключ находится в файле с расширением .txt

# cat /etc/opendkim/keys/4skill.loc/*.txt

mail._domainkey IN      TXT     ( "v=DKIM1; k=rsa; "
          "p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDMtyLiYLXF0ywByDzfnQmdI+OMBsr6dg0OfXnejQtKwwCKmxLdxdk7dXXca7ZaO10b35deSX2XQuCuKp0ZeVsRAQsEu4dAYrJ/5Km7Rh3V45uLv1w7ksky128u6oiqllL5iVg+MWWQYtbedO7hT/Rod+aXb7DV3NjNAIl53ZdPtQIDAQAB" )  ; ----- DKIM key mail for 4skill.loc

Добавим его в локальные DNS. Откроем оснастку «Диспетчер DNS», нажмем правой кнопкой мыши по DNS зоне, выберем «Другие новые записи…» в окне «Тип записи ресурса» выберем «Текст (TXT)» и нажмем «Создать запись…»

add_txt_spf

Укажем данные открытого ключа

add_dkim_4skill.loc

Выполним проверку

# opendkim-testkey -d 4skill.loc -s mail -vvv
opendkim-testkey: using default configfile /etc/opendkim.conf
opendkim-testkey: checking key 'mail._domainkey.4skill.loc'
opendkim-testkey: key not secure
opendkim-testkey: key OK

Создадим файл, определяющий от кого подписывать почту

# nano /etc/opendkim/trusted_hosts 

::1
127.0.0.1
192.168.1.10

В данном примере будет подписываться почта, сформированная на самом почтовом сервере, и пересылаемая от узла 192.168.1.10. Даже если явно не указывать ::1 или 127.0.0.1, почта сформированная почтовыми клиентами пользователей, прошедших аутентификацию на сервере будет подписана. Явное указание адреса петлевого интерфейса дает возможность подписания почты, сформированной утилитой telnet на почтовом сервере(# telnet localhost 25).

Создадим файл, определяющий список закрытых ключей

# nano /etc/opendkim/key_table

4skill.loc      %:mail:/etc/opendkim/keys/%/mail.private

В данном примере используется переменная «%». Она заменяется названием домена отправителя при создании подписи. Использование переменной возможно из-за добавления префикса refile: в начале пути к фалу key_table в opendkim.conf. Та же запись без использование префикса имеет вид

4skill.loc      4skill.loc:mail:/etc/opendkim/keys/4skill.loc/mail.private

Каждый ключ прописывается отдельной строкой и имеет формат

<название ключа>      <название домена>:<название селектора>:<путь к закрытому ключу>

Создадим файл, сопоставляющий закрытый ключ с именем домена

# nano /etc/opendkim/signing_table

*@4skill.loc      %

Без переменной запись выглядела бы так

*@4skill.loc      4skill.loc

Формат записи следующий

<название домена>      <название ключа из key_table>

Создадим файлы, определяющий список хостов и доменов, для которых не нужно производить проверку

# touch /etc/opendkim/no_check_hosts
# touch /etc/opendkim/no_check_domains

Формат заполнения данных файлов такой же как у trusted_hosts.

Укажем SOCKET для подключения к OpenDKIM

# nano /etc/default/opendkim

заменим строку

SOCKET="local:/var/run/opendkim/opendkim.sock"

на

SOCKET="local:/var/spool/postfix/var/run/opendkim/opendkim.sock"

Создадим каталог для SOCKETa

# mkdir -p /var/spool/postfix/var/run/opendkim/

Выставим права на созданный каталог

# chown opendkim:opendkim /var/spool/postfix/var/run/opendkim/

Чтобы Postfix мог подключаться к SOCKETу OpenDKIM, добавим пользователя postfix в группу opendkim

# gpasswd -a postfix opendkim

Укажем Postfix как подключаться к OpenDKIM. Для этого добавим к конец main.cf следующие строки

# nano /etc/postfix/main.cf
. . .
smtpd_milters = unix:/var/run/opendkim/opendkim.sock
non_smtpd_milters = $smtpd_milters

Для взаимодействия Postfix и OpenDKIM через сеть, нужно в /etc/default/opendkim закоментировать все строки и раскоментировать

SOCKET="inet:12345@localhost"

А в /etc/postfix/main.cf добавить

smtpd_milters = inet:localhost:12345
non_smtpd_milters = $smtpd_milters

Перезапустим OpenDKIM

# service opendkim restart

Перезапустим Postfix

# service postfix restart

Настройка сервера mail.4skill.ru производится по аналогии с mail.4skill.loc.

Зайдем на mail.4skil.loc и отправим сообщение используя telnet

# telnet localhost 25
Trying ::1...
Connected to localhost.
Escape character is '^]'.
220 mail.4skill.loc ESMTP Postfix (Ubuntu)
helo mail.4skill.loc
250 mail.4skill.loc
mail from: root@4skill.loc
250 2.1.0 Ok
rcpt to: root@4skill.ru
250 2.1.5 Ok
data
354 End data with .
From: root@4skill.loc
.
250 2.0.0 Ok: queued as 4E0B92035D
quit
221 2.0.0 Bye
Connection closed by foreign host.

На основании домена, извлекаемого из поля From, происходит подпись письма. Если поле From отсутствует, письмо не будет подписано.
Посмотрим на содержание отправленного письма на сервере mail.4skill.ru

# tail -n24 /var/mail/root

From root@4skill.loc  Tue Oct 24 12:33:51 2017
Return-Path: <root@4skill.loc>
X-Original-To: root@4skill.ru
Delivered-To: root@4skill.ru
Received: from mail.4skill.loc (mail.4skill.loc [192.168.1.35])
        by mail.4skill.ru (Postfix) with ESMTP id 867D521B32
        for <root@4skill.ru>; Tue, 24 Oct 2017 12:33:51 +0300 (MSK)
Authentication-Results: mail.4skill.ru;
        dkim=pass (1024-bit key; unprotected) header.d=4skill.loc header.i=@4skill.loc header.b=d2ji+6+Q;
        dkim-atps=neutral
Received: from mail.4skill.loc (localhost [IPv6:::1])
        by mail.4skill.loc (Postfix) with SMTP id 4E0B92035D
        for <root@4skill.ru>; Tue, 24 Oct 2017 12:33:31 +0300 (MSK)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=4skill.loc; s=mail;
        t=1508837631; r=y; bh=47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=;
        h=From:Message-Id:Date;
        b=d2ji+6+QGIKcGj1MN3AeNecbuPW2Fw7SWnnMvyhBhYuhYAhwcdTgjqD5VD1TddFjG
         RTkbfwc+jnQ7V0A2+63pr2l6p/NmNpB+wdEp45qu5GStma51XljBtQjT0lrmmTUuD4
         OnN+iw0eEhSSWuFKrAKc5YkUauZUZUmVfTHoBAmc=
From: root@4skill.loc
Message-Id: <20171024093338.4E0B92035D@mail.4skill.loc>
Date: Tue, 24 Oct 2017 12:33:31 +0300 (MSK)

Строка Authentication-Results является результатом проверки. Она добавляется к заголовку письма принимающим сервером. В данном случае письмо успешно прошло проверку, об этом свидетельствует статус dkim=pass. Строка DKIM-Signature являются началом DKIM подписи. Она была сформирована сервером источником. Данная DKIM подпись содержит в себе тег r=y. Он добавляется в подпись, если в opendkim.conf параметр RequestReports имеет значение yes. Это означает, что сервер отправитель запрашивает отчет, в случае неудачной проверки. Отчет направляется на адрес, указанный в TXT записи

_report._domainkey.<название домена>

Добавим данную запись для домена 4skill.loc

dkim_report_record

Первый тег ra=dkim.report содержит в себе адрес, на который нужно отсылать отчеты о неудачных проверках. В данном теге нужно указывать только первую часть адреса до символа @. Доменная часть добавляется автоматически. Второй тег не является обязательным и может иметь значение от 0 до 100 включительно. Он указывает какой процент отчетов должен быть отправлен. По умолчанию используется значение 100.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *