Понадобилось сделать Postfix с SMTP аутентификацией. Раньше не настраивал, перерыл кучу статей. Очень сумбурно всё изложено, поэтому пришлось написать свой вариант. Если кто-то знает хорошую инструкцию по данному вопросу без лишней воды — пишите в комментариях.
Я хотел реализовать обычный рассыльщик писем без приёма почты. Никаких POP3 и IMAP, чистый SMTP. При этом не хотелось устанавливать какие-то лишние компоненты. Я уверен, что задачу можно было выполнить проще, кто подскажет — молодец.
Окружение
Операционная система
Используем операционную систему Ubuntu Server 20.04 LTS. Если кому-то нужна инструкция по установке, то вот ссылка:
Установка Ubuntu Server 20.04 LTS на виртуальную машину VMware ESXi 6.7
Итак, ОС установлена.
lsb_release -a
Почта
Почтовый сервер Postfix.
Аутентификация SMTP
Для аутентификации использую Cyrus. Пользователей SMTP будем хранить в локальной базе sasldb (Cyrus SASL Berkeley DB database).
Домен
Я создам для тестирования отдельный домен третьего уровня testsender.internet-lab.ru, настрою DNS и буду слать письма с адреса info@testsender.internet-lab.ru. Пароль пользователя "888776". После выхода статьи пароль сменю :)
Настройка DNS
Добавим домен testsender.internet-lab.ru и настроим почту. Добавляем A запись домена. Я использую тот же IP, что у основного домена.
Postfix будет представляться как postfix.testsender.internet-lab.ru, добавим A запись.
Настроим SPF и DMARC, чтобы письма можно было отправлять со своего IP адреса.
Установка Postfix
Установим Postfix самым простым способом из репозитория без настроек.
apt-get update
apt-get install postfix
Общий тип почтовой настройки выбираем "Без настройки":
OK.
dpkg -l | grep postfix
Установлен postfix версии 3.4.10.
Настройка Postfix
Создаём главный файл настроек /etc/postfix/main.cf:
myorigin = postfix.testsender.internet-lab.ru
myhostname = postfix.testsender.internet-lab.ru
mydomain = testsender.internet-lab.ru
smtpd_banner = postfix.testsender.internet-lab.ru
biff = no
alias_maps = hash:/etc/postfix/aliases
mynetworks = 127.0.0.0/8 192.168.1.0/24 [::ffff:127.0.0.0]/104 [::1]/128
message_size_limit = 35840000
mailbox_size_limit = 0
recipient_delimiter = +
inet_interfaces = all
masquerade_classes = envelope_sender, header_sender
relay_domains = testsender.internet-lab.ru
maximal_queue_lifetime = 5d
compatibility_level = 2
Пока ничего особо не настроено, почтовик обслуживает один домен testsender.internet-lab.ru. Представляется как postfix.testsender.internet-lab.ru, 192.168.1.0/24 — моя локальная сеть, из которой я буду отправлять в postfix письма. После настройки SMTP аутентификации отправлять письма можно будет не только из этой сети.
Создаём файл /etc/postfix/aliases:
postmaster:root
Выполняем:
postalias /etc/postfix/aliases
Перезагружаем Postfix.
service postfix restart
Проверка отправки письма
Из подсети 192.168.1.0/24 пытаемся отправить письмо с помощью telnet по 25 порту.
telnet 192.168.1.13 25
ehlo localhost
Отправляем письмо без аутентификации.
Письмо ушло в postfix. Смотрим логи postfix:
status=sent, письмо отправлено. Уже хорошо, система заработала. Получатель, конечно, попытался далее переслать письмо мне на ящик в gmail, но не смог.
Не понравилось ему, что нет заголовка "From". Но это уже другая история. Кстати, можно обойти проблему, отправив письмо с помощью VBS, накидал скрипт:
Set emailObj = CreateObject("CDO.Message")
emailObj.From = "Тест postfix <info@testsender.internet-lab.ru>"
emailObj.To = "info@internet-lab.ru"
emailObj.Subject = "Test postfix"
emailObj.TextBody = "Test body postfix"
Set emailConfig = emailObj.Configuration
emailConfig.Fields("http://schemas.microsoft.com/cdo/configuration/smtpserver") = "192.168.1.13"
emailConfig.Fields("http://schemas.microsoft.com/cdo/configuration/smtpserverport") = 25
emailConfig.Fields("http://schemas.microsoft.com/cdo/configuration/sendusing") = 2
emailConfig.Fields("http://schemas.microsoft.com/cdo/configuration/smtpauthenticate") = 0
emailConfig.Fields("http://schemas.microsoft.com/cdo/configuration/smtpusessl") = false
emailConfig.Fields.Update
emailObj.Send
If err.number = 0 then Msgbox "Done"
Отправляю скриптом:
Письма дошло, можно двигаться дальше.
Аутентификация
Для начала настроим пользователей для аутентификации. Для администрирования пользователей базы sasldb понадобится пакет sasl2-bin.
Ещё нужны модули libsasl2-2 и libsasl2-modules, но они уже есть:
dpkg -l | grep sasl
Установим sasl2-bin:
apt-get install sasl2-bin
Редактируем файл /etc/default/saslauthd.
Включаем saslauthd:
START=yes
Механизм аутентификации sasldb:
MECHANISMS="sasldb"
Для postfix указываем опцию:
OPTIONS="-c -m /var/spool/postfix/var/run/saslauthd"
Перезагружаем saslauthd:
service saslauthd restart
Вместе с пакетом sasl2-bin устанавливаются утилиты для работы с пользователями sasldb: saslpasswd2, sasldblistusers2, testsaslauthd.
Создаём пользователя info@testsender.internet-lab.ru с паролем 888776:
saslpasswd2 -c -u testsender.internet-lab.ru info
Посмотреть список пользователей в базе:
sasldblistusers2
Видим что в базе один пользователь info@testsender.internet-lab.ru, пароль не отображается.
Утилита testsaslauthd позволяет проверить аутентификацию:
testsaslauthd -u info -r testsender.internet-lab.ru -p 888776
Результат:
connect() : No such file or directory
Упс, что-то не работает. На самом деле всё просто, мы в опциях /etc/default/saslauthd сменили директорию /var/run/saslauthd на /var/spool/postfix/var/run/saslauthd, утилита работает с /var/run/saslauthd. Исправим проблему, правильнее всего монтировать директорию в нужное место, добавляем в /etc/fstab:
/var/run/saslauthd /var/spool/postfix/var/run/saslauthd none rw,bind 0 0
Перезагружаем сервер:
reboot
После перезагрузки проверяем аутентификацию:
testsaslauthd -u info -r testsender.internet-lab.ru -p 888776
Результат:
0: OK "Success."
Мы добились успешной аутентификации созданного нами пользователя.
Аутентификация в Postfix
Сама база пользователей sasldb находится в /etc/sasldb2.
cd /etc
ll | grep sasl
Для того, чтобы Postfix мог читать из базы, пользователю postfix нужно дать права на файл sasldb2. Файл sasldb2 принадлежит группе sasl. Добавим пользователя postfix в группу sasl:
usermod -a -G sasl postfix
Находим директорию /etc/postfax/sasl:
Создаём в директории /etc/postfax/sasl файл smtpd.conf:
pwcheck_method: saslauthd
mech_list: PLAIN LOGIN
Выполняем:
postconf -a
И видим, что Postfix по умолчанию поставляется с поддержкой cyrus и dovecot. Я выбрал cyrus. Ставим пакет cyrus-common:
apt-get install cyrus-common
Спрашивают про какие-то буферы. Говорю Yes.
Настраиваем аутентификацию в Postfix. Модифицируем файл настроек /etc/postfix/main.cf. Добавляем:
smtpd_sasl_type = cyrus
smtpd_sasl_path = smtpd
smtpd_sasl_auth_enable = yes
broken_sasl_auth_clients = yes
smtpd_sasl_security_options = noanonymous
smtpd_relay_restrictions = permit_mynetworks permit_sasl_authenticated reject_unauth_destination
smtp_tls_security_level = may
Получилось:
myorigin = postfix.testsender.internet-lab.ru
myhostname = postfix.testsender.internet-lab.ru
mydomain = testsender.internet-lab.ru
smtpd_banner = postfix.testsender.internet-lab.ru
biff = no
alias_maps = hash:/etc/postfix/aliases
mynetworks = 127.0.0.0/8 192.168.1.0/24 [::ffff:127.0.0.0]/104 [::1]/128
message_size_limit = 35840000
mailbox_size_limit = 0
recipient_delimiter = +
inet_interfaces = all
masquerade_classes = envelope_sender, header_sender
relay_domains = testsender.internet-lab.ru
maximal_queue_lifetime = 5d
compatibility_level = 2
smtpd_sasl_type = cyrus
smtpd_sasl_path = smtpd
smtpd_sasl_auth_enable = yes
broken_sasl_auth_clients = yes
smtpd_sasl_security_options = noanonymous
smtpd_relay_restrictions = permit_mynetworks permit_sasl_authenticated reject_unauth_destination
smtp_tls_security_level = may
Перезагружаю сервисы:
service postfix restart
service saslauthd restart
Проверка отправки письма с аутентификацией
Из подсети 192.168.1.0/24 пытаемся отправить письмо с помощью telnet по 25 порту.
telnet 192.168.1.13 25
ehlo localhost
Строка AUTH PLAIN LOGIN символизирует наличие возможности аутентификации.
Отправляем письмо с аутентификацией. Для этого нам понадобится перевести логин и пароль в формат Base64. Можно найти онлайн декодер.
- Логин "info@testsender.internet-lab.ru" в Base64 — "aW5mb0B0ZXN0c2VuZGVyLmludGVybmV0LWxhYi5ydQ==".
- Пароль "888776" в Base64 — "ODg4Nzc2".
Отправляем письмо:
Сообщение 235 2.7.0 Authentication successful говорит о том, что аутентификация успешна.
Отправляем также VBS скриптом:
Set emailObj = CreateObject("CDO.Message")
emailObj.From = "Тест postfix SASL<info@testsender.internet-lab.ru>"
emailObj.To = "info@internet-lab.ru"
emailObj.Subject = "Test postfix"
emailObj.TextBody = "Test body postfix"
Set emailConfig = emailObj.Configuration
emailConfig.Fields("http://schemas.microsoft.com/cdo/configuration/smtpserver") = "192.168.1.13"
emailConfig.Fields("http://schemas.microsoft.com/cdo/configuration/smtpserverport") = 25
emailConfig.Fields("http://schemas.microsoft.com/cdo/configuration/sendusing") = 2
emailConfig.Fields("http://schemas.microsoft.com/cdo/configuration/smtpauthenticate") = 1
emailConfig.Fields("http://schemas.microsoft.com/cdo/configuration/sendusername") = "info@testsender.internet-lab.ru"
emailConfig.Fields("http://schemas.microsoft.com/cdo/configuration/sendpassword") = "888776"
emailConfig.Fields("http://schemas.microsoft.com/cdo/configuration/smtpusessl") = false
emailConfig.Fields.Update
emailObj.Send
If err.number = 0 then Msgbox "Done"
Письмо доставлено.
Настройка DKIM
Правим главный файл настроек /etc/postfix/main.cf, добавляем:
milter_protocol = 2
milter_default_action = accept
smtpd_milters = inet:localhost:8891
non_smtpd_milters = inet:localhost:8891
Ставим opendkim:
apt-get install opendkim opendkim-tools
Создаём каталог для ключей и сгенерируем ключ (пока для одного домена):
mkdir /etc/opendkim
opendkim-genkey -D /etc/opendkim/ --domain testsender.internet-lab.ru --selector testsenderpostfix
Где testsenderpostfix — придуманный селектор, можно любой придумать.
Появится два файла /etc/opendkim/testsenderpostfix.private и /etc/opendkim/testsenderpostfix.txt с секретным и публичным ключами. Публичный ключ нужно добавить в соответствующую TXT запись вашего домена:
testsenderpostfix._domainkey.testsender IN TXT ( "v=DKIM1; h=sha256; k=rsa; "
"p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApjvmaLNcAnyLmBxUw1b7EGPQ5BdZbbsM+HQ0qIsjdkcidYjJR/z39xw0gRbFC7+WMfj6zrutTBb5PJwRmb9zIM4nhs4KvxPVSMSA1mkmVDdjKqF7MJ3dUhRmpXcgVH0Mh4zzIeZQO1skg13HPBcGrPqVF3LebZ2v4PenfWxm/CJrBxJD++MLi0IdPvxu4/OQl+ZgZCuasN7iNj"
"fK4MGsYxzAmYgZhSP2qVGNdKWnrmuKLV6/wijqfEA677KunkFJxqtssBfijCYE61/+5RTUxWGNdaoPxzWhO8H00HOfxc374dOE9SKpSKqr21Xj8O20GL+Q6mzl7LTOkHkut6e1dQIDAQAB" )
Настраиваем /etc/opendkim.conf:
Syslog No
Mode sv
SOCKET="inet:8891@localhost"
KeyTable refile:/etc/opendkim/KeyTable
SigningTable refile:/etc/opendkim/SigningTable
Создаём файл /etc/opendkim/KeyTable:
testsenderpostfix._domainkey.testsender.internet-lab.ru testsender.internet-lab.ru:testsenderpostfix:/etc/opendkim/testsenderpostfix.private
Создаём файл /etc/opendkim/SigningTable:
*@testsender.internet-lab.ru testsenderpostfix._domainkey.testsender.internet-lab.ru
Задаем группу владельца opendkim для созданных ключей и файлов:
chown :opendkim /etc/opendkim/*
Устанавливаем права на секретный ключ:
chmod 640 /etc/opendkim/testsenderpostfix.private
Перезапускаем postfix и opendkim:
service opendkim restart
service postfix restart
Осталось только проверить и отправить письмо.