Email: Exim и Dovecot — настройка SSL/TLS от Let’s Encrypt

Автор: | 08/17/2017
 

Вся моя почта бегает через маленький VPS в дата-центре «Воля».

Настроена она была ещё в 07/12/2014 и до сих пор работает отлично  (CentOS: установка и настройка Dovecot 2 + Exim + ClamAV + Postfixadmin).

Один недостаток — тогда я поленился добавить SSL/TLS, что недавно и исправил.

Проверить почтовый сервер можно на странице http://emailsecuritygrader.com — изначально он мне отдавал 50% (без SSL и SPF для домена, надо ещё добавить DKIM).

Пост — скорее «быстрая» заметка (делалось вечером) о настройке шифрования на существующем почтовом сервере Exim с аутентификатором Dovecot.

Буду мигрировать почтовый сервис в AWS — напишу более полноценный пост.

Exim

По теме:

Configuring STARTTLS in Exim

How to create a new self-signed /etc/exim.cert and /etc/exim.key

Encrypted SMTP connections using TLS/SSL

Создаём ключ:

[root@venti /etc] # openssl req -x509 -sha256 -days 9000 -nodes -newkey rsa:4096 -keyout /etc/exim.key -out /etc/exim.cert
Generating a 4096 bit RSA private key
...
writing new private key to '/etc/exim.key'
...
-----
Country Name (2 letter code) [XX]:UA
State or Province Name (full name) []:
Locality Name (eg, city) [Default City]:Kiev
Organization Name (eg, company) [Default Company Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) []:mail.domain.kiev.ua
Email Address []:user@domain.kiev.ua

Проверяем файлы:

[root@venti /etc] # file /etc/exim.cert
/etc/exim.cert: ASCII text
[root@venti /etc] # file /etc/exim.key
/etc/exim.key: ASCII text

Проверяем пользователя, под которым работает Exim:

[root@venti /etc] # ps aux | grep exim
exim     16651  0.0  0.1  99556   544 ?        Ss   Jul05   0:07 /usr/sbin/exim -bd -q1h
exim     26308  0.0  0.4  20624  2088 ?        S    20:53   0:00 dovecot/imap
...

Проверяем группы:

[root@venti /etc] # cat /etc/group | grep exim
mail:x:12:mail,postfix,exim
exim:x:93:

Выполняем chown ключей:

[root@venti /etc] # chown mail:mail /etc/exim.key
[root@venti /etc] # chmod 644 /etc/exim.key
[root@venti /etc] # chmod 644 /etc/exim.cert

Редактируем /etc/exim/exim.conf, добавляем настройки TLS:

...
tls_certificate = /etc/exim.cert
tls_privatekey = /etc/exit.key
tls_advertise_hosts = *
tls_on_connect_ports=465
...

Перезапускаем:

[root@venti /etc] # service exim restart
Shutting down exim:                                        [  OK  ]
Starting exim:                                             [  OK  ]

Проверяем логи:

2017-08-07 21:23:20 1demgS-0006uG-8P <= user@domain.kiev.ua H=([192.168.1.102]) [188.***.***.114] I=[77.***.***.20]:25 P=esmtpa A=auth_login:user@domain.kiev.ua S=1423
id=ec2d4801-4280-ba3c-3155-0261954b3e6a@domain.kiev.ua from <user@domain.kiev.ua> for user@domain.kiev.ua
2017-08-07 21:23:20 1demgS-0006uG-8P => user <user@domain.kiev.ua> R=dovecot_user T=dovecot_delivery
2017-08-07 21:23:20 1demgS-0006uG-8P Completed

Почему [77.***.***.20]:25?

Пробуем swaks:

[root@venti /etc] # yum install swaks

Запускаем:

[root@venti /etc] # swaks -a -tls -q HELO -s mail.domain.kiev.ua -au test -ap '<>'
=== Trying mail.domain.kiev.ua:25...
=== Connected to mail.domain.kiev.ua.
<-  220 mail.domain.org.ua, ESMTP EXIM 4.89
-> EHLO venti.domain.org.ua
<-  250-mail.domain.org.ua Hello venti.domain.org.ua [77.***.***.20]
<-  250-SIZE 67108864
<-  250-8BITMIME
<-  250-PIPELINING
<-  250-AUTH LOGIN PLAIN CRAM-MD5
<-  250-CHUNKING
<-  250-STARTTLS
<-  250 HELP
-> STARTTLS
<-  220 TLS go ahead
=== TLS started with cipher TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256
=== TLS no local certificate set
=== TLS peer DN="/C=UA/L=Kiev/O=Default Company Ltd/CN=mail.domain.kiev.ua/emailAddress=user@domain.kiev.ua"
~> EHLO venti.domain.org.ua
<~  250-mail.domain.org.ua Hello venti.domain.org.ua [77.***.***.20]
<~  250-SIZE 67108864
<~  250-8BITMIME
<~  250-PIPELINING
<~  250-AUTH LOGIN PLAIN CRAM-MD5
<~  250-CHUNKING
<~  250 HELP
~> QUIT
<~  221 mail.domain.org.ua closing connection
=== Connection closed with remote host.

TLS есть:


<- 250-STARTTLS
<- 250 HELP
-> STARTTLS
<- 220 TLS go ahead

Но всё равно подключается на порт 25, вместо 465.

Вчитываемся ещё раз в маны, обновляем в exim.conf параметр daemon_smtp_ports, добавляем открытие порта 465 при запуске:

...
daemon_smtp_ports = 25 : 250 : 465
...

Проверяем:

[root@venti /etc] # netstat -anp | grep 465
tcp        0      0 0.0.0.0:465                 0.0.0.0:*                   LISTEN      26634/exim
tcp        0      0 :::465                      :::*                        LISTEN      26634/exim

Пробуем:

[root@venti /etc] # swaks -a -tls -q HELO -s mail.domain.kiev.ua -au test -ap '<>'
=== Trying mail.domain.kiev.ua:25...
=== Connected to mail.domain.kiev.ua.
<-  220 mail.domain.org.ua, ESMTP EXIM 4.89
-> EHLO venti.domain.org.ua
<-  250-mail.domain.org.ua Hello venti.domain.org.ua [77.***.***.20]
<-  250-SIZE 67108864
<-  250-8BITMIME
<-  250-PIPELINING
<-  250-AUTH LOGIN PLAIN CRAM-MD5
<-  250-CHUNKING
<-  250-STARTTLS
<-  250 HELP
-> STARTTLS
<-  220 TLS go ahead
=== TLS started with cipher TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256
=== TLS no local certificate set
=== TLS peer DN="/C=UA/L=Kiev/O=Default Company Ltd/CN=mail.domain.kiev.ua/emailAddress=user@domain.kiev.ua"
~> EHLO venti.domain.org.ua
<~  250-mail.domain.org.ua Hello venti.domain.org.ua [77.***.***.20]
<~  250-SIZE 67108864
<~  250-8BITMIME
<~  250-PIPELINING
<~  250-AUTH LOGIN PLAIN CRAM-MD5
<~  250-CHUNKING
<~  250 HELP
~> QUIT
<~  221 mail.domain.org.ua closing connection
=== Connection closed with remote host.

Отправляем письмо, проверяем логи снова:

2017-08-07 21:30:39 exim 4.89 daemon started: pid=26634, -q1h, listening for SMTP on port 25 (IPv6 and IPv4) port 250 (IPv6 and IPv4) and for SMTPS on port 465 (IPv6 and IPv4)
2017-08-07 21:31:32 rejected HELO from [101.187.110.152] I=[77.***.***.20]:25: syntactically invalid argument(s): mail.domain.org.ua,
2017-08-07 21:31:58 1demom-0006vl-8s <= user@domain.kiev.ua H=([192.168.1.102]) [188.***.***.114] I=[77.***.***.20]:25 P=esmtpa A=auth_login:user@domain.kiev.ua S=643 id=09d084a6-56a4-86be-ab1a-7a1205b1ed2b@domain.kiev.ua from <user@domain.kiev.ua> for user@domain.kiev.ua
2017-08-07 21:31:58 1demom-0006vl-8s => user <user@domain.kiev.ua> R=dovecot_user T=dovecot_delivery
2017-08-07 21:31:58 1demom-0006vl-8s Completed

[77.***.***.20]:25 — а ты упрям…

Пробуем закрыть 25 вообще, оставляем только 465:

...
daemon_smtp_ports = 465
...

Отправляем через Thunderbird, и:

The message could not be sent because connecting to Outgoing server (SMTP) 77.***.***.20 failed. The server may be unavailable or is refusing SMTP connections. Please verify that your Outgoing server (SMTP) settings are correct and try again.

А что telnet скажет — сервер вообще готов работать?

[root@venti /etc] # telnet mail.domain.kiev.ua 465
Trying 77.***.***.20...
Connected to mail.domain.kiev.ua.
Escape character is '^]'.

Да, всё ОК.

Проверяем логи Exim — и оп! Уже что-то:

2017-08-07 21:35:32 TLS error on connection from [77.***.***.20] I=[77.***.***.20]:465 (SSL_accept): error:140760FC:SSL routines:SSL23_GET_CLIENT_HELLO:unknown protocol
2017-08-07 21:35:32 TLS client disconnected cleanly (rejected our certificate?)
2017-08-07 21:36:31 TLS error on connection from [188.***.***.114] I=[77.***.***.20]:465 (SSL_accept): error:140760FC:SSL routines:SSL23_GET_CLIENT_HELLO:unknown protocol

openssl verify TLS

Проверяем с помощью openssl:

[root@venti /etc] # openssl s_client -connect mail.domain.kiev.ua:465 -tls1 -servername venti.domain.kiev.ua
CONNECTED(00000003)
depth=0 C = UA, L = Kiev, O = Default Company Ltd, CN = mail.domain.kiev.ua, emailAddress = user@domain.kiev.ua
verify error:num=18:self signed certificate
verify return:1
depth=0 C = UA, L = Kiev, O = Default Company Ltd, CN = mail.domain.kiev.ua, emailAddress = user@domain.kiev.ua
verify return:1
---
Certificate chain
0 s:/C=UA/L=Kiev/O=Default Company Ltd/CN=mail.domain.kiev.ua/emailAddress=user@domain.kiev.ua
i:/C=UA/L=Kiev/O=Default Company Ltd/CN=mail.domain.kiev.ua/emailAddress=user@domain.kiev.ua
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIFzTCCA7WgAwIBAgIJAI3/E0l5HkHEMA0GCSqGSIb3DQEBCwUAMH0xCzAJBgNV
...
6hpCEGJj8XmSPg++QMbGq8rNDY5HmqXZV6grpyqtDGgWVUitn3my4ZHEPtIDDzmU
ag==
-----END CERTIFICATE-----
subject=/C=UA/L=Kiev/O=Default Company Ltd/CN=mail.domain.kiev.ua/emailAddress=user@domain.kiev.ua
issuer=/C=UA/L=Kiev/O=Default Company Ltd/CN=mail.domain.kiev.ua/emailAddress=user@domain.kiev.ua
---
No client certificate CA names sent
Server Temp Key: ECDH, prime256v1, 256 bits
---
SSL handshake has read 2446 bytes and written 319 bytes
---
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES256-SHA
...
SSL-Session:
Protocol  : TLSv1
...
TLS session ticket lifetime hint: 200 (seconds)
TLS session ticket:
...
Timeout   : 7200 (sec)
Verify return code: 18 (self signed certificate)
---
220 mail.domain.org.ua, ESMTP EXIM 4.89

Verify return code: 18 (self signed certificate) — ОК, тут проблема понятна.

Let’s Encrypt SSL для Exim

Загружаем LE клиент:

[root@venti /etc] # git clone https://github.com/letsencrypt/letsencrypt /opt/letsencrypt

Получаем ключи для домена (который указан в MX):

[root@venti /etc] # dig domain.kiev.ua mx +short
10 mail.domain.kiev.ua.

Выполняем:

[root@venti /etc] # /opt/letsencrypt/letsencrypt-auto certonly -d mail.domain.kiev.ua

yum туговат…

Для авторизации тут используем standalone webserver:

...
1: Apache Web Server plugin - Beta (apache)
2: Spin up a temporary webserver (standalone)
3: Place files in webroot directory (webroot)
-------------------------------------------------------------------------------
Select the appropriate number [1-3] then [enter] (press 'c' to cancel): 2
...

Проверяем файлы ключей:

[root@venti /etc] # ls -l /etc/letsencrypt/live/mail.domain.kiev.ua/
total 4
lrwxrwxrwx 1 root root  44 Aug  7 21:59 cert.pem -> ../../archive/mail.domain.kiev.ua/cert1.pem
lrwxrwxrwx 1 root root  45 Aug  7 21:59 chain.pem -> ../../archive/mail.domain.kiev.ua/chain1.pem
lrwxrwxrwx 1 root root  49 Aug  7 21:59 fullchain.pem -> ../../archive/mail.domain.kiev.ua/fullchain1.pem
lrwxrwxrwx 1 root root  47 Aug  7 21:59 privkey.pem -> ../../archive/mail.domain.kiev.ua/privkey1.pem

Обновляем настройки Exim:

...
tls_certificate = /etc/letsencrypt/live/mail.domain.kiev.ua/fullchain.pem
tls_privatekey = /etc/letsencrypt/live/mail.domain.kiev.ua/privkey.pem
...

Перезапускаем, проверям с помощь например https://ssl-tools.net/mailservers.

Проверяем логи — ошибки:

2017-08-07 22:05:19 TLS error on connection from (openssl.client.net) [72.32.40.101] I=[77.***.***.20]:25 (SSL_CTX_use_certificate_chain_file file=/etc/letsencrypt/live
/mail.domain.kiev.ua/fullchain.pem): error:0200100D:system library:fopen:Permission denied
2017-08-07 22:05:20 SMTP syntax error in «\026\003\001?\320\001??\314\003\003\025G\201 \277″\212\246\241\372\201\250\0243\2661\035!?\245\374u\243M\322\371\263\214:\371\
217\277??N?\236?\237?g?k\300\024\300’\300/\300\023?=?\235?5?<?\234?/\300        \300» H=(openssl.client.net) [72.32.40.101] I=[77.***.***.20]:25 NULL character(s) present (shown as ‘?’)

system library:fopen:Permission denied — ОК…

Проверяем владельца каталогов (нам нужен доступ к archive и live):

[root@venti /etc] # ls -l /etc/letsencrypt/
total 28
drwx------ 3 root root 4096 Aug  7 21:58 accounts
drwx------ 3 root root 4096 Aug  7 21:59 archive
drwxr-xr-x 2 root root 4096 Aug  7 21:59 csr
drwx------ 2 root root 4096 Aug  7 21:59 keys
drwx------ 3 root root 4096 Aug  7 21:59 live
...

Меняем владельца:

[root@venti /etc] # chown -R exim /etc/letsencrypt/archive/mail.domain.kiev.ua/
[root@venti /etc] # chown -R exim /etc/letsencrypt/live/mail.domain.kiev.ua/

Перезапускаем, проверяем на https://ssl-tools.net/mailservers:

Возвращаем порты на место:

...
daemon_smtp_ports = 25 : 250 : 465 : 587
...

Проверяем:

[root@venti /etc] # openssl s_client -connect mail.domain.kiev.ua:465 -tls1 -servername mail.domain.kiev.ua
CONNECTED(00000003)
depth=2 O = Digital Signature Trust Co., CN = DST Root CA X3
verify return:1
depth=1 C = US, O = Let's Encrypt, CN = Let's Encrypt Authority X3
verify return:1
depth=0 CN = mail.domain.kiev.ua
verify return:1
---
Certificate chain
0 s:/CN=mail.domain.kiev.ua
i:/C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3
1 s:/C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3
i:/O=Digital Signature Trust Co./CN=DST Root CA X3
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIFCzCCA/OgAwIBAgISA5nPXwXDw64ldv6rCsp6Z3deMA0GCSqGSIb3DQEBCwUA
...
+SRTkkCxEtH1OIeqqOLQzOtrbd7lfgfIFMnlixaQjkuqnFZq15gukBXtkF7eZ2A=
-----END CERTIFICATE-----
subject=/CN=mail.domain.kiev.ua
issuer=/C=US/O=Let's Encrypt/CN=Let's Encrypt Authority X3
---
No client certificate CA names sent
Server Temp Key: ECDH, prime256v1, 256 bits
---
SSL handshake has read 3157 bytes and written 318 bytes
---
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES256-SHA
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
Protocol  : TLSv1
...
Timeout   : 7200 (sec)
Verify return code: 0 (ok)
---
220 mail.domain.org.ua, ESMTP EXIM 4.89

Verify return code: 0 (ok) — отлично.

Логи:

2017-08-07 22:20:15 1denZX-00079A-Kt <= user@domain.kiev.ua H=([192.168.1.102]) [188.***.***.114] I=[77.***.***.20]:465 P=esmtpsa X=TLSv1.2:ECDHE-RSA-AES128-GCM-SHA256:
128 CV=no A=auth_login:user@domain.kiev.ua S=1304 id=276214b5-0e1c-4d00-231d-b0503c8df710@domain.kiev.ua from <user@domain.kiev.ua> for user@domain.kiev.ua
2017-08-07 22:20:15 1denZX-00079A-Kt => user <user@domain.kiev.ua> R=dovecot_user T=dovecot_delivery

Проверяем на странице http://emailsecuritygrader.com — уже 80% надёжности.

Dovecot SSL

По теме:

Linux Dovecot Secure IMAPS / POP3S SSL Server configuration

Бекапим конфиг:

[root@venti /etc] # cp /etc/dovecot/dovecot.conf /etc/dovecot/dovecot.conf_07_08_2017

 

Обновляем /etc/dovecot/dovecot.conf, задаём протокол imaps вместо imap:

...
protocols = imaps
...

И SSL:

...
ssl = yes
ssl_cert_file = /etc/letsencrypt/live/mail.domain.kiev.ua/fullchain.pem
ssl_key_file = /etc/letsencrypt/live/mail.domain.kiev.ua/privkey.pem
...

Перезапускаем:

23:20:27 [root@venti /etc] # service dovecot restart
Stopping Dovecot Imap:                                     [  OK  ]
Starting Dovecot Imap: doveconf: Warning: NOTE: You can get a new clean config file with: doveconf -n > dovecot-new.conf
doveconf: Warning: Obsolete setting in /etc/dovecot/dovecot.conf:17: protocols=imaps is no longer supported. to disable non-ssl imap, use service imap-login { inet_list
ener imap { port=0 } }
doveconf: Warning: Obsolete setting in /etc/dovecot/dovecot.conf:49: ssl_cert_file has been replaced by ssl_cert = <file
doveconf: Warning: Obsolete setting in /etc/dovecot/dovecot.conf:50: ssl_key_file has been replaced by ssl_key = <file

protocols=imaps is no longer supported — ну, ОК, меняем на imap:

Лог:

Aug  7 23:23:12 venti dovecot: master: Error: service(imap-login): command startup failed, throttling
Aug  7 23:23:12 venti dovecot: imap-login: Fatal: Can’t load ssl_cert: There is no valid PEM certificate. (You probably forgot ‘<‘ from ssl_cert=</etc/letsencrypt/live/
mail.domain.kiev.ua/fullchain.pem)
Aug  7 23:23:12 venti dovecot: imap-login: Fatal: Can’t load ssl_cert: There is no valid PEM certificate. (You probably forgot ‘<‘ from ssl_cert=</etc/letsencrypt/live/
mail.domain.kiev.ua/fullchain.pem)
Aug  7 23:24:12 venti dovecot: imap-login: Fatal: Can’t load ssl_cert: There is no valid PEM certificate. (You probably forgot ‘<‘ from ssl_cert=</etc/letsencrypt/live/
mail.domain.kiev.ua/fullchain.pem)

ОК, добавляем «<«:

...
ssl = yes
ssl_cert=</etc/letsencrypt/live/mail.domain.kiev.ua/fullchain.pem
ssl_key=</etc/letsencrypt/live/mail.domain.kiev.ua/privkey.pem
...

(странный синтаксис, ну да ладно)

Обновляем листенеры — комментим старый и добавляем новый:

...
#service imap-login {
#    chroot =
#    client_limit = 256
#    process_limit = 128
#    process_min_avail = 3
#    service_count = 1
#    vsz_limit = 64 M
#}

service imap-login {
  process_min_avail = 16
  user = dovecot

  inet_listener imap {
      port=0
  }
}
...

Отправляем через Thunderbird:

Настройки SMTP:

Лог:

Aug  7 23:30:45 venti dovecot: imap-login: Login: user=<user@domain.kiev.ua>, method=PLAIN, rip=188.***.***.114, lip=77.***.***.20, TLS

77.***.***.20, TLS — отлично.

В целом на этом всё. Осталось перенести на новый сервер и насетапить всё с нуля.

Вообще было 98%.