воскресенье, 27 октября 2013 г.

Настройка postfix для виртуальных пользователей (Ubuntu Server, Debian)

Для того, чтобы не заводить системных пользователей для каждого нового email адреса, а также на одном сервере обрабатывать множество доменов, необходимо настроить почтовый сервер для работы с виртуальными доменами и пользователями. Будем настраивать postfix в качестве MTA. Пользователей и домены будем хранить в MySQL базе данных (для удобного редактирования), в качестве POP3 и Imap серверов настроим Courier.

Ставим postfix и почтовые утилиты (mail)

sudo apt-get install postfix postfix-mysql mailutils mysql-server
при установке спросит тип сервера - Internet. (Если же нам понадобиться отправлять почту с чужого smtp (остальные вырианты при установке postfix-а), то необходимо будет просто добавить этот smpt сервер в параметре relayhost конфигурационного файла)

Необходимо отредактировать конфигурационный файл postfix-а:
/etc/postfix/main.cf
myhostname = localhost
в конце файла добавим:
home_mailbox = Maildir/
Перезапустим postfix, чтобы изменения вступили в силу:
sudo /etc/init.d/postfix restart

Настраиваем виртуальных пользователей

Создадим группу для виртуальных почтовых ящиков:
sudo groupadd -g 5000 vmail
Добавим владельца:
sudo useradd -m -u 5000 -g 5000 -s /bin/bash vmail
Отредактируем /etc/postfix/main.cf.
Параметр mydestancion должен быть пустым:
mydestination =
Добавим в конец файла:
virtual_mailbox_domains = /etc/postfix/vhosts
virtual_mailbox_base = /home/vmail
virtual_mailbox_maps = hash:/etc/postfix/vmaps
virtual_mailbox_limit = 0
virtual_minimum_uid = 1000
virtual_uid_maps = static:5000
virtual_gid_maps = static:5000
Создадим файл, содержащий список доменов:
sudo vi /etc/postfix/vhosts
С содержимым:
domain1.com
domain2.com
Создадим файл со списком виртуальных почтовых ящиков:
sudo vi /etc/postfix/vmaps
Следующего содержания:
info@example.com  example.com/info/
alias@example.com  example.com/info/
sales@example.com  example.com/sales/
info@example2.com  example2.com/info/
sales@example2.com  example2.com/sales/
Теперь необходимо преобразовать виртуальные почтовые ящики в хэш, командой:
sudo postmap /etc/postfix/vmaps
Это необходимо делать после каждого изменения виртуальных почтовых ящиков.
Чтобы изменения вступили в силу, необходимо перезапустить postfix
sudo  /etc/init.d/postfix restart
проверим работу виртуальных почтовых ящиков, отправив на один из них письмо:
mail info@domain1.com
если все верно, то в директории /home/vmail создастся поддиректория domain1.com/info - содержашая виртуальный почтовый ящик вкотором должно находиться посланное нами письмо.

Виртуальные почтовые ящики в MySQL базе данных

Создадим новую базу данных mail
sudo mysqladmin -u root -p create mail
создадим для нее пользователя с необходимыми правами:
mysql -u root -p
mysql> CREATE USER 'mailadmin'@'localhost' IDENTIFIED BY 'mypassword';
mysql> FLUSH PRIVILEGES;
mysql> GRANT SELECT, INSERT, UPDATE, DELETE ON `mail` . * TO 'mailadmin'@'localhost';
mysql> FLUSH PRIVILEGES;
выберем нашу базу данных и создадим необходимые таблицы:
USE mail;
CREATE TABLE domains (  domain varchar(50) NOT NULL,  PRIMARY KEY (domain)  )  Engine=MyISAM;
CREATE TABLE users (  email varchar(80) NOT NULL,  password varchar(20) NOT NULL,  PRIMARY KEY (email)  ) Engine = MyISAM;
CREATE TABLE forwards (  source varchar(80) NOT NULL,  destination TEXT NOT NULL,  PRIMARY KEY (source)  ) Engine=MyISAM;
Для того, чтобы postfix мог использовать данные из таблиц mysql, необходимо добавить несколько конфигурационных файлов.
Файл для получения списка доменов:
sudo mkdir /etc/postfix/mysql
sudo vi /etc/postfix/mysql/domains.cf
с содержимым:
user = mailadmin
password = mypassword
hosts = 127.0.0.1
dbname = mail
table = domains
select_field = domain
where_field = domain
для списка почтовых ящиков:
sudo vi /etc/postfix/mysql/mailboxes.cf
user = mailadmin
password = mypassword
dbname = mail
hosts = 127.0.0.1
query = SELECT CONCAT(SUBSTRING_INDEX(email,'@',-1),'/',SUBSTRING_INDEX(email,'@',1),'/') FROM users WHERE email='%s'
для алиасов:
sudo vi /etc/postfix/mysql/alias.cf
user = mailadmin
password = mypassword
hosts = 127.0.0.1
dbname = mail
table = forwards
select_field = destination
where_field = source
Установим нужные права и владельца:
sudo chmod o= /etc/postfix/mysql/*
sudo chgrp postfix /etc/postfix/mysql/*
изменим настройки postfix для того, чтобы он использовал эти конфигурационные файлы для получения необходимых данных
sudo vi /etc/postfix/main.cf
изменяем параметры:
virtual_mailbox_domains = mysql:/etc/postfix/mysql/domains.cf
virtual_mailbox_maps = mysql:/etc/postfix/mysql/mailboxes.cf
добавляем параметр:
virtual_alias_maps = mysql:/etc/postfix/mysql/alias.cf
добавим в базу данных информацию о доменах и почтовых ящиках:
mysql -u root -p
USE mail;
INSERT INTO `domains` (`domain`) VALUES ('example.com');
INSERT INTO `domains` (`domain`) VALUES ('example2.com');
INSERT INTO `users` (`email`, `password`) VALUES ('info@example.com', ENCRYPT('password1'));
INSERT INTO `users` (`email`, `password`) VALUES ('info@example2.com', ENCRYPT('password2'));
Перезапускаем postfix
sudo /etc/init.d/postfix restart
Теперь, для добавления новых почтовых ящиков и доменов, нам не нужно перезапускать postfix или запускать создание хэшей. Достаточно просто редактировать данные в mysql базе mail.

Аутентификация пользователей через saslauthd

ставим софт:
sudo apt-get install libsasl2-2 libsasl2-modules libsasl2-modules-sql sasl2-bin libpam-mysql
Отредактируем конфигурационный файл saslauthd
sudo vi /etc/default/saslauthd
изменим в нем 2 параметра на значения указанные ниже:
START=yes
и:
OPTIONS="-c -r -m /var/spool/postfix/var/run/saslauthd"
(параметр r - для правильной передачи имени пользователя, измененный путь, для того чтобы к нему мог обратиться постфикс, который запускается в изолированной среде)
создаем каталог:
mkdir -p /var/spool/postfix/var/run/saslauthd
и добавим символическую ссылку:
sudo rm -rf /var/run/saslauthd
sudo ln -s /var/spool/postfix/var/run/saslauthd /var/run/saslauthd
необходимо создать 2 конфигурационных файла
sudo vi /etc/pam.d/smtp
с содержимым:
auth    required   pam_mysql.so user=mailadmin passwd=mypassword host=127.0.0.1 db=mail table=users usercolumn=email passwdcolumn=password crypt=1
account sufficient pam_mysql.so user=mailadmin passwd=mypassword host=127.0.0.1 db=mail table=users usercolumn=email passwdcolumn=password crypt=1
и:
sudo vi /etc/postfix/sasl/smtpd.conf
с содержимым:
pwcheck_method: saslauthd
mech_list: plain login
allow_plaintext: true
далее необходимо добавить postfix в группу sasl для того, чтобы он имел доступ к процессу saslauthd, который мы только что создали
sudo adduser postfix sasl
перезапустим postfix и sasl
sudo /etc/init.d/postfix restart
sudo /etc/init.d/saslauthd restart
Убедимся что saslauthd работает правильно:
testsaslauthd -s smtp -u info@example.com -p emailpassword
0: OK "Success."
Если все работает нормально, то необходимо изменить права для доступа к созданным конфигурационным файлам:
sudo chgrp sasl /etc/pam.d/smtp
sudo chmod 640 /etc/pam.d/smtp
sudo chgrp postfix /etc/postfix/sasl/smtpd.conf
sudo chmod 640 /etc/postfix/sasl/smtpd.conf
Теперь мы должны указать postfix-у что аутентифицированным пользователям разрешено отправлять почту. Добавляем в файл sudo vi /etc/postfix/main.cf
строку:
smtpd_sender_restrictions =
    permit_mynetworks
    permit_sasl_authenticated
    permit_tls_clientcerts
Для того, чтобы наш почтовый сервер не использовали в качестве открытого ретранслятора, добавим также строку
smtpd_recipient_restrictions =
    permit_mynetworks
    permit_sasl_authenticated 
    reject_unauth_destination
    reject_unlisted_recipient
    reject_unverified_recipient
перезапускаем postfix и sasl
sudo /etc/init.d/postfix restart
sudo /etc/init.d/saslauthd restart

Сертификаты сервера

Созадим приватный ключ
sudo openssl genrsa -des3 -out server.key 1024
[sudo] password for *****: 
Generating RSA private key, 1024 bit long modulus
................................................................................................................................................................++++++
..................++++++
e is 65537 (0x10001)
Enter pass phrase for server.key:
Verifying - Enter pass phrase for server.key:
Теперь, когда у нас есть приватный ключ, необходимо создать "запрос на подпись сертификата"
sudo openssl req -new -key server.key -out server.csr
Enter pass phrase for server.key:
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:example.com
Email Address []:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
Common Name должно соответствовать доменному имени нашего сервера.
Теперь нужно удалить фазу запроса пароля ключа, иначе каждый раз при перезапуске сервисов (apache, postfix, и т.д.) будет требоваться ввод пароля.
cp server.key server.key.org
sudo openssl rsa -in server.key.org -out server.key
Enter pass phrase for server.key.org:
writing RSA key
теперь, когда server.key без ввода пароля, мы можем создать самоподписанный сертификат:
sudo openssl x509 -req -in server.csr -signkey server.key -out server.crt
Signature ok
subject=/C=AU/ST=Some-State/O=Internet Widgits Pty Ltd/CN=example.com
Getting Private key
Если нужен временный сертификат, то можно добавить параметр -days 365, указывающий на то, что сертификат действителен в течении 365 дней (openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt).
server.crt содержит самоподписанный сетрификат. Для создания server.pem необходимо объединить server.crt server.key
cat server.crt server.key > server.pem
Файлы server.key и server.pem содержать закрытый ключ сервера без фразы проверки пароля, вы должны убедиться, что обычные пользователи на вашем сервере не могут получить доступ к этим файлам. server.csr - содержит самоподписанный сертификат.
сохраним ключи:
sudo mkdir /etc/ssl/self-signed
sudo mv server.* /etc/ssl/self-signed/
sudo chown -R root:root /etc/ssl/self-signed/
sudo chmod -R 644 /etc/ssl/self-signed/

TLS в postfix

в конфигурациоонном файле postfix-а
sudo vi /etc/postfix/main.cf
изменяем блок строк:
# TLS parameters
smtpd_tls_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem
smtpd_tls_key_file=/etc/ssl/private/ssl-cert-snakeoil.key
smtpd_use_tls=yes
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache
на:
# TLS parameters
smtpd_sasl_auth_enable = yes
broken_sasl_auth_clients = yes
smtpd_sasl_authenticated_header = yes
smtpd_recipient_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination
smtpd_use_tls = yes
smtpd_tls_cert_file = /etc/ssl/self-signed/server.pem
smtpd_tls_key_file = $smtpd_tls_cert_file
этим мы говорим postfix-у что разрешено отправлять почту без аутентификации из нашей подсети (localhost), и аутентифицированным через sasl пользователям.

На данном этапе можно проверить отсылку почты (проверка почты пока недоступна) через email клиент на внешней клиентской машине. для аутентификации а качестве логина пользователя необходимо использовать полный email и включить шифрование TLS.

так как многие провайдеры блокируют 25-й порт, то для того, чтобы использовать наш сервер вкачестве сервера исходящей почты, нам необходимо включить порт 587 в postfix и изменить правила брандмауэра, чтобы разрешить через него трафик. Для этого редактируем файл master.cf
sudo vi /etc/postfix/master.cf
необходимо раскомментировать строки:
submission inet n       -       -       -       -       smtpd
  -o syslog_name=postfix/submission
  -o smtpd_tls_security_level=encrypt
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_client_restrictions=permit_sasl_authenticated,reject
  -o milter_macro_daemon_name=ORIGINATING

Courier

ставим софт:
sudo apt-get install courier-authdaemon courier-authlib-mysql courier-pop courier-pop-ssl courier-imap courier-imap-ssl fam
укажем, что пароли для аутентификации необходимо брать из базы данных mysql
sudo vi /etc/courier/authdaemonrc
меняем параметр:
authmodulelist="authpam"
на:
authmodulelist="authmysql"
очистим файл authmysqlrc
sudo cp /etc/courier/authmysqlrc /etc/courier/authmysqlrc.orig
и вставим в него:
MYSQL_SERVER localhost
MYSQL_USERNAME mailadmin
MYSQL_PASSWORD mypassword
MYSQL_PORT 0
MYSQL_DATABASE mail
MYSQL_USER_TABLE users
MYSQL_CRYPT_PWFIELD password
MYSQL_UID_FIELD 5000
MYSQL_GID_FIELD 5000
MYSQL_LOGIN_FIELD email
MYSQL_HOME_FIELD "/home/vmail"
MYSQL_MAILDIR_FIELD CONCAT(SUBSTRING_INDEX(email,'@',-1),'/',SUBSTRING_INDEX(email,'@',1),'/')
отредактируем файл:
sudo vi /etc/courier/imapd-ssl
изменим 2 параметра:
TLS_CERTFILE=/etc/ssl/self-signed/server.pem
TLS_TRUSTCERTS=/etc/ssl/self-signed/server.crt
перезупустим службы Courier-а:
sudo /etc/init.d/courier-authdaemon restart
sudo /etc/init.d/courier-imap restart
sudo /etc/init.d/courier-imap-ssl restart
sudo /etc/init.d/courier-pop restart
sudo /etc/init.d/courier-pop-ssl restart

Полезные команды

postconf mail_version - узнать установленную версию postmail-а.
mailq - показать очередь сообщений.
postsuper -d ALL - удалить из очереди сообщения, которые не доставлены из-за ошибок.
postfix flush - отправить сообщения, находящиеся в очереди.
postfix check - проверить файлы и директории на права доступа и владельца.

17 комментариев:

  1. Все сделал, на этапе Убедимся что saslauthd работает правильно:
    connect() : Permission denied

    ОтветитьУдалить
  2. ну. во первых, нужно убедиться чтобы postfix был в группе sasl. а вообще, логи смотреть нужно, например тут: /var/log/auth.log

    ОтветитьУдалить
    Ответы
    1. Авторизация пройшла нормально testsaslauthd вернул 0: OK "Success." но достучаться извне к pop3 или к smtp нереально. В логах warning: mysql:/etc/postfix/mysql/alias.cf lookup error for "mail@gmail.com"

      Удалить
    2. 1. что значит достучаться нерельно? телнетом не выходит? или почтовая прога ругается на отсутствие директорий ящиков? если второе, то разумеется, если писем нет - то чего и конектиться! пошлите какой либо письмо на ящик, который проверять хотите. наприер так:
      mail mybox@example.com после этого, директории для ящика создадуться. (что вообще находится в /home/vmail/?)
      2. это в каких именно логах? /var/log/mail.log? и откуда вообще этот адрес взялся - mail@gmail.com - если в качестве примера, то по госту example.com используйте - тогда ясно, что замена реального адреса.
      3. но вообще, создается впечатление, что для домена gmail.com нет ящика mail (если бы достучаться было невозможно, то не писалобы ничего в логи). мало информации даете - я не шибко продвинутый телепат :(

      Удалить
  3. У меня не получается добавить почтовый ящик, просто добавив записи в базу данных. Дополнительно требует создать каталог domain1.com/info в /home/vmail и отправить из командной строки письмо (иначе ругается почтовый клиент). Можно ли сделать что бы не требовалось "ручное" создание каталогов новых пользователей?

    ОтветитьУдалить
    Ответы
    1. Не должно требовать вручную создавать директории для ящиков. должно создавать автоматически при получении первого письма. не обязательно из командной строки. достаточно отправить на этот ящик письмо из любого места. владелец на директорию домена точно vmail и группа vmail? а то если сами создавали, то, возможно, владелец уже не тот и недостаточно прав для автоматического создания директорий.

      Удалить
    2. Спасибо за ответ. Владелец vmail, проверил. Добавил запись пользователя в базу для уже имеющегося домена (папка /home/vmail/mydomain.ru была, владелец vmail). Пытаюсь клиентом подключиться - пишет "неверное имя пользователя или пароль", а mail.log говорит: chdir mydomain.ru/newuser/: No such file or directory. Делаю sudo mkdir /home/vmail/mydomain.ru/newuser , sudo chown vmail:vmail -R /home/vmail/mydomain.ru/newuser . Клиент подключился, отправлять почту через командную строку действительно не потребовалось. Но от необходимости создавать папку не избавлюсь никак.

      Удалить
    3. Разобрался, прочитал внимательнее ответ выше. " пошлите какой либо письмо на ящик, который проверять хотите. наприер так: mail mybox@example.com после этого, директории для ящика создадуться" . Т.е. надо обязательно welcome-message отправлять, тогда проблем с подключением клиента не будет.

      Отличный пост, все доходчиво, спасибо!

      Строчка "smtpd_recipient_restrictions" дважды упоминается в настройках posfix - в параграфе про настройку аутентификации через saslauthd и потом в TSL. Одна лишняя?

      Удалить
    4. Да. Все верно. Просто оно и для tsl нужно (вроде как). но и для нормальной работы почты без всяких tsl также необходимо. Так что оно, разумеется, должно 1 раз встречаться.

      Удалить
  4. Я совсем начинающий. На минисервере держу несколько сайтов на WP. Принимать почту нет нужды, нужно только отправлять автоматические уведомления с этих WP сайтов, но чтобы каждый от своего домена. Как это реализовать в postfix?

    ОтветитьУдалить
    Ответы
    1. из командной строки я отправлял так:

      (echo "Subject:test subject"; echo "Test mailbody";) | sendmail -t -i -fit@example.com -F "TestName" example@gmail.com

      соотвествтвенно отправит письмо с ящика it@example.com на example@gmail.com

      если нужно из пхп, то могу посоветовать класс PHPMailer, который очень гибко можно настроить, включая и посылку через sendmail, а не mail функцией php, которая для всех отправок использует параметры sendmail-а из php.ini

      Удалить
    2. А WordPress в рамках своих штатный установок через свои формы как отправляет письма? Для это нужен postfix, sendmail или PHPMailer?

      Удалить
    3. Не имел дела с вордпрессом, однако, изучив первую страницу резкльтатов поиска гугла, могу предположить, что там, по умолчанию, включен phpMailer, с отправкой через php функцию mail() - соответственно у всех сайтов на данном сервере в строке отправитель будет один адрес, прописанный в php.ini

      Согласно данной статье: http://www.mysoftware.ws/wordpress-ne-rabotaet-otpravka-pochty/ достаточно просто указать sendmail в файле /wp-includes/pluggable.php. Возможно, в нем же, есть и другие настройки. Или уже в самой контрольной панели WP. Если нет, то, теоретически, вордпресс должен будет сам подставлять значения для сендмайла. Хотя - нужно пробовать, с вордпрессом дел не имел :(
      Но, не забываем, что IP адрес сервера должен быть добавлен, как минимум, в SPF запись домена.

      Удалить
  5. 0: NO "authentication failed"
    Рою гугл, находится что-то, да не то...(

    ОтветитьУдалить
  6. я, думаю, уже разобрался? для активации ящиков нужно письмо послать туда. после этого и конектится можно будет всякими почтовыми прогами.ю и л=директории наср=оздаются

    ОтветитьУдалить
    Ответы
    1. Неа. Письмо послал, но снова 0: NO "authentication failed" это если под рутом
      если под юзером, то connect() : Permission denied
      права все настроил, имя и пароль корректные

      Удалить
    2. Вообще ман очень толковый, до этого момента всё шло как по маслу, и тут встрял((

      Удалить