Настройка DKIM на Postfix упирается в установку дополнительного компонента – OpenDKIM, а со стороны Postfix необходимо добавить лишь несколько строчек. Помимо этого, вам надо будет также добавить DNS-запись у вашего регистратора (ну или на вашем DNS-сервере, если зона делегирована вам).
Теперь обо всем подробнее.
Если вам интересна тематика почтовых серверов, рекомендую обратиться к соответствующей рубрике на моем блоге – Mail Servers.
Содержание
Настройка DKIM на Postfix
Если пока вы чувствуете себя неуверенно с DKIM, рекомендую прочитать статью Технология DKIM для почтового сервера.
В качестве тестового домена будет использоваться bq-srv.ru.
Установка
С установкой на Debian все просто:
1 2 |
apt-get install -y opendkim \ opendkim-tools |
Переходим к настройке.
Ключи
Начинать настройку OpenDKIM будет логичнее всего с генерации пары ключей – закрытого и открытого. Сделать это можно локально на сервере с помощью утилиты opendkim-genkey, но для начала создадим отдельный каталог с необходимыми правами и выставим нужного владельца:
1 |
mkdir -m 750 /etc/opendkim && chown opendkim:opendkim /etc/opendkim |
А теперь создаем ключи:
1 2 3 |
opendkim-genkey -D /etc/opendkim \ --domain=$(postconf -h mydomain) \ --selector=mail |
После выполнения команды будут созданы два файла – mail.private и mail.txt. Вы можете посмотреть их содержимое, если интересно. Один из этих файлов нам понадобится уже в следующей главе.
Выставим нужные права на файл закрытого ключа:
1 2 |
chown opendkim:opendkim /etc/opendkim/mail.private chmod 600 /etc/opendkim/mail.private |
Можно создавать записи.
Записи DNS
Чтобы не тратить время впустую, ожидая распространения DNS-записей, разумно добавить DKIM-запись уже сейчас, а потом спокойно заниматься настройкой. Напомню, что потребуется создать запись TXT. Её вы можете найти в файле /etc/opendkim/mail.txt и она уже имеет нужный вид:
1 2 3 |
mail._domainkey IN TXT ( "v=DKIM1; h=sha256; k=rsa; " "p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwY3QT9H4zJk3aLfMcXkyMG7qLdKA75vVAmA+Trz5t3ulE9H9MFa8xY2dHjDHjJECRV4ZR2MwNN1kmbsS832qQ9Owp7Zu1g1Fn+8xr15u0vzOR3tv1Jm8LXLf16HerSCGz84Ky25CkY+Gkzif0fmk9WSJPMBcTCYEnap+vd8k9IhENPSsfaDeoUCuWT1Ai53YgbECImatIrKz5P" "8b+5hsdddsgMviphMsJQ5NupYioFmwMT4RlEO9zbRjOrXwuEi5O0cpXilHpLIypiJUv1Up/DFQThwhbwDL++cOmnGnbWAjbTdfop1rW9Jk7dhl7vEzX0BSXwFg1yI9N1Amc2a5HwIDAQAB" ) ; ----- DKIM key mail for bq-srv.ru |
Переходим к настройке.
Настройка OpenDKIM
Основные настройки OpenDKIM находятся в файле /etc/opendkim.conf. Оставим его оригинал в качестве бэкапа, а на его месте создадим новый пустой файл:
1 |
mv /etc/opendkim.conf{,.backup} && > /etc/opendkim.conf |
Открываем его для редактирования и вставляем содержимое:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
AlwaysAddARHeader Yes SubDomains Yes RemoveARAll Yes RemoveOldSignatures Yes SendReports Yes Canonicalization relaxed/relaxed Mode sv UserID opendkim:opendkim Syslog Yes SyslogSuccess Yes LogWhy Yes KeyTable /etc/opendkim/KeyTable SigningTable refile:/etc/opendkim/SigningTable ExternalIgnoreList refile:/etc/opendkim/TrustedHosts InternalHosts refile:/etc/opendkim/TrustedHosts Nameservers 8.26.56.26,8.20.247.20 PidFile /var/run/opendkim/opendkim.pid Socket inet:10021@localhost ReportAddress "DKIM Error Postmaster" <postmaster@bq-srv.ru> |
Традиционно небольшое описание 2 каждого параметра ниже.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 |
## AlwaysAddARHeader { yes | no } ## default "no" ## ## Add an "Authentication-Results:" header even to unsigned messages ## from domains with no "signs all" policy. The reported DKIM result ## will be "none" in such cases. Normally unsigned mail from non-strict ## domains does not cause the results header to be added. AlwaysAddARHeader Yes ## SubDomains { yes | no } ## default "no" ## ## Sign for subdomains as well? SubDomains Yes ## RemoveARAll { yes | no } ## default "no" ## ## Remove all Authentication-Results: headers on all arriving mail. RemoveARAll Yes ## RemoveOldSignatures { yes | no } ## default "no" ## ## Remove old signatures on messages, if any, when generating a signature. RemoveOldSignatures Yes ## SendReports { yes | no } ## default "no" ## ## Specifies whether or not the filter should generate report mail back ## to senders when verification fails and an address for such a purpose ## is provided. See opendkim.conf(5) for details. SendReports Yes ## Canonicalization hdrcanon[/bodycanon] ## default "simple/simple" ## ## Select canonicalizations to use when signing. If the "bodycanon" is ## omitted, "simple" is used. Valid values for each are "simple" and ## "relaxed". Canonicalization relaxed/relaxed ## Mode [sv] ## default sv ## ## Indicates which mode(s) of operation should be provided. "s" means ## "sign", "v" means "verify". Mode sv ## Userid userid ## default (none) ## ## Change to user "userid" before starting normal operation? May include ## a group ID as well, separated from the userid by a colon. UserID opendkim:opendkim ## Syslog { yes | no } ## default "yes" ## ## Log informational and error activity to syslog? Syslog Yes ## SyslogSuccess { yes | no } ## default "no" ## ## Log success activity to syslog? SyslogSuccess Yes ## LogWhy { yes | no } ## default "no" ## ## If logging is enabled (see Syslog below), issues very detailed logging ## about the logic behind the filter's decision to either sign a message ## or verify it. The logic behind the decision is non-trivial and can be ## confusing to administrators not familiar with its operation. A ## description of how the decision is made can be found in the OPERATIONS ## section of the opendkim(8) man page. This causes a large increase ## in the amount of log data generated for each message, so it should be ## limited to debugging use and not enabled for general operation. LogWhy Yes ## KeyTable dataset ## default (none) ## ## Defines a table that will be queried to convert key names to ## sets of data of the form (signing domain, signing selector, private key). ## The private key can either contain a PEM-formatted private key, ## a base64-encoded DER format private key, or a path to a file containing ## one of those. KeyTable /etc/opendkim/KeyTable ## SigningTable dataset ## default (none) ## ## Defines a dataset that will be queried for the message sender's address ## to determine which private key(s) (if any) should be used to sign the ## message. The sender is determined from the value of the sender ## header fields as described with SenderHeaders above. The key for this ## lookup should be an address or address pattern that matches senders; ## see the opendkim.conf(5) man page for more information. The value ## of the lookup should return the name of a key found in the KeyTable ## that should be used to sign the message. If MultipleSignatures ## is set, all possible lookup keys will be attempted which may result ## in multiple signatures being applied. SigningTable refile:/etc/opendkim/SigningTable ## ExternalIgnoreList filename ## ## Names a file from which a list of externally-trusted hosts is read. ## These are hosts which are allowed to send mail through you for signing. ## Automatically contains 127.0.0.1. See man page for file format. ExternalIgnoreList refile:/etc/opendkim/TrustedHosts ## InternalHosts dataset ## default "127.0.0.1" ## ## Names a file from which a list of internal hosts is read. These are ## hosts from which mail should be signed rather than verified. ## Automatically contains 127.0.0.1. InternalHosts refile:/etc/opendkim/TrustedHosts ## Nameservers addr1[,addr2[,...]] ## default (none) ## ## Provides a comma-separated list of IP addresses that are to be used when ## doing DNS queries to retrieve DKIM keys, VBR records, etc. ## These override any local defaults built in to the resolver in use, which ## may be defined in /etc/resolv.conf or hard-coded into the software. Nameservers 8.26.56.26, 8.20.247.20 ## PidFile filename ## default (none) ## ## Name of the file where the filter should write its pid before beginning ## normal operations. PidFile /var/run/opendkim/opendkim.pid ## Socket socketspec ## ## Names the socket where this filter should listen for milter connections ## from the MTA. Required. Should be in one of these forms: ## ## inet:port@address to listen on a specific interface ## inet:port to listen on all interfaces ## local:/path/to/socket to listen on a UNIX domain socket Socket inet:10021@localhost ## ReportAddress addr ## default (executing user)@(hostname) ## ## Specifies the sending address to be used on From: headers of outgoing ## failure reports. By default, the e-mail address of the user executing ## the filter is used. ReportAddress "DKIM Error Postmaster" <postmaster@bq-srv.ru> |
Каждая строка файла /etc/opendkim/KeyTable задает соответствие селектор – домен – закрытый ключ. Разумеется вы можете иметь сколько угодно доменов и селекторов:
1 |
mail._domainkey.bq-srv.ru bq-srv.ru:mail:/etc/opendkim/mail.private |
Соответствия отправителей и селектора определяет файл /etc/opendkim/SigningTable. По сути, второе значение каждой строки SigningTable соответствует первому значению файла KeyTable:
1 |
*@bq-srv.ru mail._domainkey.bq-srv.ru |
Файл /etc/opendkim/TrustedHosts используется для двух целей одновременно. Он определяет список внутренних (InternalHosts) и внешних (ExternalIgnoreList) хостов, с которых всю почту надо подписывать, а не проверять.
1 2 3 4 |
127.0.0.1 localhost 172.16.0.20 *.bq-srv.ru |
На стороне OpenDKIM настройка завершена, теперь необходимо научить Postfix отдавать письма на подпись.
Настройка Postfix
Чтобы Postfix после всех манипуляций подписывал сообщение, необходимо добавить всего три строки в конфиг /etc/postfix/main.cf:
1 2 3 |
milter_default_action = accept smtpd_milters = inet:localhost:10021 non_smtpd_milters = inet:localhost:10021 |
Напомню, что сам Postfix ничего не знает о DKIM и в процессе обработки сообщения лишь на время отправляет его OpenDKIM и, как только тот его подпишет, принимает его обратно и отсылает конечным получателям. В терминологии Postfix эта технология называется Milter (mail filter 3).
Добавьте проверку DKIM самой последней, но перед DMARC (если она имеется).
Проверка работы
А теперь отправим тестовое письмо и после этого проверим содержимое лог-файлов (по умолчанию /var/log/mail.log). Хочу напомнить, что моя лаба представляет из себя связку Exchange Server 2016 + релэй на Postfix, который я начал настраивать в статье Простейший relay на Postfix для Exchange Server. Итак, логи:
1 2 3 4 5 6 7 8 |
postfix/smtpd[35561]: connect from exch01.sc.local[172.16.0.20] postfix/smtpd[35561]: 016117F3F7: client=exch01.sc.local[172.16.0.20] postfix/cleanup[35566]: 016117F3F7: message-id=<4212dd5e05504b6b9b118743d8b6860e@bq-srv.ru> opendkim[32872]: 016117F3F7: DKIM-Signature field added (s=mail, d=bq-srv.ru) postfix/qmgr[35554]: 016117F3F7: from=<e.vasilev@bq-srv.ru>, size=14453, nrcpt=1 (queue active) postfix/smtpd[35561]: disconnect from exch01.sc.local[172.16.0.20] ehlo=2 starttls=1 mail=1 rcpt=1 data=1 quit=1 commands=7 postfix/smtp[35567]: 016117F3F7: to=<e.s.vasilyev@mail.ru>, relay=mxs.mail.ru[94.100.180.104]:25, delay=2.4, delays=0.09/0/0.05/2.2, dsn=2.0.0, status=sent (250 OK id=1fknJI-00071n-9W) postfix/qmgr[35554]: 016117F3F7: removed |
# tail -n 40 /var/log/mail.log
Идентификатор сообщения представляет из себя десятисимвольную запись (пример – 016117F3F7). Скопируйте его и выполните уже другую команду:
# grep -e ‘016117F3F7’ /var/log/mail.log
После этого вы получите все записи, связанные с обработкой сообщение, которому присвоен идентификатор 016117F3F7.
Видно, что письмо приходит с эксча, подписывается (DKIM-Signature field added), ставится в очередь на отправку и отправляется со статусом ОК. На принимающей стороне просматриваем заголовки сообщения и видим:
1 |
dkim=pass header.d=bq-srv.ru |
А также саму подпись:
1 2 3 4 5 6 7 8 9 |
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bq-srv.ru; s=mail; t=1533115247; bh=e6IZE49kmkJx8p6ujrQuU4DncHDsIuDx0vpJjbn+Azw=; h=From:To:Subject:Date:References:In-Reply-To; b=h+B10b3fSfDqkvhE4TBcmOXNggZkmkfGzA3yRoabesHCWmohF5OFPPh2GAq1QDHQs QFm3yVv1FtLA5KWBY7fr/wceds5FE3VXeU98bXgEzvG4e9rOZrHgUJ1FFv3tkIGrZ+ 3dpOsv0y8JVpawwy/A9KmQpgf//qggmCzt7jPCanGVeiQbZiIxSpRV59HFS+ADMl4O kVILB5RTE3bbaDQxBX3fbBVHli3a/8usU0Lf/xWDUOAZJSKuxeb/oGnE5Ww6QfHJOJ ATD1cNcgHjgvVkG04QVuGIwWN9n/WHUBBrjEEsmTqUzJwVsS0xkEusjC6ssU2v5S4A cBNSKoELPD9jQ== |
Релэй правильно подписывает отсылаемые сообщения, но надо удостовериться, что он не забывает проверять подписи у сообщений, которые приходят снаружи на внутренний сервер. Пробуем отправить сообщение с любого внешнего сервера и смотрим логи:
1 2 3 4 5 6 7 8 9 |
postfix/smtpd[99428]: B82D87F06E: client=f487.i.mail.ru[217.69.138.154] postfix/cleanup[99431]: B82D87F06E: message-id=<1538598858.628412344@f487.i.mail.ru> opendkim[99420]: B82D87F06E: f487.i.mail.ru [217.69.138.154] not internal opendkim[99420]: B82D87F06E: not authenticated opendkim[99420]: B82D87F06E: DKIM verification successful opendkim[99420]: B82D87F06E: s=mail2 d=mail.ru SSL postfix/qmgr[35554]: B82D87F06E: from=<e.s.vasilyev@mail.ru>, size=2964, nrcpt=1 (queue active) postfix/smtp[99433]: B82D87F06E: to=<e.vasilev@bq-srv.ru>, relay=exch01.sc.local[172.16.0.20]:25, delay=0.41, delays=0.23/0/0/0.17, dsn=2.6.0, status=sent (250 2.6.0 <1538598858.628412344@f487.i.mail.ru> [InternalId=77296526426123, Hostname=EXCH01.sc.local] 4748 bytes in 0.161, 28,667 KB/sec Queued mail for delivery) postfix/qmgr[35554]: B82D87F06E: removed |
Из логов видно, что сообщение получено, DKIM подпись проверена и является валидной, а далее сообщение направлено на конечный сервер EXCH01.
Настройка на этом завершена.