Электронная почта до сих пор держит инфраструктуру компаний: уведомления, регистрации, переписку. Задача инженера - поднять MTA, который надёжно принимает и отправляет письма, не превращаясь при этом в открытый релей для спамеров. В этом уроке разбираем роль MTA и путь письма по протоколу SMTP, два главных конфига Postfix (main.cf и master.cf), ключевые параметры (myhostname, mydestination, mynetworks), виртуальные домены и алиасы, ретрансляцию через провайдера, работу с очередью (postqueue, postsuper), базовую защиту от спама и инструмент postconf.

Как это работает
MTA (Mail Transfer Agent) - это сервер, который перевозит письма между хостами по протоколу SMTP. Путь письма такой: почтовый клиент (MUA) сдаёт письмо своему MTA, тот по DNS находит MX-запись домена получателя, соединяется с принимающим MTA на порту 25 и передаёт письмо. На приёмной стороне MTA кладёт письмо в локальный почтовый ящик через агент доставки (MDA, например Dovecot или procmail), а пользователь забирает его по IMAP/POP3. Postfix играет роль MTA: он и отправляет, и принимает SMTP.
Внутри Postfix - не один процесс, а семейство демонов под управлением мастер-процесса master. Каждый кусок работы делает отдельный демон: smtpd принимает входящие соединения, smtp отправляет наружу, cleanup переписывает заголовки и кладёт письмо в очередь, qmgr (queue manager) решает, что и когда доставлять, local доставляет в локальные ящики. Такая раздробленность - намеренная архитектура безопасности: демоны работают под непривилегированным пользователем postfix, общаются через очередь на диске, и компрометация одного не открывает всю систему.
Конфигурация живёт в двух файлах. main.cf задаёт параметры (кто мы, какие домены принимаем, кому доверяем) в формате имя = значение. master.cf описывает сами демоны и сервисы: какой процесс на каком порту/сокете слушает, под каким пользователем, с какими ограничениями. Грубо: main.cf - это что делать, master.cf - кто это делает.
Ключевые параметры main.cf. myhostname - полное FQDN-имя хоста (mail.example.com), оно же подставляется в SMTP-приветствие и Message-ID. mydomain обычно отрезает первую часть от myhostname. myorigin - домен, который дописывается к письмам от локальных пользователей. mydestination - список доменов, которые Postfix считает СВОИМИ и доставляет локально (если домена тут нет и это не релей-получатель, письмо отвергается или релеится). mynetworks - доверенные сети (CIDR), которым разрешено слать письма наружу без аутентификации. Вот тут и кроется главная опасность: слишком широкий mynetworks (например 0.0.0.0/0) превращает сервер в открытый релей, и его за час найдут спамеры.
Виртуальные домены - это домены, которые сервер обслуживает, но без системных Unix-аккаунтов. Их два режима. Виртуальные алиасы (virtual_alias_maps) перенаправляют адрес на другой адрес - удобно, когда домен только пересылает почту. Виртуальная доставка (virtual_mailbox_domains + virtual_mailbox_maps) кладёт письма в файлы-ящики, привязанные не к Unix-юзерам, а к записям в карте (часто в БД). Локальные алиасы для системных пользователей задаются в /etc/aliases (например root: admin@example.com), и после правки обязателен newaliases, который компилирует текст в бинарную хеш-карту.
Команды и примеры
Установка различается по семействам. Конфиги в обоих случаях лежат в /etc/postfix/.
Код: Выделить всё
# Debian 13 / Ubuntu 24.04
apt install postfix
# во время установки выбирается профиль (Internet Site / Satellite)
# RHEL 10 / Fedora 41+
dnf install postfix
systemctl enable --now postfix
Код: Выделить всё
postconf myhostname mydestination mynetworks # показать конкретные
postconf -d mydestination # значение ПО УМОЛЧАНИЮ
postconf -n # только НЕдефолтные (что вы реально настроили)
postconf -e 'myhostname = mail.example.com' # безопасно записать в main.cf
postconf -M # содержимое master.cf
Код: Выделить всё
myhostname = mail.example.com
mydomain = example.com
myorigin = $mydomain
inet_interfaces = all
inet_protocols = ipv4
mydestination = $myhostname, localhost.$mydomain, localhost, $mydomain
mynetworks = 127.0.0.0/8, 192.168.10.0/24
home_mailbox = Maildir/
Код: Выделить всё
# main.cf
virtual_alias_domains = forward.example.com
virtual_alias_maps = hash:/etc/postfix/virtual
# /etc/postfix/virtual
info@forward.example.com admin@example.com
sales@forward.example.com bob@example.com
Код: Выделить всё
postmap /etc/postfix/virtual # создаёт virtual.db (hash-карта)
newaliases # компилирует /etc/aliases -> aliases.db
postfix reload # перечитать конфиг без обрыва соединений
Код: Выделить всё
# main.cf
relayhost = [smtp.provider.net]:587
smtp_sasl_auth_enable = yes
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
smtp_sasl_security_options = noanonymous
smtp_tls_security_level = encrypt
Код: Выделить всё
postqueue -p # показать очередь (псевдоним mailq)
postqueue -j # то же в JSON (удобно скриптовать)
postqueue -f # flush: попытаться доставить всё прямо сейчас
postsuper -d ALL # удалить ВСЕ письма из очереди
postsuper -d <QUEUEID> # удалить одно конкретное
postsuper -r ALL # перевести в активную очередь (requeue)
postsuper -h <id> # hold: придержать письмо
postcat -q <QUEUEID> # посмотреть содержимое письма в очереди
Код: Выделить всё
# main.cf
smtpd_helo_required = yes
smtpd_recipient_restrictions =
permit_mynetworks,
permit_sasl_authenticated,
reject_unauth_destination,
reject_rbl_client zen.spamhaus.org
- Открытый релей. Поставили mynetworks слишком широко или забыли reject_unauth_destination - сервер шлёт чужой спам, IP попадает в блоклисты, своя почта перестаёт доходить. Проверяйте postconf -n и тестируйте релей снаружи.
- Забыли postmap/newaliases после правки текстовой карты. Postfix читает скомпилированный .db, а не текст - изменения не применятся, ошибок не будет.
- Путают postfix reload и restart с newaliases. reload перечитывает main.cf/master.cf, но НЕ перекомпилирует карты - для карт нужен postmap.
- Домен в mydestination И одновременно в virtual_mailbox_domains - Postfix ругается на конфликт, доставка ломается. Домен должен быть в чём-то одном.
- inet_interfaces = localhost (дефолт во многих сборках) - сервер слушает только loopback и не принимает внешнюю почту. Для приёма нужно all или конкретный IP.
- relayhost без квадратных скобок заставляет искать MX у самого smarthost - часто не то, что нужно. Скобки [host] отключают MX-резолв.
- Письма копятся в очереди, а смотрят только в логи. Сначала postqueue -p и postcat - причина (deferred) видна прямо там.
- Установите Postfix и через postconf -e задайте myhostname, mydomain, myorigin = $mydomain и mydestination со своим доменом.
- Ограничьте mynetworks только 127.0.0.0/8 и своей подсетью; выполните postconf -n и убедитесь, что 0.0.0.0/0 там нет.
- Создайте в /etc/aliases строку для root (root: youruser), выполните newaliases, отправьте письмо root и проверьте доставку.
- Заведите файл /etc/postfix/virtual с алиасом домена, выполните postmap и postfix reload.
- Остановите доставку (например, временно поднимите defer) и отправьте пару писем; посмотрите их через postqueue -p и postcat -q.
- Освободите очередь через postqueue -f, затем удалите оставшееся через postsuper -d ALL.
- Добавьте reject_unauth_destination в smtpd_recipient_restrictions и снаружи попробуйте релей на чужой домен - убедитесь, что получаете отказ.
- Чем отличается роль MTA от MDA и MUA, и на каком порту MTA принимает входящую почту по умолчанию?
- Что задают параметры mydestination и mynetworks и почему ошибка в mynetworks опаснее всего?
- За что отвечают main.cf и master.cf и какой инструмент безопасно правит main.cf?
- В чём разница между virtual_alias_maps и virtual_mailbox_domains?
- Зачем нужны postmap и newaliases и чем они отличаются от postfix reload?
- Какое правило в smtpd_recipient_restrictions закрывает сервер от использования как открытый релей?