Как вам может быть известно, я не очень доверяю SaaS-решениям . Причин тому больше одной. SaaS’ы оставляют за собой право менять Terms of Service в любой момент как им вздумается. SaaS’ы сливают персональные данные. SaaS’ы меняют пользовательский интерфейс и функционал на свое усмотрение. Наконец, если вы используете SaaS’ы от какого-нибудь Google, то однажды получив в них бан за любое нарушение ToS (который, напомню, постоянно меняется), назад вы больше никогда не разбанитесь. В прошлой статье мы решали описанные проблемы, поднимая / перенося на VDS свой блог . Сегодня же мы попробуем разобраться, как с нуля поднять собственный почтовый сервер с TLS, спам-фильтром и списками рассылок.
Примечание: Описанные далее действия производились на Ubuntu Linux 16.04. Однако для других версий Ubuntu, ровно как и для других дистрибутивов Linux, последовательность шагов должна не сильно отличаться.
Подготовка
Примем за рабочую теорию, что у вас есть выделенный сервер (VDS) и указывающее на него доменное имя. Далее в качестве примера я буду использовать домен mail.remontka.com. Если VDS у вас нет, сейчас есть множество VDS-провайдеров, предоставляющих их за смешные деньги. На момент написания этих строк я предпочитаю пользоваться DigitalOcean. При регистрации в DigitalOcean по моей реферальной ссылке вы получаете на счет 10$, что позволит бесплатно пользоваться VDS в течение двух месяцев.
В /etc/hosts прописываем Fully Qualified Domain Name (FQDN):
Ставим необходимые пакеты:
dovecot-core dovecot-imapd dovecot-lmtpd dovecot-mysql
При установке Postfix на вопрос «General type of mail configuration» говорим «Internet Site». На вопрос о доменном имени отвечаем «mail.remontka.com».
Postfix представляет собой Mail Transfer Agent (MTA) , он будет отвечать за отправку и получение почты по SMTP . Dovecot будет предоставлять доступ к письмам по протоколу IMAP (также поддерживается ныне устаревший POP3 ). СУБД MySQL будет использоваться для хранения информации о доменах, пользователях и алиасах. Вместо MySQL с тем же успехом можно взять и MariaDB .
Наполняем базу
В MySQL создаем пользователя и базу данных:
mysql> CREATE DATABASE mail;
mysql> CREATE USER ‘mail’@’localhost’ IDENTIFIED BY ‘pa55w0rd’;
mysql> GRANT ALL ON mail.* TO ‘mail’@’localhost’;
mysql> exit
Заходим под новым пользователем:
Создаем следующие таблицы:
`id` INT NOT NULL AUTO_INCREMENT ,
`name` VARCHAR ( 50 ) NOT NULL ,
PRIMARY KEY ( `id` )
) ENGINE = InnoDB DEFAULT CHARSET = utf8;
CREATE TABLE `virtual_users` (
`id` INT NOT NULL AUTO_INCREMENT ,
`domain_id` INT NOT NULL ,
`password` VARCHAR ( 106 ) NOT NULL ,
`email` VARCHAR ( 120 ) NOT NULL ,
PRIMARY KEY ( `id` ) ,
UNIQUE KEY `email` ( `email` ) ,
FOREIGN KEY ( domain_id ) REFERENCES virtual_domains ( id )
ON DELETE CASCADE
) ENGINE = InnoDB DEFAULT CHARSET = utf8;
CREATE TABLE `virtual_aliases` (
`id` INT NOT NULL AUTO_INCREMENT ,
`domain_id` INT NOT NULL ,
`source` VARCHAR ( 100 ) NOT NULL ,
`destination` VARCHAR ( 100 ) NOT NULL ,
PRIMARY KEY ( `id` ) ,
FOREIGN KEY ( domain_id ) REFERENCES virtual_domains ( id )
ON DELETE CASCADE
) ENGINE = InnoDB DEFAULT CHARSET = utf8;
Вводим информацию о доменах, пользователях и алиасах:
INSERT INTO virtual_users ( `id` , `domain_id` , `email` , `password` )
VALUES ( 1 , 1 , ‘mail@remontka.com’ ,
ENCRYPT ( ‘s3cr3t’ , CONCAT ( ‘$6$’ , SUBSTRING ( SHA ( RAND ( ) ) , — 16 ) ) ) ) ;
INSERT INTO virtual_aliases
( `id` , `domain_id` , `source` , `destination` )
VALUES ( 1 , 1 , ‘postmaster@remontka.com’ , ‘mail@remontka.com’ ) ;
В колонке destination таблицы virtual_aliases можно указывать несколько получателей через запятую, в том числе и на всяких gmail.com. Таким образом, можно создавать списки рассылки. Если алиасы образуют цепочку, например postmaster@remontka.com → mail@remontka.com → somebody@example.org, то это тоже превосходно работает.
Настраиваем Postfix
Правим /etc/postfix/main.cf:
# пока что без TLS
smtpd_use_tls=no
myhostname = mail.remontka.com
mydestination = localhost
virtual_transport = lmtp:unix:private/dovecot-lmtp
# то, что пока нет таких файлов — это ОК
virtual_mailbox_domains = mysql:/etc/postfix/mysql-domains.cf
virtual_mailbox_maps = mysql:/etc/postfix/mysql-users.cf
virtual_alias_maps = mysql:/etc/postfix/mysql-aliases.cf
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
smtpd_sasl_auth_enable = yes
smtpd_recipient_restrictions = permit_sasl_authenticated,⏎
permit_mynetworks,reject_unauth_destination
# увеличиваем максимальный размер письма до 50 Мб
message_size_limit = 52428800
Создаем /etc/postfix/mysql-domains.cf:
user = mail
password = pa55w0rd
dbname = mail
query = SELECT 1 FROM virtual_domains WHERE name=’%s’
…, а также /etc/postfix/mysql-users.cf:
user = mail
password = pa55w0rd
dbname = mail
query = SELECT 1 FROM virtual_users WHERE email=’%s’
…, и наконец /etc/postfix/mysql-aliases.cf:
user = mail
password = pa55w0rd
dbname = mail
query = SELECT destination FROM virtual_aliases WHERE source=’%s’
Поскольку файлы содержат пароль от базы, стоит выставить на них правильные права:
sudo chmod o-rwx / etc / postfix / mysql- * .cf
Перезапускаем Postfix:
Проверяем, что он видит домены, пользователей и алиасы:
1
$ sudo postmap -q remontka.com mysql:/etc/postfix/mysql-domains.cf
1
$ sudo postmap -q postmaster@remontka.com mysql:/etc/postfix/mysql-aliases.cf
mail@remontka.com
Теперь самое время заняться настройкой Dovecot.
Настраиваем Dovecot
Конфигурация Dovecot состоит из нескольких файлов, каждый из которых предстоит немного подправить.
Правим /etc/dovecot/dovecot.conf:
Затем /etc/dovecot/conf.d/10-mail.conf:
mail_privileged_group = mail
В /etc/dovecot/conf.d/10-auth.conf меняем следующее:
# эту строчку нужно закомментировать:
#!include auth-system.conf.ext
!include auth-sql.conf.ext
Далее правим /etc/dovecot/conf.d/auth-sql.conf.ext:
driver = sql
args = /etc/dovecot/dovecot-sql.conf.ext
}
userdb {
driver = static
args = uid=vmail gid=vmail home=/var/mail/vhosts/%d/%n
}
Редактируем /etc/dovecot/dovecot-sql.conf.ext:
connect = host=127.0.0.1 user=mail password=pa55w0rd dbname=mail
default_pass_scheme = SHA512-CRYPT
password_query =
SELECT email as user, password
FROM virtual_users
WHERE email=’%u’;
Правим в /etc/dovecot/conf.d/10-master.conf следующее:
service lmtp {
unix_listener /var/spool/postfix/private/dovecot-lmtp {
mode = 0600
user = postfix
group = postfix
}
}
# …
service auth {
unix_listener /var/spool/postfix/private/auth {
mode = 0666
user = postfix
group = postfix
}
unix_listener auth-userdb {
mode = 0600
user = vmail
}
user = dovecot
}
# …
service auth-worker {
user = vmail
}
Наконец, в файле /etc/dovecot/conf.d/15-lda.conf указываем:
Фух, с конфигами покончено. Теперь для каждого домена говорим:
Создаем пользователя и группу vmail, проставляем права и перезапускаем Dovecot:
sudo useradd -g vmail -u 5000 vmail -d / var / mail
sudo chown -R vmail:vmail / var / mail
sudo chown -R vmail:dovecot / etc / dovecot
sudo chmod -R o-rwx / etc / dovecot
sudo service dovecot restart
Dovecot настроен!
Проверяем
К этому моменту у вас должен крутиться SMTP на порту 25 и IMAP на порту 143. Пока что без TLS и спам-фильтра, но это уже самый настоящий почтовый сервер. Проверяем, что к нему можно подключиться почтовым клиентом. Затем добавляем в DNS MX-запись, указывающую на mail.remontka.com. Обновление зоны занимает какое-то время — обычно около часа, но особо «умные» провайдеры могут кэшировать данные на сутки. То, что зона обновилась, можно увидеть так:
…
;; ANSWER SECTION:
remontka.com. 3599 IN MX 5 mail.remontka.com.
…
После этого проверяем, что почта приходит с какого-нибудь GMail и уходит на него (возможно, попадая при этом в каталог «Спам»), также проверяем работу алиасов. В случае возникновения проблем смотрим в файл /var/log/mail.log — туда пишет логи как Postfix, так и Dovecot.
Дополнение: С недавних пор некоторые почтовые сервисы начали отклонять письма, если у почтового сервера нет reverse DNS и SPF записей. Добавление reverse DNS происходит по-разному у разных VDS-провайдеров. У DigitalOcean нужно назвать VDS доменным именем сервера (например, «mail.remontka.com»). Проверить, что все в порядке, можно командой dig -x 1.2.3.4
. SPF запись включается простым добавлением TXT-записи с содержимым v=spf1 mx -all
. Она говорит, что слать письма с remontka.com могут только сервера, указанные в MX-записях домена. Для проверки выполняем команду dig -t TXT remontka.com
.
Прикручиваем TLS
Поскольку мы не дураки платить за сертификаты, то воспользуемся Let’s Encrypt . После установки certbot’а говорим:
Теперь актуальный ключ и сертификат всегда будут лежать в:
/etc/letsencrypt/live/mail.remontka.com/privkey.pem
Правим /etc/postfix/main.cf:
smtpd_tls_auth_only = yes
smtpd_tls_cert_file=/etc/letsencrypt/live/mail.remontka.com/fullchain.pem
smtpd_tls_key_file=/etc/letsencrypt/live/mail.remontka.com/privkey.pem
# Эта настройка говорит по возможности слать исходящую почту по TLS
# Без нее GMail будет помечать письма как «незашифрованные»
smtp_tls_security_level=may
Затем редактируем /etc/dovecot/conf.d/10-ssl.conf
# символы < перед путями к файлам — не опечатка
ssl_cert = </etc/letsencrypt/live/mail.remontka.com/fullchain.pem
ssl_key = </etc/letsencrypt/live/mail.remontka.com/privkey.pem
Перезапускаем Postfix и Dovecot:
sudo service dovecot restart
Postfix слушает с TLS на порту 25. Dovecot слушает одновременно порты 143 и 993. Меняем настройки почтового клиента и проверяем, что все работает. Мне в случае с Claws Mail в свойствах SMTP пришлось выбрать галочку «Use STARTTLS command to start encryption session».
Но это еще не все! Нужно, чтобы Postfix и Dovecot автоматически перечитывали сертификаты при их обновлении.
В /etc/letsencrypt/cli.ini пишем:
Создаем /etc/letsencrypt/certbot-renew-hook.sh:
set -e
systemctl reload postfix
systemctl reload dovecot
Наконец, говорим:
Скрипт будет автоматически вызываеться при каждом успещном обновлении сертификата и перезапускать демонов.
Настраиваем SpamAssassin
Apache SpamAssassin — это открытое решение для фильтрации спама. Сразу отмечу, что крутизны спам-фильтров GMail’а от него, пожалуй, ожидать не стоит. Тем не менее, по моим наблюдениям, со спамом он борется вполне достойно.
Ставим SpamAssassin и создаем пользователя spamd:
sudo adduser spamd —disabled-login
Правим /etc/default/spamassassin таким образом:
OPTIONS=»—create-prefs —max-children 5 —username spamd ⏎
—helper-home-dir ${SPAMD_HOME} -s ${SPAMD_HOME}spamd.log»
PIDFILE=»${SPAMD_HOME}spamd.pid»
CRON=1
В /etc/spamassassin/local.cf дописываем:
report_safe 0
required_score 5.0
use_bayes 1
use_bayes_rules 1
bayes_auto_learn 1
skip_rbl_checks 0
use_razor2 0
use_dcc 0
use_pyzor 0
Правим /etc/postfix/master.cf:
smtp inet n — y — — smtpd
-o content_filter=spamassassin
# в конец дописываем:
spamassassin unix — n n — — pipe
user=spamd argv=/usr/bin/spamc -f -e
/usr/sbin/sendmail -oi -f ${sender} ${recipient}
Говорим:
sudo service postfix restart
То, что SpamAssasin работает, можно определить по заголовкам X-Spam-Checker-Version и X-Spam-Status во входящих письмах. Письма, помеченные как спам, будут иметь соответствующий Subject, а также заголовок X-Spam-Flag: YES. Для проверки того, что спам определяется, можно послать себе специальное письмо, которое вы найдете в файле:
Но это еще не окончательное решение. Спам все еще приходит, просто он помечен, как спам. Его, конечно, можно отфильтровывать на стороне клиента, но лучше бы делать это на сервере.
В этом нам поможет расширение для Dovecot под названием sieve:
Правим /etc/dovecot/conf.d/20-lmtp.conf:
#mail_plugins = $mail_plugins
mail_plugins = $mail_plugins sieve
}
Редактируем /etc/dovecot/conf.d/90-sieve.conf:
# то, что пока не таких файлов и путей — это ОК
sieve = ~/.dovecot.sieve
sieve_global_dir = /var/lib/dovecot/sieve/
sieve_global_path = /var/lib/dovecot/sieve/default.sieve
sieve_dir = ~/sieve
}
Далее говрим:
Создаем /var/lib/dovecot/sieve/default.sieve:
if header :contains «X-Spam-Flag» «YES» {
fileinto «SPAM»;
}
Чтобы каталог SPAM автоматически создавался, если его еще нет, правим файл /etc/dovecot/conf.d/15-lda.conf:
Завершающие шаги:
sudo sievec / var / lib / dovecot / sieve / default.sieve
sudo service dovecot restart
Ну вот и все, теперь спам будет сыпаться в каталог SPAM. Обратите внимание, что не все почтовые клиенты проверяют появление новых каталогов, если только их прямо об этом не попросить.
Заключение
Несмотря на то, что заметка вышла довольно длинной, в действительности повторить описанные шаги занимает один вечер. За дополнительной информацией обращайтесь к официальным сайтам соответствующих проектов.
Если вы используете на сервере фаервол , обратите внимание, что для корректной работы certbot’а порт 80 должен быть открыт . Если вас интересует прикручивание к почте веб-интерфейса, тут можно порекомендовать RoundCube . В качестве открытого антивируса можно посоветовать ClamAV .
Настройка RoundCube и ClamAV, к сожалению, выходят за рамки данного поста.