Вокруг технологии DKIM ходит множество мифов, в основном сконцентрированных вокруг чудодейственной способности избавления от спама, но на деле стандарт не преследует этой цели напрямую, он лишь позволяет подтвердить подлинность отправителя и факт отсутствия изменений/подделок в сообщении со стороны промежуточных узлов.
Если вам интересна тематика почтовых серверов, рекомендую обратиться к соответствующей рубрике на моем блоге – Mail Servers.
Содержание
Технология DKIM для почтового сервера
Эта статья лишь кратко освещает некоторые нюансы технологии DKIM. Если вы хотите получить более подробную информацию из первоисточника, обратитесь к RFC 6376.
Рекомендую к прочтению перечень статей ниже:
Начинаем разбираться с DKIM.
Введение
DKIM – DomainKeys Identified Mail – технология, позволяющая обнаружить подделку сообщений и, таким образом, защититься от спуфинга. Но обо всем по порядку.
Дело в том, что заголовки сообщений достаточно легко подделываются, а базовые технологии электронной почты не предоставляют никакого механизма проверки подлинности отправителя.
Именно этот пробел призвано устранить внедрение DKIM путем гарантии того, что тело письма и некоторые его критически важные заголовки не были изменены или подделаны третьей стороной.
А теперь подробнее о самих заголовках.
Заголовки сообщения
Они бывают двух типов – заголовки самого сообщения и заголовки конверта.
Заголовки сообщения устанавливает его автор (вернее программа, в которой он пишет письмо), например:
1 2 3 4 |
From: e.vasilev@bq-srv.ru To: "e.s.vasilyev@mail.ru" <e.s.vasilyev@mail.ru> Subject: test Date: Wed, 1 Aug 2018 09:20:46 +0000 |
С точки зрения передачи сообщения серверу-получателю эти заголовки не имеют никакого смысла и во время передачи не используются (как так, спросите вы? А вот…). Важны лишь заголовки MAIL FROM и RCPT TO (и другие), которые сервер-отправитель объявляет серверу-получателю во время SMTP-сессии, но для пользователя они скрыты. Эти заголовки называются заголовками конверта. Впоследствии, во время цикла передачи сообщения между серверами, информация внутри этих заголовков “замаскируется” в заголовках Received, которых обычно имеется по несколько штук в каждом сообщении (они показывают всю цепочку движения сообщения):
1 2 3 4 5 6 7 8 9 10 11 12 13 |
Received: from [x.x.x.x] (port=58870 helo=mail.bq-srv.ru) by mx208.i.mail.ru with esmtp (envelope-from <e.vasilev@bq-srv.ru>) id 1fknJI-00071n-9W for e.s.vasilyev@mail.ru; Wed, 01 Aug 2018 12:20:49 +0300 Received: from mail.bissquit.ru (exch01.sc.local [172.16.0.20]) by mail.bq-srv.ru (Postfix) with ESMTPS id 016117F3F7 for <e.s.vasilyev@mail.ru>; Wed, 1 Aug 2018 12:20:47 +0300 (MSK) Received: from EXCH01.sc.local (172.16.0.20) by EXCH01.sc.local (172.16.0.20) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P384) id 15.1.544.27; Wed, 1 Aug 2018 12:20:46 +0300 Received: from EXCH01.sc.local ([::1]) by EXCH01.sc.local ([::1]) with mapi id 15.01.0544.027; Wed, 1 Aug 2018 12:20:46 +0300 |
Более того, заголовок MAIL FROM (его другие название – Return-Path или Envelope From) может вообще содержать адрес, отличный от содержимого заголовка From. В некоторых случаях это не будет являться признаком недобросовестных отправителей (например когда отчет о недоставке сообщения нужно отправить на другой адрес 1 или когда используется переадресация).
Вот такая интересная ситуация. Неудивительно, что для устранения такого “беспорядка” понадобился отдельный стандарт – DKIM, о котором пришло время рассказать подробнее.
Базовые понятия
В основе DKIM лежит ассиметричный алгоритм шифрования RSA 2. Сообщения подписываются закрытым ключом, который хранится у отправляющего (подписывающего) сервера, а открытый публикуется в TXT-записи на серверах DNS. Для извлечения открытого ключа из публичной записи необходимо “собрать” доменное имя. Оно состоит из вашего домена, обязательной части технологии DKIM – _domainkey – и имени селектора:
Как только доменное имя получено, извлекается TXT-запись, например:
1 2 3 |
# dig -t TXT mail._domainkey.bq-srv.ru +short "v=DKIM1; h=sha256; k=rsa; " "p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwY3QT9H4zJk3aLfMcXkyMG7qLdKA75vVAmA+Trz5t3ulE9H9MFa8xY2dHjDHjJECRV4ZR2MwNN1kmbsS832qQ9Owp7Zu1g1Fn+8xr15u0vzOR3tv1Jm8LXLf16HerSCGz84Ky25CkY+Gkzif0fmk9WSJPMBcTCYEnap+vd8k9IhENPSsfaDeoUCuWT1Ai53YgbECImatIrKz5P" "8b+5hsdddsgMviphMsJQ5NupYioFmwMT4RlEO9zbRjOrXwuEi5O0cpXilHpLIypiJUv1Up/DFQThwhbwDL++cOmnGnbWAjbTdfop1rW9Jk7dhl7vEzX0BSXwFg1yI9N1Amc2a5HwIDAQAB" |
mail._domainkey IN TXT ( “v=DKIM1; h=sha256; k=rsa; ” “p=<first_part>” “<another_part>” ) ; —– DKIM key mail for bq-srv.ru
Если и при таком подходе возникают сложности, то у вас не остается вариантов, кроме как обратиться в техподдержку регистратора. Также, не забывая о длине ключей, стоит разрешить для ваших DNS-серверов доступ по порту 53 TCP.
Пример DKIM-подписи 4 из реального сообщения:
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== |
При беглом взгляде становится понятно, что она содержит не только саму подпись, но и несколько пар ключ=значение, которые используются как инструкции для проверки. Вот что они означают:
- v= – версия DKIM. Всегда имеет значение 1;
- a= – алгоритм, используемый для генерации подписи;
- c= – тип канонизации заголовка/тела сообщения. Перед подписью сообщение необходимо привести его к стандартному (канонизированному), чтобы не возникло проблем при проверке на принимающей стороне, ведь промежуточные серверы могут незначительно модифицировать сообщение. Это достаточно важный параметр, стоит обратить на него особое внимание;
- d= – домен, который будет просматриваться на предмет наличия публичного ключа;
- s= – селектор. Позволяет взять публичный ключ из нужной TXT-записи, если их вдруг несколько (а такое вполне может быть, если подписывающих серверов больше одного);
- t= – отметка времени создания подписи;
- bh= – хэш канонизированного тела сообщения;
- h= – подписанные поля заголовков (список заголовков может варьироваться. Наличие тех или иных заголовков в подписи может защитить вас от некоторых потенциальных уязвимостей DKIM);
- b= собственно, сама подпись.
Информация выше дана лишь для справки. Ключи подписи DKIM подробно описаны в RFC 4871, советую обратиться именно к этому документу для лучшего понимания. К тому же это не все заголовки, их бывает и больше.
Сколько селекторов надо для счастья
Исходя из анализа процесса извлечения нужной TXT-записи DKIM для домена, мы приходим к выводу, что селекторов может быть несколько. Это важная особенность архитектуры протокола, которая позволяет выдать каждому подписывающему серверу свой персональный ключ.
С точки зрения администрирования это обеспечивает следующие преимущества:
- Простота отзыва ключа при его компрометации – не нужно будет отзывать ключи со всех подписывающих серверов враз, а только с одного (тут и меньше даунтайм для пользователей, и меньше объем работ);
- Разграничение зон ответственности между админами, если вдруг разные релэи администрируют разные админы (это редкий случай, но гипотетически для больших компаний такое возможно, особенно если речь идет о разных почтовых сервисах – основных корпоративных и второстепенных – которые вынуждены отправлять с одного домена)
- Если кто-то у вас угнал закрытый ключ, будет сразу понятно какой сервер сломали или какой админ слил ключ;
Тем не менее, факты говорят о том, что даже очень крупные публичные сервисы используют один и тот же ключ как минимум на нескольких серверах одновременно:
1 2 3 4 5 6 |
Received: from f473.i.mail.ru (f473.i.mail.ru [217.69.138.140]) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=mail.ru; s=mail2; Received: from f168.i.mail.ru (f168.i.mail.ru [94.100.178.87]) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=mail.ru; s=mail2; |
Выше вы можете увидеть небольшой кусок логов получения письма. Обратите внимание: имена серверов и их адреса разные, а селектор используется один и тот же.
Дополнительные записи
Помимо DNS-записи с селектором существуют и другие. Одна из них – запись политики 5 DKIM, другая – _adsp-запись.
Первая (запись политики) используется для информирования принимающих серверов о том, должны ли все письма домена быть подписаны (o=-) или нет (o=~), а также имеет ряд дополнительных опций (например адрес для обратной связи). Запись может выглядеть вот так:
1 |
_domainkey IN TXT "o=~; r=postmaster@bq-srv.ru" |
Следующая запись – _adsp – на момент написания статьи вообще является устаревшей 6 7. Вывод: дополнительные записи DKIM на данный момент не актуальны, используйте DMARC.
Также не забывайте, что конечная цель DKIM – не заставить принимающие серверы сразу отклонять сообщения с битой подписью, а просто предоставить ещё один механизм удостоверения отправляющей стороны 8:
Thus, DKIM specifies that an assessing site is not to take a message that has a broken signature and treat it any differently than if the signature weren’t there.
Принимающая сторона должна принимать решение о блокировке сообщений на основе множества факторов и оценок (например статус проверки DKIM может быть fail, но статус DMARC – pass. Но это уже совсем другая история).
Внедрение DKIM
Несмотря на исключительную пользу стандарта, в большинстве случаев внедрить его возможно только путем установки дополнительных компонентов.
Exchange Server
Exchange на сегодняшний момент является самым распространенным корпоративным почтовым сервисом и насчитывает десятки лет истории. Несмотря на это, вот уже и в Exchange Server 2019 9 функционала DKIM не предвидится.
На мой взгляд, этому может быть лишь одно логичное объяснение – Microsoft сосредотачивается на разработке функционала самого приложения (интеграция с другими продуктами, развитие общей экосистемы, переход в облака), а реализацию дополнительного транспортного функционала отдает на откуп сторонним разработчикам. Не зря же они открыли возможность для каждого создать собственные транспортные агенты 12.
Postfix
Postfix всего лишь MTA (агент пересылки почты) и в его функционал DKIM также не включен, но зато он реализуется с помощью пакета OpenDKIM.
В одной из ближайших статей я планирую рассказать как настроить связку Postfix + OpenDKIM, а также как её использовать в качестве релэя для Exchange Server.
UPD 19.08.2018:
А вот и статья про настройку DKIM на Postfix: Настройка DKIM на Postfix.
Notes:
- Legitimate reasons SMTP “MAIL FROM:” will not match “From:” Header in DATA ↩
- Иллюстрация работы RSA на примере ↩
- How to Split DNS DKIM Records Properly ↩
- Structure of the DKIM-Signature header ↩
- What is the policy record used by DomainKeys? ↩
- DKIM — это просто ↩
- DomainKeys Identified Mail (DKIM) Author Domain Signing Practices (ADSP) ↩
- DomainKeys Identified Mail (DKIM) Service Overview ↩
- Exchange Server 2019 Public Preview ↩
- DKIM Signing Agent for Microsoft Exchange Server ↩
- Реализация DKIM для Exchange Server 2013 ↩
- Creating transport agents for Exchange 2013 ↩