Хардненинг submission 587 и smtps 465: обязательный TLS, запрет plaintext-AUTH и боевые конфиги MSA
Порт 25 давно закрыт для клиентов, но 587 и 465 у большинства провайдеров — проходной двор: STARTTLS сбрасывается в открытый текст, AUTH разрешён до TLS, RC4 и 3DES всё ещё включены «для совместимости». Разбираем три конкретные дыры MSA и закрываем их живыми конфигами Postfix + Dovecot, проверяя результат через openssl и testssl.sh.
EvilMail Team24 июля 2026 г.13 мин чтения
Три реальных дыры на 587 и 465, а не «включите шифрование»
Порт 25 для клиентов закрыт почти у всех — провайдеры давно режут исходящий 25 и оставляют его только для MX-to-MX. А submission-порты 587 и 465 у большинства настроены по принципу «работает — и ладно». Проблема в том, что это ворота, за которыми лежит ваш SASL-логин, а вместе с ним — право рассылать почту от вашего домена и с вашего IP. Скомпрометировали креды на 587 — и через пару часов ваш адрес в Spamhaus CSS/XBL, а доставляемость восстанавливается днями.
Дыр на этих портах ровно три, и все три встречаются в проде постоянно:
STARTTLS-stripping + plaintext-AUTH. MITM вырезает строку 250-STARTTLS из ответа на EHLO. Клиент с оппортунистической настройкой видит, что «сервер не умеет TLS», и отправляет AUTH LOGIN с логином и паролем в base64 открытым текстом. cGFzc3dvcmQ=
Хардненинг портов 587 и 465: обязательный TLS и запрет plaintext-AUTH | evilmail.pro — EvilMail Blog
— это не шифрование, это кодировка.
Слабые протоколы и шифры. TLS 1.0/1.1, RC4, 3DES, экспортные наборы всё ещё торчат «для старых клиентов из 2011 года». Один POODLE/BEAST-совместимый шифр обесценивает весь TLS.
Отсутствие изоляции submission от MX и лимитов. Один и тот же smtpd обслуживает и входящую почту, и клиентский релей — без раздельных политик, без rate-limit, без fail2ban на брутфорс SASL.
Базовый принцип на весь материал: 465 (implicit TLS, RFC 8314) — основной порт, 587 (explicit STARTTLS с обязательным TLS) — для совместимости. Нужны оба, но настроены они должны быть так, чтобы незашифрованной фазы либо не было вовсе, либо она немедленно упиралась в 530.
Модель угроз MSA: что именно уводят
MSA (Message Submission Agent, RFC 6409) отличается от MX двумя вещами. Первое — аутентификация обязательна: на submission нет анонимного релея, каждое письмо привязано к учётке. Второе — релей разрешён только своим, аутентифицированным. Отсюда и главный риск: украденный SASL-логин = массовая рассылка спама с вашего IP. Не «утечка одного ящика», а компрометация всей отправляющей репутации.
Downgrade-атака на 587 пошагово:
1.Клиент открывает TCP-соединение и шлёт EHLO.
2.MITM (или скомпрометированный Wi-Fi, или прозрачный прокси) перехватывает ответ сервера и вырезает из него 250-STARTTLS.
3.Клиент, настроенный на opportunistic TLS (may), не видит capability и решает, что апгрейд невозможен.
4.Клиент отправляет AUTH LOGIN — и логин с паролем уходят в открытом виде прямо в руки атакующему.
Отдельная категория жертв — legacy-клиенты и «автонастройка», которая ищет первый попавшийся порт с AUTH. Если такой клиент найдёт открытый 587 без принудительного TLS, он аутентифицируется в открытую и даже не заметит.
RFC 8314: почему implicit TLS снова канон
Историческая ирония: порт 465 когда-то был назначен под SMTPS, потом IETF его deprecated в пользу STARTTLS на 587, а в 2018 году RFC 8314 развернул политику обратно и сделал implicit TLS рекомендуемым для submission. Причина — ровно та атака выше.
Разница на уровне рукопожатия принципиальная. На 465 TLS поднимается сразу на сокете: первый же байт после TCP-хендшейка — это ClientHello. Незашифрованной SMTP-фазы не существует, стрипить нечего. На 587 соединение открывается в открытом виде, идёт EHLO, и только потом апгрейд через STARTTLS — и вот это окно между EHLO и завершённым TLS-рукопожатием есть точка входа для MITM.
Практический вывод: 465 архитектурно устойчивее, поэтому он основной. Но 587 держим тоже — многие библиотеки и MUA по-прежнему предполагают именно его — просто настраиваем так, что без TLS там ничего не работает.
Postfix master.cf: разделяем submission и smtps
Оба сервиса объявляются в /etc/postfix/master.cf с per-service override через -o. Ключевой момент — разные `syslog_name`, чтобы потом грепать submission-трафик отдельно от MX.
Здесь работает связка из двух директив. smtpd_tls_security_level=encrypt на 587 означает обязательный STARTTLS — это не may. Разница критическая: may (opportunistic) разрешает продолжить без TLS и именно поэтому стрипится; encrypt требует успешного TLS, иначе сессия обрывается. На 465 роль encrypt выполняет smtpd_tls_wrappermode=yes — TLS оборачивает сокет с нулевого байта.
smtpd_tls_auth_only=yes добавляет второй замок: AUTH вообще не анонсируется и не принимается до завершённого TLS-рукопожатия. Даже если клиент попробует AUTH LOGIN в открытой фазе, Postfix ответит 530 5.7.0 Must issue a STARTTLS command first. Вместе encrypt + auth_only закрывают plaintext-AUTH полностью — стрипить STARTTLS бессмысленно, потому что без него не будет ни релея, ни даже возможности залогиниться.
permit_sasl_authenticated,reject в client_restrictions и relay_restrictions гарантирует, что submission обслуживает только своих: нет валидного SASL — соединение отклонено, анонимный релей невозможен.
TLS-политика: протоколы и шифры без компромиссов
Транспорт настраивается в main.cf. Цель — TLS 1.2 как минимум (лучше 1.3), никаких RC4/3DES/экспортных наборов, ECDHE для forward secrecy:
smtpd_tls_security_level = may в глобальном main.cf — это про входящий MX (там оппортунистический TLS оправдан, иначе часть легитимной почты просто не дойдёт). Жёсткий encrypt/wrappermode живёт в per-service override submission/smtps, где клиент обязан уметь TLS. Не путайте два уровня — это частая ошибка.
Директива smtpd_tls_chain_files (Postfix 3.x) заменяет старую пару key_file/cert_file одним списком: сначала приватный ключ, затем цепочка. tls_preempt_cipherlist = yes заставляет сервер выбирать шифр по своему списку, а не по клиентскому — иначе слабый клиент навяжет слабый набор. TLS-компрессия в современных сборках OpenSSL отключена глобально, что закрывает CRIME.
Dovecot SASL: аутентификация только поверх TLS
Postfix делегирует проверку паролей Dovecot через unix-сокет. В 10-auth.conf:
disable_plaintext_auth = yes — это страховка на стороне SASL-провайдера: даже если что-то мимо Postfix попробует PLAIN/LOGIN без TLS, Dovecot откажет. Механизмы plain login безопасны ровно потому, что они допускаются только внутри уже поднятого TLS.
Сокет для Postfix в 10-master.conf:
text
service auth {
unix_listener /var/spool/postfix/private/auth {
mode = 0660
user = postfix
group = postfix
}
}
ssl = required
ssl = required в 10-ssl.conf запрещает IMAP/POP-логины без шифрования. По схеме паролей: в проде не держите PLAIN-схему для новых учёток — используйте ARGON2ID или BCRYPT в passdb. Если исторически схема PLAIN (uid/gid 5000 в нашей инсталляции), миграцию делают ленивым апгрейдом хеша при успешном логине, а не разовым сбросом всех паролей.
Проверка: openssl, testssl.sh, живой downgrade-тест
Конфиг не считается рабочим, пока не проверен снаружи. Три обязательные пробы.
Implicit TLS на 465 — рукопожатие обязано начаться немедленно, до любого SMTP-баннера:
bash
openssl s_client -connect mail.evilmail.pro:465 -quiet
# Ожидаем: сразу Certificate chain, Protocol: TLSv1.3, затем 220 баннер
STARTTLS-апгрейд на 587:
bash
openssl s_client -starttls smtp -connect mail.evilmail.pro:587
# В EHLO-ответе должен быть 250-STARTTLS; после апгрейда — TLSv1.2/1.3
Живой тест на plaintext-AUTH — самое важное. Подключаемся телнетом и пробуем аутентифицироваться до STARTTLS:
bash
$ nc mail.evilmail.pro 587
220 mail.evilmail.pro ESMTP Postfix
EHLO test
250-mail.evilmail.pro
250-PIPELINING
250-SIZE 52428800
250-STARTTLS
250 8BITMIME
AUTH LOGIN
530 5.7.0 Must issue a STARTTLS command first
Строка 530 5.7.0 — это то, ради чего всё затевалось. Если вместо неё пришёл 334 VXNlcm5hbWU6 (запрос логина) — у вас дыра, smtpd_tls_auth_only не сработал.
mode: enforce заставляет отправляющие серверы отклонять доставку, если TLS не поднялся или сертификат не совпал. TLS-RPT (_smtp._tls) присылает агрегированные отчёты о неудачных рукопожатиях — так вы увидите реальные downgrade-попытки в цифрах.
DANE — запись TLSA под DNSSEC, применяется к MX (входящий 25), не к submission:
text
_25._tcp.mail.evilmail.pro. IN TLSA 3 1 1 <sha256-хеш-ключа>
Для submission эти механизмы вторичны — там главное защита от брутфорса SASL. fail2ban с jail postfix-sasl: фильтр по SASL LOGIN authentication failed, порог 3–5 фейлов, findtime = 600, bantime от часа. Плюс встроенные лимиты Postfix:
client_restrictions=permit_sasl_authenticated,reject на submission и smtps
Сертификат Let's Encrypt актуален, chain_files содержит полную цепочку
Живой тест: AUTH LOGIN до STARTTLS даёт 530 5.7.0
fail2ban jail postfix-sasl активен, rate-limit включён
MTA-STS mode: enforce и TLS-RPT публикуются
testssl.sh показывает грейд A на 587 и 465
Последнее — перепроверяйте после каждого обновления Postfix, OpenSSL и продления сертификата: testssl.sh --starttls smtp mail.evilmail.pro:587 должен оставаться зелёным. Молчаливая деградация шифров после апгрейда пакетов — как раз то, что находят через месяц, когда уже поздно.