Двенадцать сборок

Самописный почтовый сервер, письма которого реально попадают во входящие

Postfix, Dovecot и rspamd на одном инстансе, с корректно настроенными SPF, DKIM и DMARC, и шагом проверки, который читает заголовки принимающей стороны.

Что мы создаём

Полноценный почтовый сервер для одного домена: Postfix для транспорта, Dovecot для IMAP и локальной доставки, rspamd для фильтрации и подписи DKIM, и три DNS-записи, которые определяют, попадёт ли ваше письмо у крупных получателей во входящие или в папку, которую никто не открывает. Он отправляет, принимает, аутентифицирует и не является открытым релеем.

Совет поднять собственный почтовый сервер немоден, и в основном по делу. Сложность не в программном обеспечении, а в доставляемости. Ошибитесь в DNS — и самый тщательно настроенный Postfix в мире отправит сообщения в пустоту.

Перед началом работы

  • Инстанс R-8 или больше. Фильтрация требует много CPU, и rspamd с радостью использует все ядра, которые вы ему дадите, во время спам-волны.
  • Домен, DNS которого вы контролируете, и терпение для распространения записей.
  • Обратный DNS на адресе инстанса, указывающий на ваш почтовый хостнейм. Он редактируется в панели и обязателен: получатели отклоняют отправителей, чьи адреса не резолвятся.
  • Один тикет в поддержку с вопросом, открыт ли исходящий порт 25 на вашем инстансе. Спросите до начала работы, а не после.
  • mail.example.com повсюду. Подставьте свои значения.

1. Хостнейм и DNS

hostnamectl set-hostname mail.example.com
apt update && apt full-upgrade -y

Опубликуйте эти записи сейчас, потому что для шага с сертификатом нужна A-запись, а для шага с подписью нужно куда-то поместить ключ. Значения в таблице — это то, что делает каждая запись, а не то, что вставлять.

ЗаписьИмяСодержимое
A / AAAAmailАдреса инстанса из панели
MX@10 mail.example.com.
TXT@v=spf1 mx -all
TXT_dmarcv=DMARC1; p=none; rua=mailto:[email protected]; adkim=s; aspf=s
PTRадрес инстансаmail.example.com — задаётся в панели

Запись SPF говорит: письма отправляет мой MX, всё остальное — подделка. Жёсткий отказ (hard fail), а не мягкий (soft fail), потому что ~all приглашает получателей принять собственное решение, а их решение не будет благосклонным. DMARC начинается с p=none, чтобы вы в течение недели собирали отчёты до того, как что-то начнёт отклоняться от вашего имени.

2. Сертификаты

apt install -y certbot
certbot certonly --standalone -d mail.example.com

На порту 80 ещё ничего не слушает, поэтому автономный режим — самый простой путь. Хуки обновления появятся в конце, когда уже будут существовать демоны для перезагрузки.

3. Postfix

DEBIAN_FRONTEND=noninteractive apt install -y postfix postfix-pcre dovecot-imapd dovecot-lmtpd rspamd redis-server

Теперь задайте конфигурацию транспорта. Каждая строка ниже продумана; postconf записывает их на место, так что редактор не нужен и ошибиться негде:

postconf -e "myhostname = mail.example.com"
postconf -e "mydestination = localhost"
postconf -e "smtpd_banner = \$myhostname ESMTP"
postconf -e "inet_interfaces = all"
postconf -e "smtpd_tls_cert_file = /etc/letsencrypt/live/mail.example.com/fullchain.pem"
postconf -e "smtpd_tls_key_file = /etc/letsencrypt/live/mail.example.com/privkey.pem"
postconf -e "smtpd_tls_security_level = may"
postconf -e "smtp_tls_security_level = dane"
postconf -e "smtpd_tls_mandatory_protocols = >=TLSv1.2"
postconf -e "smtpd_sasl_type = dovecot"
postconf -e "smtpd_sasl_path = private/auth"
postconf -e "smtpd_relay_restrictions = permit_mynetworks permit_sasl_authenticated reject_unauth_destination"
postconf -e "smtpd_recipient_restrictions = permit_mynetworks permit_sasl_authenticated reject_unknown_recipient_domain reject_unauth_destination"
postconf -e "virtual_transport = lmtp:unix:private/dovecot-lmtp"
postconf -e "virtual_mailbox_domains = example.com"
postconf -e "smtpd_milters = inet:127.0.0.1:11332"
postconf -e "non_smtpd_milters = inet:127.0.0.1:11332"
postconf -e "milter_default_action = accept"

Самая важная строка — smtpd_relay_restrictions. Она заканчивается на reject_unauth_destination, что не позволяет всему интернету использовать вашу машину для отправки почты. Открытое реле приведёт к внесению в чёрные списки в течение нескольких часов, а также является нарушением правил допустимого использования.

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

postconf -M submission/inet="submission inet n - y - - smtpd"
postconf -P "submission/inet/syslog_name=postfix/submission"
postconf -P "submission/inet/smtpd_tls_security_level=encrypt"
postconf -P "submission/inet/smtpd_sasl_auth_enable=yes"
postconf -P "submission/inet/smtpd_client_restrictions=permit_sasl_authenticated,reject"

4. Dovecot

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

groupadd -g 5000 vmail
useradd -g vmail -u 5000 -d /var/vmail -m vmail
install -d -o vmail -g vmail -m 700 /var/vmail/example.com

Запишите /etc/dovecot/conf.d/99-local.conf:

mail_location = maildir:/var/vmail/%d/%n
mail_uid = vmail
mail_gid = vmail
ssl = required
ssl_cert = </etc/letsencrypt/live/mail.example.com/fullchain.pem
ssl_key = </etc/letsencrypt/live/mail.example.com/privkey.pem
ssl_min_protocol = TLSv1.2
auth_mechanisms = plain login
disable_plaintext_auth = yes

passdb {
  driver = passwd-file
  args = scheme=ARGON2ID username_format=%u /etc/dovecot/users
}
userdb {
  driver = static
  args = uid=vmail gid=vmail home=/var/vmail/%d/%n
}

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 = 0660
    user = postfix
    group = postfix
  }
}

Создайте почтовый ящик. Команда запрашивает пароль дважды и сохраняет хэш, а не сам пароль:

echo -n "[email protected]:" >> /etc/dovecot/users
doveadm pw -s ARGON2ID >> /etc/dovecot/users
chmod 640 /etc/dovecot/users
chgrp dovecot /etc/dovecot/users

5. rspamd и DKIM

Сгенерируйте ключ подписи, затем опубликуйте открытую часть:

install -d -o _rspamd -g _rspamd -m 750 /var/lib/rspamd/dkim
rspamadm dkim_keygen -s mail -b 2048 -d example.com -k /var/lib/rspamd/dkim/example.com.mail.key
chown _rspamd:_rspamd /var/lib/rspamd/dkim/example.com.mail.key
chmod 400 /var/lib/rspamd/dkim/example.com.mail.key

Эта команда выводит DNS-запись на стандартный вывод. Опубликуйте её как TXT-запись на mail._domainkey.example.com, точно так, как она выведена, соединив сегменты в кавычках так, как требует ваш DNS-провайдер. Затем сообщите rspamd, где находится ключ, в /etc/rspamd/local.d/dkim_signing.conf:

path = "/var/lib/rspamd/dkim/$domain.$selector.key";
selector = "mail";
allow_username_mismatch = true;
use_domain = "header";
sign_authenticated = true;
sign_local = true;

Подключите milter и задайте пароль для веб-интерфейса:

echo "bind_socket = \"127.0.0.1:11332\";" > /etc/rspamd/local.d/worker-proxy.inc
rspamadm pw

Вставьте полученный хэш в /etc/rspamd/local.d/worker-controller.inc как password = "...". Доступ к интерфейсу — через SSH-туннель, не открывайте порт 11334 наружу.

6. Запуск всего

systemctl enable --now redis-server rspamd dovecot postfix
postfix check
systemctl --no-pager --failed

Добавьте хук обновления сертификата, чтобы новый сертификат добрался до обоих демонов:

echo "systemctl reload postfix dovecot" > /etc/letsencrypt/renewal-hooks/deploy/reload-mail.sh
chmod +x /etc/letsencrypt/renewal-hooks/deploy/reload-mail.sh

Проверка

Три теста. Первый — локальный, второй — тот, который важен, третий — тот, который уберегает вас от блокировок.

echo | openssl s_client -starttls smtp -connect mail.example.com:25 -servername mail.example.com 2>/dev/null | grep -E "subject=|Verify return"

Затем отправьте сообщение с вашего нового сервера на ваш ящик на крупном веб-почтовом провайдере, откройте полученное сообщение и прочитайте его исходные заголовки. Ищите одну строку:

Authentication-Results: mx.receiver.example;
  dkim=pass [email protected];
  spf=pass smtp.mailfrom=example.com;
  dmarc=pass (p=NONE) header.from=example.com

Три успешных проверки — и готово. dkim=none означает, что rspamd не подписывает, поэтому проверьте rspamadm configdump dkim_signing. spf=fail почти всегда означает, что сообщение ушло через IPv6, в то время как ваша запись SPF покрывает только адрес MX версии 4.

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

apt install -y swaks
swaks --to [email protected] --from [email protected] --server mail.example.com

Правильный результат — отказ на этапе получателя: 554 5.7.1 Relay access denied. Всё остальное означает, что вы настроили машину, которую будут использовать в злонамеренных целях уже в течение дня; остановитесь и перечитайте шаг три.

Дальнейшие шаги

Оставьте DMARC на p=none на неделю и читайте агрегированные отчёты. Как только они покажут, что только ваш сервер подписывает вашу почту, переходите на p=quarantine, а через две недели — на p=reject. Попутно настройте резервное копирование за пределами узла для /var/vmail, потому что почта — это то, второй копии чего у пользователей никогда нет, а наш аддон резервного копирования записывает данные на другой сайт, нежели инстанс.

Готовы, когда вы готовы

Выберите город. Выберите размер. Оплатите монетой.

Никаких форм о том, кто вы, никакого ожидания одобрения человеком, никаких звонков для проверки. Счёт оплачен — и учётные данные приходят на почту.