воскресенье, 9 февраля 2014 г.

Настройка SSL/TLS в Postfix, Dovecot, Lighttpd

Настройка SSL и TLS уже была вскользь упомянута в предыдущих заметках Установка и настройка Postfixadmin, Установка и настройка Dovecot и Установка и настройка Postfix, OpenDKIM, ClamAV-Milter, Milter-Greylist. В этой заметке я собираюсь раскрыть тему поподробнее. Учтите, что некоторые из описанных настроек я не тестировал, они приведены лишь для того, чтобы обозначить направление, в котором следует двигаться, если такие настройки понадобятся.

1. Подготовка сертификатов SSL/TLS

Сертификаты могут быть самоподписанными или подписанными удостоверяющим центром. Самоподписанные сертификаты обычно используются лишь для тестирования поддержки SSL/TLS в различных серверах и отладки настроек. На публичных серверах стоит использовать сертификаты, подписанные удостоверяющими центрами.

Услуги удостоверяющих центров, по моим меркам, обходятся довольно дорого, но некоторые удостоверяющие центры предоставляют и бесплатные ограниченные услуги для частных лиц. Мне известен только один такой удостоверяющий центр - StartSSL. Подробнее процедура получения такого сертификата описана, например, в статье Получаем бесплатный SSL сертификат или в заметке Бесплатный валидный (подписанный) SSL-сертификат через StartSSL. Перед получением сертификата нужно иметь настроенный почтовый сервер, чтобы иметь возможность подтвердить владение доменом.

2. Создание CA-сертификата (для самоподписания)

CA-сертификат - это сертификат центра сертификации (как бы тавтологично это ни звучало). Этим сертификатом подписываются все остальные сертификаты, используемые различными сервисами.

Воспользуемся скриптом, идущим в комплекте с пакетом openssl:
# /usr/lib/ssl/misc/CA.pl -newca
Перед созданием сертификата удостоверяющего центра скрипт задаст вам несколько вопросов. Нужно приготовиться предоставить следующую информацию:
  • Страна (Country)
  • Область (State or province)
  • Город (City or other municipal area)
  • Организация (Organization)
  • Подразделение (Organization unit)
  • Общепринятое имя (Common name)
  • Электронный адрес (Email address)
В процессе создания сертификата также нужно будет указать секретную фразу, которая будет использоваться каждый раз при подписании или отзыве удостоверенных сертификатов.

В поле «общепринятое имя» в данном случае нужно вписать название организации (или торговую марку, под которой она работает) или имя владельца. В случае создания сертификата сервера нужно указать его DNS-имя.

В текущем каталоге будет создан подкаталог demoCA, в котором будут созданы необходимые файлы.

После этого я дополнительно отредактировал файл конфигурации OpenSSL /etc/ssl/openssl.cnf, указав в нём полный путь к каталогу с сертификатами удостоверяющего центра (в двух местах) и настройки срока годности вновь создаваемых сертификатов:
dir = /etc/ssl/demoCA
и
default_days = 3650
3. Создание сертификата сервера

Хотя удостоверяющий центр может сгенерировать и сертификат сервера, его можно сгенерировать самостоятельно:
# openssl req -new -nodes -keyout domain1.net.pem -out domain1.net.pem -days 3650
Generating a 2048 bit RSA private key
...........................................................................................+++
...........................................................................................................................................  ....................+++
writing new private key to 'domain1.net.pem'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:RU
State or Province Name (full name) [Some-State]:Bashkortostan Republic
Locality Name (eg, city) []:Ufa
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Vladimir Stupin
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:domain1.net
Email Address []:wheel69@yandex.ru

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
В этом случае при создании сертификата секретную фразу указывать не нужно, а в поле «Общеизвестное имя» нужно указать DNS-имя сервера.

В текущем каталоге будет создан файл domain1.net.pem с секретной частью сертификата.

4.1. Подписание сертификата сервера (самоподписание)

Для создания самоподписанного сертификата можно воспользоваться следующей командой:
# openssl ca -policy policy_anything -out domain1.net.pubilc.pem -infiles domain1.net.pem
Using configuration from /usr/lib/ssl/openssl.cnf
Enter pass phrase for /etc/ssl/ca/private/cakey.pem:
Check that the request matches the signature
Signature ok
Certificate Details:
        Serial Number: 14036232404122642274 (0xc2cab701208ea762)
        Validity
            Not Before: Feb  5 15:31:10 2014 GMT
            Not After : Feb  3 15:31:10 2024 GMT
        Subject:
            countryName               = RU
            stateOrProvinceName       = Bashkortostan Republic
            localityName              = Ufa
            organizationName          = Vladimir Stupin
            commonName                = domain1.net
            emailAddress              = wheel69@yandex.ru
        X509v3 extensions:
            X509v3 Basic Constraints: 
                CA:FALSE
            Netscape Comment: 
                OpenSSL Generated Certificate
            X509v3 Subject Key Identifier: 
                0B:DB:32:31:76:C8:F1:80:8E:2F:2E:70:8B:05:91:2A:91:69:AF:31
            X509v3 Authority Key Identifier: 
                keyid:B5:CB:D1:89:6A:E8:82:D2:D6:7C:A5:6C:13:88:EA:EE:D9:5F:8F:6E

Certificate is to be certified until Feb  3 15:31:10 2024 GMT (3650 days)
Sign the certificate? [y/n]:y


1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated

# mv domain1.net.pem domain1.net.private.pem
При подписании сертификата нужно будет указать секретную фразу из сертификата удостоверяющего центра (см. выше).

4.2. Подписание сертификата сервера (внешнее подписание)

В случае использования официального центра сертификации для подписания сертификата нужно следовать его инструкциям. Обычно для этого нужно скопировать из файла сертификата секцию CERTIFICATE REQUEST вместе с начальной и конечной строчками. Центр сертификации в ответ на запрос сгенерирует секцию CERTIFICATE, которую нужно вставить в private-файл после секции CERTIFICATE REQUEST.

После этого можно сгенерировать публичную часть сертификата:

# openssl x509 -in mail.stupin.su.pem -text > mail.stupin.su.public.pem
# mv domain1.net.pem domain1.net.private.pem
5. Подготовка сертификатов сервера к использованию

Расположим сертификаты так, чтобы они автоматически подхватились Dovecot'ом и настроим права доступа.

Чтобы локальные пользователи системы не получили доступ на чтение к приватной части сертификата и не смогли подменить публичную часть сертификата, нужно соответствующим образом выставить права доступа к файлам:
# chown root:root /etc/ssl/domain1.net.public.pem
# chmod u=rw,go=r /etc/ssl/domain1.net.public.pem

# chown root:root /etc/ssl/domain1.net.private.pem
# chmod u=rw,go= /etc/ssl/domain1.net.private.pem
6. Postfix

Postfix может выступать в роли SMTP-клиента, когда доставляет почту на другой почтовый сервер, и может выступать в роли SMTP-сервера, когда получает почту от другого сервера.

6.1. Настройка TLS в клиенте

Настроим шифрование и аутентификацию почтового сервера получателя, когда наш сервер будет пытаться отправить письмо по защищённому протоколу SMTP.

Сконвертируем pem-сертификат нашего удостоверяющего центра в формат crt и поместим в каталог для сертификатов доверенных центров авторизации:
# apt-get install ca-certificates
# mkdir /usr/share/ca-certificates/stupin.su
# openssl x509 -in /etc/ssl/demoCA/cacert.pem -out /usr/share/ca-certificates/stupin.su/cacert.crt
Теперь сгенерируем новый список сертификатов, которым будет доверять наша система:
# dpkg-reconfigure ca-certificates
В открывшемся окне нужно ответить «спрашивать» и отметить в списке наш сертификат. После этого будет сформирован новый файл /etc/ca-certificates.conf (нужно проверить, что в списке есть наш сертификат и в начале строчки нет восклицательного знака). pem-сертификаты будут помещены в каталог /etc/ssl/certs.

Добавим в файл /etc/postfix/main.cf следующие настройки:
# Настройка SMTP-клиента, отправляющего почту
smtp_tls_loglevel = 2
smtp_tls_CApath = /etc/ssl/certs
Осталось перезапустить сервер, чтобы настройки вступили в силу:
# /etc/init.d/postfix restart
6.2. Настройка TLS в сервере

Настраиваем шифрование с использованием ранее подготовленных SSL-сертификатов. Для этого добавим в файл /etc/postfix/main.cf следующие настройки:
# Настройка SMTP-сервера, принимающего почту
smtpd_use_tls = yes
smtpd_tls_key_file = /etc/ssl/domain1.net.private.pem
smtpd_tls_cert_file = /etc/ssl/domain1.net.public.pem
smtpd_tls_CApath = /etc/ssl/certs
smtpd_tls_loglevel = 2
smtpd_tls_received_header = yes
Осталось перезапустить сервер, чтобы настройки вступили в силу:
# /etc/init.d/postfix restart
6.3. Несколько сертификатов TLS на сервере

Postfix не имеет поддержки расширения SNI, потому что в SMTP клиент не может указать, к серверу с каким доменным именем он подключался. Соответственно, пока клиент не может этого сообщить, SMTP-сервер не может выбрать правильный сертификат. Для обслуживания почты из других доменов придётся обойтись настройкой MX-записи, указывающей на доменное имя сервера, которое он сообщает в команде HELO/EHLO.

Postfix также не имеет явных настроек для работы с разными сертификатами на разных IP-адресах. Однако, можно запустить несколько экземпляров сервера smtpd с разными настройками прослушиваемого IP-адреса, имени сервера и используемых сертификатов. Для этого можно попытаться задать в файле /etc/postfix/master.cf следующие настройки:
192.168.0.1:smtp inet  n  -        n        -        -        smtpd
  -o smtpd_tls_key_file=/etc/ssl/domain1.net.private.pem
  -o smtpd_tls_cert_file=/etc/ssl/domain1.net.public.pem
  -o myhostname=domain1.net
  -o mydomain=domain1.net
  -o myorigin=domain1.net

172.16.0.1:smtp inet  n  -        n        -        -        smtpd
  -o smtpd_tls_key_file=/etc/ssl/domain2.ru.private.pem
  -o smtpd_tls_cert_file=/etc/ssl/domain2.ru.public.pem
  -o myhostname=domain2.ru
  -o mydomain=domain2.ru
  -o myorigin=domain2.ru
Или можно воспользоваться новой возможностью Postfix - создать несколько экземпляров сервера. Подробнее об этом можно почитать на странице http://www.postfix.org/MULTI_INSTANCE_README.html

6.4. Оптимизация производительности

Настройка менеджера TLS-сессий описана в заметке Установка и настройка Postfix, OpenDKIM, ClamAV-Milter, Milter-Greylist в разделе «6. Оптимизация скорости работы Postfix».

7. Dovecot

При включении поддержки SSL нужно задать сертификат для использования по умолчанию. Включим поддержку SSL в файле /etc/dovecot/conf.d/10-ssl.conf:
ssl = yes
ssl_cert = </etc/ssl/domain1.net.public.pem
ssl_key = </etc/ssl/domain1.net.private.pem
И перезапустить Dovecot, чтобы новые настройки вступили в силу:
# /etc/init.d/dovecot restart
Dovecot может использовать как один сертификат, так и несколько. В случае использования нескольких сертификатов можно назначать отдельные сертификаты как на отдельные IP-адреса, на которых Dovecot будет ожидать подключения, так и на отдельные сервисы. Например, можно задать отдельные сертификаты для POP3 и для IMAP (хотя не ясно, какой в этом может быть смысл). Например, вот так:
local 192.168.0.1 {
  protocol imap {
    ssl_cert = </etc/ssl/dovecot/imap.domain1.net.public.pem
    ssl_key  = </etc/ssl/dovecot/imap.domain1.net.private.pem
  }

  protocol pop3 {
    ssl_cert = </etc/ssl/dovecot/pop.domain1.net.pubilc.pem
    ssl_key  = </etc/ssl/dovecot/pop.domain1.net.private.pem
  }
}

local 172.16.0.1 {
    ssl_cert = </etc/ssl/dovecot/domain2.ru.public.pem
    ssl_key  = </etc/ssl/dovecot/domain2.ru.private.pem
}
В примере выше указаны раздельные сертификаты для сервисов на первом IP-адресе и общий сертификат для сервисов на втором IP-адресе. Вместо IP-адресов можно указывать доменные имена, однако не впадайте в заблуждение - эти доменные имена не могут указывать на один и тот же IP-адрес. Перед использованием доменные имена решаются в IP-адреса, так что два домена, указывающих на один и тот же IP-адрес, породят две секции с одинаковым IP-адресом.

Использование раздельных сертификатов для отдельных IP-адресов и сервисов не избавляет от необходимости указывать сертификаты по умолчанию. Будьте внимательны!

Также Dovecot поддерживает расширение протокола SSL, которое называется Server Name Indication или, сокращённо, SNI. Если клиент поддерживает это расширение, то можно использовать разные сертификаты для разных доменных имён. Настройки, которые можно прописать при использовании SNI:
local_name domain1.net {
  ssl_cert = </etc/ssl/domain1.net.pubilc.pem
  ssl_key = </etc/ssl/domain1.net.private.pem
}

local_name domain2.ru {
  ssl_cert = </etc/ssl/domain2.ru.public.pem
  ssl_key = </etc/ssl/domain2.ru.private.pem
}
Более подробную информацию о настройке SSL в Dovecot можно найти на официальной wiki-странице: Dovecot SSL configuration. SNI поддерживается не всеми клиентами. Одним из клиентов с подтверждённой поддержкой SNI является Thunderbird в Linux.

8. Lighttpd

Для настройки SSL в веб-сервере Lighttpd достаточно включить модуль ssl:
# lighty-enable-mod ssl
B прописать используемый сертификат в файл /etc/lighttpd/conf-enabled/05-ssl.conf:
$SERVER["socket"] == "0.0.0.0:443" {
  ssl.engine  = "enable"
  ssl.pemfile = "/etc/ssl/vladimir.stupin.su.pem"

  ssl.cipher-list = "ECDHE-RSA-AES256-SHA384:AES256-SHA256:RC4:HIGH:!MD5:!aNULL:!EDH:!AESGCM"
  ssl.honor-cipher-order = "enable"
}
И перезапустить веб-сервер, чтобы его новые настройки вступили в силу:
# /etc/init.d/lighttpd restart
Как видно, в настройках проверяется совпадение с прослушиваемым IP-адресом и TCP-портом 443. Очевидно, что таким образом можно задать несколько SSL-сертификатов, каждый из которых будет использоваться при обращении клиента к определённому IP-адресу веб-сервера. Например, вот так:
$SERVER["socket"] == "192.168.0.1:443" {
  ssl.engine  = "enable"
  ssl.pemfile = "/etc/ssl/domain1.net.pem"

  ssl.cipher-list = "ECDHE-RSA-AES256-SHA384:AES256-SHA256:RC4:HIGH:!MD5:!aNULL:!EDH:!AESGCM"
  ssl.honor-cipher-order = "enable"
}

$SERVER["socket"] == "172.16.0.1:443" {
  ssl.engine  = "enable"
  ssl.pemfile = "/etc/ssl/domain2.ru.pem"

  ssl.cipher-list = "ECDHE-RSA-AES256-SHA384:AES256-SHA256:RC4:HIGH:!MD5:!aNULL:!EDH:!AESGCM"
  ssl.honor-cipher-order = "enable"
}
Однако, таким образом можно задать только один сертификат для одного IP-адреса. Если же на одном IP-адресе обслуживается несколько доменов, то можно либо прописать в этот сертификат доменные имена всех необходимых сайтов, либо воспользоваться поддержкой SNI.

Веб-сервер Lighttpd поддерживает SNI начиная с версии 1.4.24, в случае если установлен OpenSSL версии 0.9.8f или выше. Для задания отдельных сертификатов для отдельных доменов можно воспользоваться условными секциями, меняя внутри них используемый сертификат:
$HTTP["host"] == "domain1.net" {
  ssl.pemfile = "/etc/ssl/domain1.net.pem"
}

$HTTP["host"] == "domain2.ru" {
  ssl.pemfile = "/etc/ssl/domain2.ru.pem"
}
Для того, чтобы принудительно использовать SSL на определённых сайтах, можно вписать в файл /etc/lighttpd/conf-enabled/05-ssl.conf следующую условную секцию:
$HTTP["host"] =~ "^domain(1\.net|2\.ru)$" {
  url.redirect = (".*" => "https://%0$0")
}
Стоит отметить, что сайты должны быть готовы к подобной переадресации. Например, во всех внутренних ссылках на сайте стоит убрать спецификацию протокола http. Все внутренние ссылки сайта должны быть либо относительными, либо начинаться с двух косых черт.

Продолжение следует...

14 комментариев:

hexkey комментирует...

https://www.startssl.com/ дают бесплатные сертификаты, которые проходят валидацию. :) Есть мнение, что это дело будет куда симпатичнее самоподписанного...

morbo комментирует...

Спасибо, кэп. Я, вообще-то, написал об этом в заметке.

Anton комментирует...

, Например, можно задать отдельные сертификаты для POP3 и для IMAP (хотя не ясно, какой в этом может быть смысл),

Смысл в том что это разные хосты. и некоторые почтовые клиенты не будут принимать почту если хост один, а в сертификате указан другой.

morbo комментирует...

>Смысл в том что это разные хосты. и некоторые почтовые клиенты не будут принимать почту если хост один, а в сертификате указан другой.

Если оба сервера, и POP3 и IMAP, доступны по одному и тому же IP и доменному имени, то смысл ускользает. Настраивать разные доменные имена для двух сервисов на одном и том же IP мне кажется нелогичным - от этого появляются только дополнительные хлопоты с записями в DNS и сертификатами.

Анонимный комментирует...

а нужен ли TLS на сервере, если он является почтовым релеем?

morbo комментирует...

А зачем вообще нужен TLS? Это аутентификация сервера и шифрование писем при передаче от сервера к серверу.

Почтовый релей обычно используется для одной из целей:
1. резервирует основной сервер, принимая письма, когда основной сервер недоступен,
2. выполняет часть его работы, занимаясь приёмом снаружи и передачей их основному серверу,
3. выполняет часть его работы, занимаясь приемом писем от основного сервера и их передачей во внешний мир.

Во всех этих случаях релей взаимодействует с внешними серверами, поэтому поддержка TLS на нём полезна. При передаче писем наружу он выступает TLS-клиентом (проверяет подлинность внешнего почтового сервера), а при приёме - TLS-сервером (удостоверяет свою подлинность перед внешними серверами). В обоих случаях как правило обмен письмами происходит по зашифрованному каналу. При этом на серверах письма обрабатываются в открытом виде.

Для шифрования между адресатами, а не серверами, и аутентификации адресатов, а не серверов нужно использовать PGP/GPG. При этом, в зависимости от обстоятельств в которых состоялся обмен ключами, получается разный уровень аутентификации. Если обмен ключами произошёл при личной встрече, то с определённой степенью достоверности можно считать, что переписываешься именно с этим человеком. Если подпись была взята из публичного источника, то можно удостовериться лишь в том, что определённые письма написаны одним и тем же автором.

Полной уверенности, конечно, PGP не даёт, т.к. паяльник в известном месте может творить чудеса - адресат может выдать и ключи и пароли. Тогда письма от его лица могут читать и писать посторонние люди.

Анонимный комментирует...

Как показала практика. Если руководствоваться данной статьей, шифрование работает только в одну сторону то есть, на получение почты. Для отключения небезопасного sslv3. И возможности отправлять шифрованные сообщения, добавил в main.comf следующий текст:
# inbound
smtpd_tls_security_level = may
smtpd_tls_protocols=!SSLv2,!SSLv3
smtpd_tls_mandatory_protocols=!SSLv2,!SSLv3
# outbound
smtp_tls_security_level = may
smtp_tls_protocols=!SSLv2,!SSLv3
smtp_tls_mandatory_protocols=!SSLv2,!SSLv3

ссылка: http://serverfault.com/questions/669847/how-to-disable-sslv3-in-postfix-2-11

Анонимный комментирует...

извините, описался добавить нужно в main.cf

Unknown комментирует...

Добрые сутки, скажите пажаласта, пункт номер один является заменой пункту под номером два? Я уже просто упоролся с этими сертификатами, ваша статья отличная, но не понимаю, без пункта номер один могу я идти дальше по списку? Меня эти первые два пункта сбивают с толку. 8-(

morbo комментирует...

Доброго времени года.

Понимаю, получилось запутанно. Сам хотел переработать этот раздел, но так и не сподобился.

Пункт 1 - это просто введение.

Пункт 2 нужен только для пункта 4.1.

Пункты 4.1 и 4.2 взаимозаменяемые.

Если у вас уже есть сертификаты, тогда можно переходить к пункту 5.

Пажаласта.

Unknown комментирует...

Теперь всё стало на свои места. Кстати пункта 4 нет, идёт сразу 4.1!!
Сертификатов нет, хочу использовать только свои, очасти поэтому и возник вопрос.

Спасиба большая!

morbo комментирует...

Очасти вы правы, формально пункта 4 нет, но фактически он состоит из подпунктов 4.1 и 4.2.

На здаровья!!11одинодин

Alexander комментирует...

спасибо, полезный мануал, заметил опечатку - не /etc/ssl/openssl.conf а /etc/ssl/openssl.cnf

morbo комментирует...

Спасибо, поправил.