Предполагается, что начальная установка и настройка POSTFIX была сделана по статье «Сервер для отправки писем с сайта (debian, sendmail, postfix, SPF, DKIM)».
Все команды необходимо выполнять в консоли от суперпользователя.
Для удобства сделаем алиасы для замены доменов из примеров на ваши значения:
alias my_smtp_host='sed "s/smtp.example.com/ВАШ_ХОСТ/g"'
alias my_mail_domain='sed "s/example.org/ВАШ_ПОЧТОВЫй_ДОМЕН/g"'
ВАШ_ХОСТ
— домен вашего сервера, где будет работать POSTFIX. Если на этом сервере у вас размещён сайт, то можно указать
домен сайта.ВАШ_ПОЧТОВЫй_ДОМЕН
— домен, с которого будет приходить почта (@mydomain.tld).Дальше будут приводиться конфиги с smtp.example.com
и example.org
, а фильтры будут заменять их на правильные значения.
Все команды оптимизированы для копирования и вставки в консоль БЕЗ редактирования (кроме тех мест, где встречается ВАШ_...
,
там нужно вставлять ваши значения).
Разрешаем POSTFIX'у работать на всех адресах вашего сервера:
sed -i 's/^inet_interfaces.*/inet_interfaces = all/' /etc/postfix/main.cf
Чтобы ваш сервер не стал лакомым кусочком для спамеров, добавляем ограничения на пересылку сообщений:
cat >> /etc/postfix/main.cf <<EOF
# Режем спам и неавторизованных пользователей
smtpd_sender_restrictions = permit_sasl_authenticated reject_unknown_sender_domain reject_unknown_reverse_client_hostname reject_unknown_client_hostname
smtpd_recipient_restrictions = permit_sasl_authenticated permit_mynetworks
smtpd_relay_restrictions = permit_sasl_authenticated reject_unauth_destination
EOF
Настройка TLS
Крайне рекомендуется использовать шифрование при передаче данных. Самый простой способ — использовать бесплатные сертификаты Let's Encrypt.
Если у вас ещё нет сертификата, то получить его можно очень просто:
# Устанавливаем certbot для NGINX'а
apt install python3-certbot-nginx
# Добавляем свой домен
sed "s/server_name.*;/server_name $(echo smtp.example.com | my_smtp_host);/;s/ default_server//" \
/etc/nginx/sites-enabled/default \
| grep -v '^#' > /etc/nginx/sites-enabled/my_domain.conf
# Запускаем мастер получения сертификата
certbot
ВАШ_ХОСТ
— домен сервера, где работает POSTFIX.Добавляем конфиг для TLS:
(cat | my_smtp_host >> /etc/postfix/main.cf) <<EOF
# Добавляем поддержку TLS
smtpd_tls_key_file = /etc/letsencrypt/live/smtp.example.com/privkey.pem
smtpd_tls_cert_file = /etc/letsencrypt/live/smtp.example.com/fullchain.pem
smtpd_tls_security_level = may
smtpd_tls_auth_only = yes
smtp_use_tls = yes
tls_high_cipherlist = 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:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!3DES:!MD5:!PSK
tls_ssl_options = NO_RENEGOTIATION
smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
smtpd_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
smtp_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
smtp_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
EOF
И ещё --deploy-hook "service postfix restart"
в файл /etc/cron.d/certbot, чтобы получилось примерно так:
0 */12 * * * root test -x /usr/bin/certbot -a \! -d /run/systemd/system && perl -e 'sleep int(rand(43200))' && certbot -q renew --deploy-hook "service postfix restart"
Перезапускаем postfix:
service postfix restart
Проверяем поддержку TLS:
openssl s_client -starttls smtp -connect localhost:25 | openssl x509 -noout -dates 2>/dev/null | grep notAfter | cut -d'=' -f2
Результат должен быть следующим:
depth=2 O = Digital Signature Trust Co., CN = DST Root CA X3
verify return:1
depth=1 C = US, O = Let's Encrypt, CN = R3
verify return:1
depth=0 CN = ВАШ_ДОМЕН
verify return:1
250 CHUNKING
Apr 25 11:03:31 2021 GMT
SASL — это программный интерфейс, который позволяет в упрощённом режиме идентифицировать пользователей по логину и паролю.
Устанавливаем SASL:
apt install sasl2-bin
Создаём конфиг:
cat > /etc/postfix/sasl/smtpd.conf <<EOF
pwcheck_method: auxprop
auxprop_plugin: sasldb
mech_list: plain login
EOF
Добавляем пользователя в sasldb:
saslpasswd2 -c -u ДОМЕН ПОЛЬЗОВАТЕЛЬ
Утилита запросит у вас пароль, после чего добавит пользователя в базу. ДОМЕН
может быть произвольным, необязательно,
чтобы он совпадал с почтовым доменом.
Включаем авторизацию SASL в POSTFIX:
cat >> /etc/postfix/main.cf <<EOF
# Авторизация SASL
smtpd_sasl_local_domain = \$myhostname
smtpd_sasl_auth_enable = yes
smtpd_sasl_security_options = noanonymous
EOF
sed -i 's~etc/nss_mdns.config"~etc/nss_mdns.config etc/sasldb2"~' /usr/lib/postfix/configure-instance.sh
Так как база sasldb это обычный файл, а SMTPD по умолчанию запускается в chroot, то каждый раз после добавления или изменения пользователя нужно выполнять перезапуск POSTFIX (чтобы нужные файлы скопировались):
service postfix restart
Вместо sasldb можно использовать PAM-аутентификацию, но это сложнее и по умолчанию работает с системными пользователями, что не очень удобно.
Безопасность
Закрываем доступ к папке POSTFIX'а, чтобы не было соблазна украсть базу пользователей sasldb:
chown root:postfix /var/spool/postfix/
chmod 0750 /var/spool/postfix/
Включаем конфиг SMTPS (который уже есть в master.cf, просто закомментирован):
sed -i -E '/#smtps/,/#\S/{s/#(smtps| )/\1/}' /etc/postfix/master.cf
Выключаем SMTP (25 порт), чтобы не принимать запросы от спамеров и других нехороших личностей:
sed -i -E 's/^smtp .*smtpd/#\0/' /etc/postfix/master.cf
Перезапускаем POSTFIX:
service postfix restart
Самый простой способ проверить, это отправить письмо и отслеживать логи:
$ tail /var/log/mail.log -f
Отправляем письмо через консоль
Для начала формируем тело письма:
cat > test.eml <<EOF
From: "test" <test@ВАШ_ПОЧТОВЫЙ_ДОМЕН>
To: "test" <test@example.com>
Subject: Test SMTPS
This is just a test mail
EOF
Отправляем с помощью curl:
curl -qv --ssl-reqd \
--url 'smtps://ВАШ_ХОСТ:465' \
--user 'ПОЛЬЗОВАТЕЛЬ@ДОМЕН:ПАРОЛЬ' \
--mail-from 'ВАШ_ЯЩИК@ВАШ_ПОЧТОВЫЙ_ДОМЕН' \
--mail-rcpt 'test@example.com' \
--upload-file test.eml
ВАШ_ХОСТ
— адрес сервера, где запущен POSTFIX (обязательно нужно указывать домен).ПОЛЬЗОВАТЕЛЬ
, ДОМЕН
, ПАРОЛЬ
— данные, которые были указаны при добавлении пользователя через saslpasswd2.ВАШ_ЯЩИК@ВАШ_ПОЧТОВЫЙ_ДОМЕН
— адрес, к которому у вас есть доступ (на него придёт уведомление о недоставленном письме).Адрес получателя test@example.com
указан только потому, что на домен example.com
письма не уходят, но попадают в логи.
Проверять правильность работы сервера нужно по логу:
Через PHP
Для тестирования я пользовался формой из ApMailer, более подробно описано в статье Отправка писем на PHP через SMTP.
Смотрим логи
Пример работы без ошибок:
Aug 5 15:37:16 aws postfix/smtps/smtpd[2755]: 9D14A1F94: client=unknown[XX.XX.XX.XX], sasl_method=PLAIN, sasl_username=ПОЛЬЗОВАТЕЛЬ@ДОМЕН
Aug 5 15:37:16 aws postfix/cleanup[2757]: 9D14A1F94: message-id=<20210805153716.9D14A1F94@ВАШ_ХОСТ>
Aug 5 15:37:16 aws opendkim[12893]: 9D14A1F94: DKIM-Signature field added (s=key1, d=ВАШ_ПОЧТОВЫЙ_ДОМЕН)
Aug 5 15:37:16 aws postfix/qmgr[2715]: 9D14A1F94: from=<ВАШ_ЯЩИК@ВАШ_ПОЧТОВЫЙ_ДОМЕН>, size=5562, nrcpt=1 (queue active)
Aug 5 15:37:16 aws postfix/smtp[2749]: 9D14A1F94: to=<test@example.com>, relay=none, delay=0.23, delays=0.22/0/0/0, dsn=5.1.0, status=bounced (Domain example.com does not accept mail (nullMX))
Aug 5 15:37:16 aws postfix/cleanup[2757]: C77972033: message-id=<20210805153716.C77972033@ВАШ_ХОСТ>
Aug 5 15:37:16 aws postfix/qmgr[2715]: C77972033: from=<>, size=8060, nrcpt=1 (queue active)
Aug 5 15:37:16 aws postfix/bounce[2758]: 9D14A1F94: sender non-delivery notification: C77972033
Aug 5 15:37:16 aws postfix/qmgr[2715]: 9D14A1F94: removed
Прежде всего интересует строчка, где есть sasl_method=PLAIN, sasl_username=ПОЛЬЗОВАТЕЛЬ@ДОМЕН
, это значит, что
аутентификация имела место быть по логину и паролю, который мы создали. Дальше надо искать DKIM-Signature field added
,
если есть, то цифровая подпись была добавлена. И последнее, что нас интересует, — status=bounced (Domain example.com does not accept mail (nullMX))
,
значит была попытка отправить письмо, но проблема в удалённом сервере.
А вот так выглядит ошибка авторизации, если логин или пароль неверные:
warning: SASL authentication failure: Password verification failed
Если же ошибок нет, попробуйте отправить письмо себе на Google или Яндекс (лучше это сделать через PHP).
Чтобы пресечь любителей подбирать пароли, ставим fail2ban
:
apt install fail2ban
Включаем конфиг для SASL:
cat >> /etc/fail2ban/jail.local <<EOF
[postfix-sasl]
enabled = true
port = smtp,465
filter = postfix[mode=auth]
logpath = /var/log/mail.log
findtime = 60
bantime = 86400
maxretry = 3
EOF
Перезапускаем сервис:
service fail2ban restart
Проверить работу фильтров можно с помощью команд:
fail2ban-client status
fail2ban-client status postfix-sasl