Когда на почтовом сервере «вроде бы включили TLS», а пользователи всё равно видят предупреждения, письма уходят без шифрования или логи забиты verify error — почти всегда проблема в нюансах: какой поток трафика вы шифруете (клиент→сервер или сервер→сервер), какой режим TLS выбран (opportunistic vs enforced), какая цепочка сертификатов отдаётся наружу и как Postfix выбирает сертификат при нескольких доменах (SNI).
Ниже — практический разбор Postfix TLS: входящие SMTP/Submission, исходящий SMTP TLS, корректная цепочка сертификатов (smtp certificate chain), SNI при мультидоменности и системный подход к ошибкам вида verify error. Примеры рассчитаны на типовую установку Postfix в Linux; пути к файлам адаптируйте под ваш дистрибутив.
База: STARTTLS, SMTPS и «465 vs 587» без путаницы
SMTP TLS — это шифрование поверх SMTP. На практике встречаются два режима:
- STARTTLS: соединение начинается без шифрования, затем стороны договариваются о переходе на TLS командой STARTTLS (типично для порта 25 и submission 587).
- Implicit TLS (SMTPS): TLS включён с первых байт соединения (submission 465, если вы его используете).
В Postfix критично различать направления:
- Входящие: Postfix как сервер принимает почту от внешних МТА на 25 и от пользователей/клиентов на 587/465.
- Исходящие: Postfix как клиент подключается к чужим MX и решает, использовать ли TLS и как проверять сертификаты.
Частая ошибка: настроить TLS только на submission (587), но ожидать, что доставка между серверами (порт 25) тоже всегда будет шифроваться. Для межсерверного трафика нужны параметры SMTP-клиента Postfix и (при необходимости) политики TLS для исходящих.
Входящий TLS в Postfix: минимально корректная конфигурация
За входящий TLS отвечают параметры smtpd_*. Практичный «скелет» для main.cf:
# main.cf (фрагмент)
# Сертификат и ключ, которые Postfix отдаёт входящим клиентам
smtpd_tls_cert_file = /etc/ssl/mail/fullchain.pem
smtpd_tls_key_file = /etc/ssl/mail/privkey.pem
# Opportunistic TLS на вход: шифруемся, если клиент поддерживает STARTTLS
smtpd_tls_security_level = may
# Кэш сессий (ускоряет повторные соединения)
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
# Логи по TLS (0..4) — для диагностики временно можно поднять
smtpd_tls_loglevel = 1
# Запрещаем старые протоколы (пример)
smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
smtpd_tls_protocols = !SSLv2, !SSLv3
smtpd_tls_security_level = may — разумный старт для порта 25: вы не ломаете доставку от старых/кривых отправителей, но шифруетесь там, где это возможно.
Submission (587): делаем TLS обязательным
Для порта 587 обычно включают режим «только с TLS» и аутентификацию. Удобнее задавать это в master.cf, чтобы не «пережать» порт 25:
# master.cf (фрагмент)
submission inet n - y - - smtpd
-o syslog_name=postfix/submission
-o smtpd_tls_security_level=encrypt
-o smtpd_sasl_auth_enable=yes
-o smtpd_recipient_restrictions=permit_sasl_authenticated,reject
encrypt означает: без STARTTLS на 587 клиент не пройдёт. Это хороший стандарт для пользовательской отправки.
Если клиенты жалуются на предупреждения о доверии или «неполную цепочку», в 90% случаев проблема не в Postfix как таковом, а в сертификате: неправильный файл в smtpd_tls_cert_file, отсутствуют промежуточные сертификаты или используется сертификат не на то имя. Дальше — как это проверить быстро и без догадок.

Цепочка сертификатов (smtp certificate chain): почему fullchain важнее cert
Для входящих соединений ключевой момент — что вы отдаёте в smtpd_tls_cert_file. Для Postfix самый безопасный и предсказуемый вариант — использовать полную цепочку (сертификат сервера + промежуточные):
- Правильно:
fullchain.pem(leaf + intermediates). - Частая ошибка: указать только leaf-сертификат (например,
cert.pem). Тогда часть клиентов/МТА не достроит цепочку и покажет ошибки проверки.
Быстрая проверка того, что реально отдаёт ваш сервер:
# STARTTLS на 25
openssl s_client -starttls smtp -connect mail.example.com:25 -servername mail.example.com -showcerts
# STARTTLS на 587
openssl s_client -starttls smtp -connect mail.example.com:587 -servername mail.example.com -showcerts
Смотрите блок Certificate chain и количество сертификатов. Если цепочка состоит из одного сертификата, почти наверняка intermediates не отдаются.
Почему verify error иногда «не про ваш входящий TLS»
В логах Postfix слово verify встречается в двух принципиально разных контекстах:
- Входящий (
smtpd): вы как сервер проверяете клиентский сертификат (редко, если вы не делаете mTLS). - Исходящий (
smtp): вы как клиент проверяете сертификат удалённого MX (вот тут verify error встречается чаще всего).
Первый шаг при разборе verify error — понять, какой демон пишет: smtpd или smtp, и для какого направления трафика.
Исходящий SMTP TLS: opportunistic режим и точечное ужесточение
Исторически Postfix настроен так, чтобы письма доставлялись «любой ценой»: если у удалённого MX нет STARTTLS — отправим без TLS; если STARTTLS есть, но сертификат проблемный — доставка может продолжиться (в зависимости от политики). Это и есть opportunistic TLS.
Базовые параметры исходящего TLS (Postfix как SMTP-клиент):
# main.cf (фрагмент)
# Opportunistic: используем TLS, если доступен
smtp_tls_security_level = may
smtp_tls_loglevel = 1
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache
# Доверенные CA (пример для Debian/Ubuntu)
smtp_tls_CAfile = /etc/ssl/certs/ca-certificates.crt
# Ограничим протоколы (пример)
smtp_tls_protocols = !SSLv2, !SSLv3
smtp_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
Если у вас резко включить строгую проверку для всех доменов, вы рискуете доставляемостью: в мире SMTP много легаси. Практичнее ужесточать выборочно.
tls_policy_maps: строгий TLS только там, где он действительно нужен
Если вам нужно требовать TLS (и/или проверку) только для отдельных доменов-получателей (банки, партнёры, внутренние домены), используйте tls_policy_maps. Это позволяет оставить глобально режим may, но «закрутить гайки» адресно.
# main.cf
smtp_tls_policy_maps = hash:/etc/postfix/tls_policy
Пример файла политик:
# /etc/postfix/tls_policy
# домен назначения политика
partner.example encrypt
securemail.example secure
Применение:
postmap /etc/postfix/tls_policy
postfix reload
Упрощённо по смыслу:
encrypt: требовать TLS (если TLS недоступен — не доставлять).secure: требовать TLS и проверять сертификат удалённой стороны максимально строго.
Практика: начинайте с
encryptдля критичных доменов, аsecureвключайте после проверки, что у партнёра корректная цепочка и стабильная TLS-настройка. Иначе получите «самострел» по доставке.
Если параллельно вы настраиваете DNS для домена и доводите почтовую репутацию, полезно свериться с базовыми требованиями к SPF/PTR/доставляемости: настройка SPF и PTR для Postfix.
SNI в Postfix: несколько доменов, несколько сертификатов
Postfix SNI — это два разных сценария:
- Входящий SNI: клиент подключается к вашему SMTP и передаёт имя (SNI), чтобы вы отдали правильный сертификат для конкретного домена.
- Исходящий SNI: ваш Postfix как клиент указывает SNI при подключении к удалённому серверу, чтобы тот выбрал корректный сертификат на многодоменном IP.
Входящий SNI: когда реально нужен
Если у вас один hostname (например, mail.example.com) и один сертификат — SNI не нужен. Но если вы обслуживаете несколько доменов на одном IP и хотите отдавать разные сертификаты, тогда SNI становится обязательным.
В Postfix это реализуется через таблицы SNI и параметры вида smtpd_tls_server_sni_maps (точное имя параметра зависит от версии Postfix). Общая идея одна: «если SNI=имя, отдай cert/key из нужных файлов».
# main.cf (примерный подход; имя параметра проверьте для вашей версии)
smtpd_tls_server_sni_maps = hash:/etc/postfix/sni_map
Таблица:
# /etc/postfix/sni_map
mail.domain1.tld /etc/ssl/domain1/fullchain.pem /etc/ssl/domain1/privkey.pem
mail.domain2.tld /etc/ssl/domain2/fullchain.pem /etc/ssl/domain2/privkey.pem
Применение:
postmap /etc/postfix/sni_map
postfix reload
Важно: в межсерверном SMTP (порт 25) SNI поддерживается не всеми реализациями одинаково. На submission (587/465) поведение обычно предсказуемее.
Исходящий SNI: лечим «не тот сертификат» у получателя
Симптом: вы подключаетесь по TLS к MX получателя, а сервер отдаёт сертификат, который вообще не относится к их домену; при строгой проверке получаете verify error (например, mismatch CN/SAN). Частая причина — удалённый сервер отдаёт «дефолтный» сертификат, потому что клиент не передал SNI.
Проверьте разницу «с SNI» и «без SNI»:
openssl s_client -starttls smtp -connect mx.remote.tld:25 -showcerts
openssl s_client -starttls smtp -connect mx.remote.tld:25 -servername mx.remote.tld -showcerts
Если сертификаты/цепочки отличаются — это SNI-история. Дальше уже разбирайтесь, как именно ваша версия Postfix ведёт себя как SMTP-клиент и что ожидает сторона получателя.

Разбор verify error: типовые причины и быстрые действия
Ниже — частые причины verify error и что проверять в первую очередь.
1) Неполная цепочка или неизвестный CA
Сообщения вроде «unable to get local issuer certificate» чаще всего означают одно из двух: удалённый сервер не отдаёт промежуточные сертификаты, либо на вашей стороне неверно задан источник доверенных CA.
- Проверьте цепочку через
openssl s_client ... -showcerts. - Проверьте, что настроены
smtp_tls_CAfileилиsmtp_tls_CApath(актуально для исходящих). - Для входящих — отдавайте
fullchain.pem, а не только leaf.
2) Несовпадение имени (hostname mismatch)
Сертификат выдан на одно имя, а соединение идёт к другому (или MX указывает на хост с сертификатом для другого имени). В строгих режимах это фатально.
- Сравните имя, к которому вы подключаетесь (MX/host), и SAN/CN сертификата.
- Если это партнёр — попросите привести DNS и сертификаты в соответствие или включить SNI на их стороне.
3) Самоподписанный сертификат
В межсерверном SMTP такое всё ещё встречается. В режиме opportunistic доставка может пройти, но при ужесточении через tls_policy_maps вы получите отказ.
- Для критичных доменов включайте строгую политику только после согласования с получателем.
- Для остальных оставляйте opportunistic TLS, если важна доставляемость.
4) Время и срок действия сертификата
Банально, но регулярно: неверное время на сервере, просроченный сертификат у одной из сторон, или цепочка уже невалидна по времени.
- Проверьте системное время и работу NTP/chrony.
- Проверьте даты в выводе
openssl s_client.
Диагностика: команды и точки наблюдения
Для практической диагностики TLS в Postfix обычно хватает трёх уровней: проверка с клиента, проверка активной конфигурации и чтение логов.
1) Проверяем STARTTLS снаружи
openssl s_client -starttls smtp -connect mail.example.com:25 -servername mail.example.com
openssl s_client -starttls smtp -connect mail.example.com:587 -servername mail.example.com
2) Смотрим активные параметры Postfix
postconf -n | grep -E 'tls|sni|policy|CA'
3) Поднимаем детализацию логов на время расследования
Для точечной диагностики временно поднимите smtpd_tls_loglevel и smtp_tls_loglevel до 2–3, воспроизведите проблему и верните значения обратно. Иначе легко утонуть в объёме логов.
Если параллельно вы защищаете почтовик от перебора паролей на submission, пригодится отдельная настройка: Fail2ban для Postfix и Dovecot.
Чек-лист: «TLS включили, но проблемы остались»
- Проверьте входящий STARTTLS на 25/587 через
openssl s_clientи убедитесь, что отдаётся полная цепочка. - Проверьте, что на 587 включён
smtpd_tls_security_level=encrypt, если вы хотите запретить аутентификацию без TLS. - Проверьте исходящую политику:
smtp_tls_security_level, а такжеsmtp_tls_CAfileилиsmtp_tls_CApath. - Если ошибки только с отдельными доменами — вынесите их в
tls_policy_mapsи решайте точечно. - При подозрении на SNI — сравните вывод
openssl s_clientс-servernameи без него.
В результате у вас получится предсказуемая схема: порт 25 остаётся совместимым (may), submission становится строгим (encrypt), цепочка сертификатов корректна (через fullchain.pem), а «строгий TLS» для партнёров включается точечно через tls_policy_maps.


