# Запуск почтового сервера. Часть 2. Настройка Postfix и Dovecot

Это вторая часть нашей инструкции по запуску почтового сервера на VPS под управлением CentOS 8.

В первой части мы рассмотрели подготовку бэкэнда для нашего сервера — настроили DNS-записи доменного имени, установили веб-сервер, систему управления базами данных, PHP и phpMyAdmin, установили веб-интерфейс для администрирования почтового сервиса Postfixadmin и создали первый ящик на сервере.

В этой части мы поговорим о настройке сервисов для отправки и получения почты — Postfix и Dovecot.

# Postfix

По умолчанию в CentOS Postfix не установлен, поэтому начнём работу с его установки. Установим сам Postfix и дополнительный пакет для работы с MySQL:

sudo dnf install postfix postfix-mysql

После установки Postfix можно сразу же переходить к его настройке:

sudo vi /etc/postfix/main.cf

Открывшийся файл основной конфигурации нужно привести к следующему виду:

soft_bounce = no

myhostname = mail.your_domain.com
mydomain = your_domain.com
myorigin = $myhostname

inet_interfaces = all
inet_protocols = ipv4

mydestination = localhost.$mydomain, localhost
mynetworks = 127.0.0.0/8, 10.1.4.22/32

smtpd_banner = $myhostname ESMTP $mail_name

Это содержимое конфигурационного файла, которое находится там по умолчанию. Сам конфигурационный файл гораздо больше, а здесь мы привели только те строки, которые необходимо в нём изменить.

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

relay_domains = mysql:/etc/postfix/mysql/relay_domains.cf
virtual_alias_maps = mysql:/etc/postfix/mysql/virtual_alias_maps.cf,
 mysql:/etc/postfix/mysql/virtual_alias_domain_maps.cf
virtual_mailbox_domains = mysql:/etc/postfix/mysql/virtual_mailbox_domains.cf
virtual_mailbox_maps = mysql:/etc/postfix/mysql/virtual_mailbox_maps.cf

smtpd_discard_ehlo_keywords = etrn, silent-discard
smtpd_forbidden_commands = CONNECT GET POST
broken_sasl_auth_clients = yes
smtpd_delay_reject = yes
smtpd_helo_required = yes
smtp_always_send_ehlo = yes
disable_vrfy_command = yes

smtpd_helo_restrictions = permit_mynetworks,
 permit_sasl_authenticated,
 reject_non_fqdn_helo_hostname,
 reject_invalid_helo_hostname

smtpd_data_restrictions = permit_mynetworks,
 permit_sasl_authenticated,
 reject_unauth_pipelining,
 reject_multi_recipient_bounce,

smtpd_sender_restrictions = permit_mynetworks,
 permit_sasl_authenticated,
 reject_non_fqdn_sender,
 reject_unknown_sender_domain

smtpd_recipient_restrictions = permit_mynetworks,
 permit_sasl_authenticated,
 reject_non_fqdn_recipient,
 reject_unknown_recipient_domain,
 reject_multi_recipient_bounce,
 reject_unauth_destination,

smtp_tls_security_level = may
smtp_tls_loglevel = 1
smtpd_tls_security_level = may
smtpd_tls_loglevel = 1
smtpd_tls_received_header = yes
smtpd_tls_session_cache_timeout = 3600s
smtp_tls_session_cache_database = btree:$data_directory/smtp_tls_session_cache
smtpd_tls_key_file = /etc/postfix/certs/key.pem
smtpd_tls_cert_file = /etc/postfix/certs/cert.pem
tls_random_source = dev:/dev/urandom
smtpd_tls_mandatory_ciphers = low
smtpd_tls_ciphers = low
smtpd_tls_mandatory_protocols = !SSLv2,!SSLv3
smtp_tls_mandatory_protocols  = !SSLv2,!SSLv3
smtp_tls_ciphers = low
smtp_tls_mandatory_ciphers = low
smtp_tls_protocols = !SSLv2,!SSLv3
smtp_tls_policy_maps = hash:/etc/postfix/tls_policy_maps
smtp_tls_note_starttls_offer = yes

# Здесь указываем максимальный размер письма в байтах
message_size_limit = 20000000
smtpd_soft_error_limit = 10
smtpd_hard_error_limit = 15
smtpd_error_sleep_time = 20
anvil_rate_time_unit = 60s
smtpd_client_connection_count_limit = 20
smtpd_client_connection_rate_limit = 30
smtpd_client_message_rate_limit = 30
smtpd_client_event_limit_exceptions = 127.0.0.0/8
smtpd_client_connection_limit_exceptions = 127.0.0.0/8

maximal_queue_lifetime = 1d
bounce_queue_lifetime = 1d

smtpd_sasl_auth_enable = yes
smtpd_sasl_security_options = noanonymous
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/dovecot-auth

# Определяем директории для хранения почты
virtual_mailbox_base = /mnt/mail
virtual_minimum_uid = 1000
virtual_uid_maps = static:1000
virtual_gid_maps = static:1000
virtual_transport = dovecot
dovecot_destination_recipient_limit = 1

sender_bcc_maps = hash:/etc/postfix/sender_bcc_maps
recipient_bcc_maps = hash:/etc/postfix/recipient_bcc_maps

compatibility_level=2

Конфигурационный файл Postfix готов. Теперь нужно создать файлы, описанные внутри конфигурационного файла, — они будут определять взаимодействие Postfix с MySQL.

Мы создадим для этих файлов отдельную директорию и сразу же перейдём туда, чтобы было удобнее работать:

sudo mkdir /etc/postfix/mysql

cd /etc/postfix/mysql

Создаём первый файл, который будет отвечать за отправку почты через почтовые серверы на нашем домене:

sudo vi relay_domains.cf

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

hosts = localhost
user = postfix
password = password
dbname = postfix
query = SELECT domain FROM domain WHERE domain='%s' and backupmx = '1'

Далее создаём файл с описанием доменных алиасов, которые также будут браться из базы данных.

sudo vi virtual_alias_domain_maps.cf

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

hosts = localhost
user = postfix
password = password
dbname = postfix
query = SELECT goto FROM alias,alias_domain WHERE alias_domain.alias_domain = '%d' and alias.address = CONCAT('%u', '@', alias_domain.target_domain) AND alias.active = 1

После этого переходим к файлу, описывающему источники для получения соответствия адреса пользователя во внешних доменах с адресом во внутренних.

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

sudo vi virtual_alias_domain.cf
hosts = localhost
user = postfix
password = password
dbname = postfix
query = SELECT goto FROM alias WHERE address='%s' AND active = '1'

Затем создаём файл для поиска домена получателя письма:

sudo vi virtual_mailbox_domains.cf
hosts = localhost
user = postfix
password = password
dbname = postfix
query = SELECT domain FROM domain WHERE domain='%s' AND backupmx = '0' AND active = '1'

Теперь создадим файл для поиска самих почтовых ящиков:

sudo vi virtual_mailbox_maps.cf
hosts = localhost
user = postfix
password = password
dbname = postfix
query = SELECT maildir FROM mailbox WHERE username='%s' AND active = '1

Последним создадим файл, в котором можно будет вручную указывать версии tls-протоколов. Это может быть удобно при подключении к серверам, использующим старые или нестандартные версии протоколов обмена данными:

sudo vi /etc/postfix/tls_policy_maps

Добавим сюда несколько вариантов протоколов:

93.175.56.122   none
77.221.87.91    encrypt protocols=TLSv1

Укажем Postfix использовать эту таблицу в качестве одной из своих:

sudo postmap /etc/postfix/tls_policy_maps

Теперь отредактируем файл, отвечающий за работу SMTP-сервера на альтернативном порту. Это может быть полезно при отправке почты, например, на смартфоны:

sudo vi /etc/postfix/master.cf

Здесь нам нужно раскомментировать все строки в разделах submission inet n - n - - smtpd и smtps inet n - n - - smtpd, и добавить в конце файла следующий раздел:

dovecot unix - n n - - pipe
 flags=DRhu user=vmail:vmail argv=/usr/libexec/dovecot/deliver -f ${sender} -d ${recipient}

Теперь осталось только создать файлы, в которых мы укажем почтовые ящики для сбора входящей и исходящей почты:

sudo mkdir /etc/postfix/recipient_bcc_maps

В открывшемся файле укажем домен и ящик для сбора входящей почты:

@your_domain.com all_in@your_domain.com

Сделаем то же самое для исходящей почты:

sudo mkdir /etc/postfix/sender_bcc_maps
@your_domain.com all_out@your_domain.com

Теперь создадим индексированные базы данных на основе этих файлов:

postmap /etc/postfix/sender_bcc_maps /etc/postfix/recipient_bcc_maps

Последний шаг — создание этих почтовых ящиков (all_in@your_domain.com и all_out@your_domain.com) через Postfixadmin.

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

Основная настройка почтового сервиса Postfix, предназначенного для отправки почты, закончена.

# Рабочий порт Postfix

Обратите внимание, что рабочий порт для Postfix — 25. У части хостинговых компаний он заблокирован, поскольку очень часто используется для массовой рассылки сообщений. Если в процессе тестирования вашего почтового сервера почта не будет отправляться, обратитесь к своей хостинговой компании с просьбой разблокировать 25 порт.

Подробнее о том, как настроить Postfix только для отправки сообщений и определить заблокированный порт, написано в нашей инструкции по установке и настройке почтового агента Potfix.

# Сертификаты безопасности

В нашей инструкции мы будем использовать самоподписные сертификаты безопасности, но в общем случае создавать сервер лучше на официальных. В целом настройка и подключение таких сертификатов принципиально не отличается от самоподписных — разница будет только в указании путей к сертификатам.

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

Создадим отдельную папку для сертификатов:

sudo mkdir /etc/postfix/certs

Теперь можно создать новый сертификат:

sudo openssl req -new -x509 -days 3650 -nodes -out /etc/postfix/certs/cert.pem -keyout /etc/postfix/certs/key.pem

В процессе создания нам предложат ответить на несколько вопросов о себе и о компании, которую для которой мы создаём сертификат. Ответы могут быть любыми — здесь нет проверки подлинности вводимых данных.

# Настройка Dovecot

После настройки сервиса для отправки сообщений настроим сервис для получения почты. Для этого мы будем использовать Dovecot.

Установим сам Dovecot, пакет для его взаимодействия с MySQL и отдельный пакет для поддержки языка sieve, чтобы подключить соответствующий плагин:

sudo dnf install dovecot dovecot-mysql dovecot-pigeonhole

После установки займёмся конфигурацией Docvecot. По умолчанию все конфигурационные файлы лежат в папке /etc/dovecot/conf.d. В каждом файле описан отдельный блок для взаимодействия. Очень часто при работе с Dovecot администраторы объединяют все настройки в одном конфигурационном файле, чтобы постоянно не переключаться между ними. Мы сделаем так же — соберём в один файл все нужные настройки:

sudo vi /etc/dovecot/dovecot.conf

По умолчанию в этом файле содержится закомментированное описание работы Dovecot. Можно его оставить, можно удалить — это на ваше усмотрение, на работу основной конфигурации наличие закомментированной информации никак не повлияет.

Мы будем добавлять информацию в этот файл отдельными блоками, и в конце получится большой файл, описывающий всю работу Dovecot.

Начнём с общих параметров: прослушиваемый порт, протоколы работы и ID пользователя, которого мы создадим чуть позже и от имени которого будем выполнять сбор почты:

listen = *

mail_plugins = mailbox_alias acl
protocols = imap pop3 sieve lmtp

mail_uid = 1001
mail_gid = 1001

first_valid_uid = 1001
last_valid_uid = 1001

…

Мы указали здесь id =1001. Вы можете выбрать любой незанятый ID. Чтобы проверить всех пользователей и их ID, используйте команду getent passwd.

Затем включаем логирование процессов Dovecot. Указываем отдельный путь для каждого из логов, чтобы потом было легче искать нужную информацию:

…
auth_verbose = yes
log_path = /var/log/dovecot/main.log
info_log_path = /var/log/dovecot/info.log
debug_log_path = /var/log/dovecot/debug.log
…

Следующий раздел отвечает за безопасность и шифрование данных:

ssl_min_protocol = SSLv3
verbose_ssl = yes
ssl_cert = </etc/postfix/certs/cert.pem
ssl_key = </etc/postfix/certs/key.pem

ssl_cipher_list = ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:ECDHE-RSA-DES-CBC3-SHA:ECDHE-ECDSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA
ssl_prefer_server_ciphers = yes

Здесь в строке ssl_cipher_list указаны типы шифрования, которые поддерживает Dovecot. В нашем случае мы указали максимально большое количество, чтобы не возникло проблем с получением шифрованных писем.

Указываем тип авторизации без шифрования и далее указываем механизм авторизации. Обычно это делают только для тестовых серверов, в остальных случаях указывают значение параметра yes:

…
disable_plaintext_auth = no
auth_mechanisms = PLAIN LOGIN
…

Указываем путь хранения почты:

…
mail_location = maildir:/mnt/mail/%d/%u/
auth_default_realm = your_domain.com
…

Описываем работу сервисов, которые будут работать внутри Dovecot:

Описание сервисов Dovecot
…
service auth {
 unix_listener /var/spool/postfix/private/dovecot-auth {
 user = postfix
 group = postfix
 mode = 0666
 }
unix_listener auth-master {
 user = vmail
 group = vmail
 mode = 0666
 }

unix_listener auth-userdb {
 user = vmail
 group = vmail
 mode = 0660
 }
}

service lmtp {
 unix_listener /var/spool/postfix/private/dovecot-lmtp {
 user = postfix
 group = postfix
 mode = 0600
 }

 inet_listener lmtp {
 address = 127.0.0.1
 port = 24
 }
}

userdb {
 args = /etc/dovecot/dovecot-mysql.conf
 driver = sql
 }

passdb {
 args = /etc/dovecot/dovecot-mysql.conf
 driver = sql
 }

auth_master_user_separator = *

plugin {
 auth_socket_path = /var/run/dovecot/auth-master

 acl = vfile
 acl_shared_dict = file:/mnt/mail/shared-folders/shared-mailboxes.db
 sieve_dir = ~/.sieve/
 mailbox_alias_old = Sent
 mailbox_alias_new = Sent Messages
 mailbox_alias_old2 = Sent
 mailbox_alias_new2 = Sent Items
}

protocol lda {
 mail_plugins = $mail_plugins sieve
 auth_socket_path = /var/run/dovecot/auth-master
 deliver_log_format = mail from %f: msgid=%m %$
 log_path = /var/log/dovecot/lda-errors.log
 info_log_path = /var/log/dovecot/lda-deliver.log
 lda_mailbox_autocreate = yes
 lda_mailbox_autosubscribe = yes
# postmaster_address = root
}

protocol lmtp {
 info_log_path = /var/log/dovecot/lmtp.log
 mail_plugins = quota sieve
 postmaster_address = postmaster
 lmtp_save_to_detail_mailbox = yes
 recipient_delimiter = +
}

protocol imap {
 mail_plugins = $mail_plugins imap_acl
 imap_client_workarounds = tb-extra-mailbox-sep
 mail_max_userip_connections = 30
}

protocol pop3 {
 mail_plugins = $mail_plugins
 pop3_client_workarounds = outlook-no-nuls oe-ns-eoh
 pop3_uidl_format = %08Xu%08Xv
 mail_max_userip_connections = 30
}

service imap-login {
 service_count = 1
 process_limit = 500
 }

service pop3-login {
 service_count = 1
 }

service managesieve-login {
 inet_listener sieve {
 port = 4190
 }
}

service stats {
    unix_listener stats-reader {
        user = vmail
        group = vmail
        mode = 0660
    }

    unix_listener stats-writer {
        user = vmail
        group = vmail
        mode = 0660
    }
}

namespace inbox {
 type = private
 separator = /
 prefix =
 inbox = yes

 mailbox Sent {
 auto = subscribe
 special_use = \Sent
 }
 mailbox "Sent Messages" {
 auto = no
 special_use = \Sent
 }
 mailbox "Sent Items" {
 auto = no
 special_use = \Sent
 }
 mailbox Drafts {
 auto = subscribe
 special_use = \Drafts
 }
 mailbox Trash {
 auto = subscribe
 special_use = \Trash
 }
 mailbox "Deleted Messages" {
 auto = no
 special_use = \Trash
 }
 mailbox Junk {
 auto = subscribe
 special_use = \Junk
 }
 mailbox Spam {
 auto = no
 special_use = \Junk
 }
 mailbox "Junk E-mail" {
 auto = no
 special_use = \Junk
 }
 mailbox Archive {
 auto = no
 special_use = \Archive
 }
 mailbox Archives {
 auto = no
 special_use = \Archive
 }
}

namespace {
 type = shared
 separator = /
 prefix = Shared/%%u/
 location = maildir:%%h:INDEX=%h/shared/%%u
 subscriptions = yes
 list = children
}

После того как мы собрали весь конфигурационный файл, его можно сохранить и закрыть.

Теперь создадим пользователя с id=1001, которого описали в самом начале конфигурационного файла, и передадим ему права на управление папками с почтой:

sudo groupadd  -g 1001 vmail

sudo useradd -d /mnt/mail/ -g 1001 -u 1001 vmail

sudo chown vmail. /mnt/mail

Осталось только создать конфигурационный файл с описанием доступа к MySQL:

sudo vi /etc/dovecot/dovecot-mysql.conf

Содержимое файла будет следующим:

driver = mysql
default_pass_scheme = CRYPT
connect = host=127.0.0.1 dbname=postfix user=postfix password=password
user_query = SELECT '/mnt/mail/%d/%u' as home, 'maildir:/mnt/mail/%d/%u' as mail, 1000 AS uid, 1000 AS gid, concat('*:bytes=', quota) AS quota_rule FROM mailbox WHERE username = '%u' AND active = '1'
password_query = SELECT username as user, password, '/mnt/mail/%d/%u' as userdb_home, 'maildir:/mnt/mail/%d/%u' as userdb_mail, 1000 as userdb_uid, 1000 as userdb_gid, concat('*:bytes=', quota) AS userdb_quota_rule FROM mailbox WHERE username = '%u' AND active = '1'

В данном случае мы указываем, как Dovecot должен подключаться к базе данных (используя учётную запись Postfix) и что делать с таблицами данных в самой базе. В строке default_pass_scheme можно указать значение PLAIN, если пароль не зашифрован.

Теперь создадим папку с файлами логов Dovecot и передадим права на неё нашему пользователю vmail:

sudo mkdir /var/log/dovecot

sudo cd /var/log/dovecot && touch main.log info.log debug.log lda-errors.log lda-deliver.log lmtp.log

sudo chown -R vmail:dovecot /var/log/dovecot

Обратите внимание, что в данном случае мы создали отдельные папки для основных логов, логов ошибок, отправки почты и т.д. Это помогает разделять события, облегчает поиск ошибок и в дальнейшем поможет защитить сервер при помощи Fail2ban.

Настройка почтового сервера завершена! Теперь нужно запустить обе службы в работу, добавить их в автозагрузку, и можно будет переходить к проверке работы нашего сервера:

sudo systemctl start postfix

sudo systemctl start dovecot

sudo systemctl enable postfix

sudo systemctl enable dovecot

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