Разворачиваем почтовый сервер Postfix+Docecot+Roundcube+Active Directory
Понедельник, 23 октября 2017 11:43

Разворачиваем почтовый сервер Postfix+Docecot+Roundcube+Active Directory

Автор
Оцените материал
(3 голосов)

Рано или поздно любая уважающая себя компания столкнется с необходимостью иметь свой почтовый сервис. Можно конечно использовать сервисы, предоставляемые провайдером. Но в этом случае имеем ряд ограничений: от количества почтовых ящиков пользователей до слишком маленького размера этих ящиков. И все это сказывается на цене, которую приходится платить хозяину сервиса. Поэтому лучше иметь свой почтовый сервер. Т.к. в стране идет активный процесс "импортозамещения", то об использовании самой продвинутой (на мой скромный взгляд) почтовой системы MS Exchange речи быть не может. В этой статье пойдет речь об установке и настройке почтовой системы Postfix, входящие в различные операционные системы, допущенные к эксплуатации в государственных учреждениях. Кроме самого Postfix будем настраивать всевозможные "кирпичики" к нему, что бы хоть как то приблизить эту почтовую систему к удобству работы, предоставляемую MS Exchange. Все работы будут производится на ОС ROSA Linux Cobalt (он же CentOS 7, он же RedHat 7)

Несколько слов о том, что будет установлено:

  1. Все почтовые сервисы будут установлены на одном сервере.
  2. Сервер будет обслуживать внутренний домен, развернутый на примере предыдущих статей
  3. Будут использованы надстройки и дополнительные сервисы: Dovecot 2 + MySQL + PostfixAdmin + Postgrey + Postscreen + ClamAV + DKIM + Sieve + RoundCube (+плагины к RoundCube) + Active Directory
  4. Будет настроена связь почтовой системы с базой пользователей Active Directory
  5. Имя сервера, на котором будет установлена почтовая система: mail
  6. Имя домена, обслуживаемого данным сервером: dest.loc
  7. Почтовый субдомен: mail.dest.loc
  8. Имя и почтовый адрес мастер-пользователя: Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в вашем браузере должен быть включен Javascript.
  9. Логин почтового ящика для авто-BCC неизвестных пользователей родных доменов: Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в вашем браузере должен быть включен Javascript.
  10. Ip адрес домена: 192.168.20.100
  11. Ip адрес почтового сервера: 192.168.20.104
  12. GUID, группа пользователей виртуальных почтовых ящиков: 5000 vmail
  13. UID, системный пользователь виртуальных ящиков: 5000 vmail
  14. Базовый каталог почты MailDir: "/opt/mail/vmail/" Формат создаваемых каталогов: "/opt/mail/vmail/dest.loc/_пользователь_/"
  15. Каталог глобальных ACL: "/etc/dovecot/acl/%d"
  16. Каталог, в котором будет создан вложенный подкаталог "sieve" с глобальными и персональными Sieve-скриптами: "/opt/dovecot"
  17. Каталог виртуальных папок плагина "virtual" Dovecot: "/opt/dovecot/virtual"
  18. Порт OpenDKIM: 8891
  19. Порт ClamAV-Milter: 7357
  20. Порт Postgrey: 10023
  21. Порт ManageSieve: 4190
  22. Файл SQL-запроса виртуального почтового ящика: "/etc/postfix/mysql_virtual_maps.cf"
  23. Файл SQL-запроса домена: "/etc/postfix/mysql_virtual_domains.cf"
  24. Файл SQL-запроса почтового ящика, для которого запрашиваемый является алиасом: "/etc/postfix/mysql_virtual_alias_maps.cf"
  25. Файл SQL-запроса ящика домена, для которого домен запрашиваемого ящика является алиасом: "/etc/postfix/mysql_virtual_alias_domain_maps.cf"
  26. Файл SQL-запроса для авто-BCC в ящики зарегистрированных отправителей: "/etc/postfix/mysql_bcc_mailbox_maps.cf"
  27. Файл SQL-запроса ящика для авто-BCC не зарегистрированных отправителей родных доменов: "/etc/postfix/mysql_bcc_domain_maps.cf"
  28. Postfix SSL ключ: "/etc/postfix/ssl.key.pem"
  29. Postfix SSL сертификат: "/etc/postfix/ssl.cert.pem"
  30. Dovecot SSL ключ: "/etc/dovecot/ssl.key.pem"
  31. Dovecot SSL сертификат: "/etc/dovecot/ssl.cert.pem"
  32. Путь к корневой папке с web-файлами для https Apache2: "/opt/www/html/"
  33. Имя MySQL базы PostfixAdmin: "POSTFIXADMIN_BASE_"
  34. Имя пользователя MySQL базы PostfixAdmin: "POSTADMIN_USER_"
  35. Пароль пользователя MySQL базы PostfixAdmin: "_POSTFIXADMIN_SQL_PASSWORD_"
  36. Имя MySQL базы Roundcube: "roundcubemail"
  37. Имя пользователя MySQL базы Roundcube: "roundcube"
  38. Пароль пользователя MySQL базы Roundcube: "_ROUNDCUBE_SQL_PASSWORD_"

Предварительная настройка сервера.

  1.  Устанавливаем ОС в режиме минимальной установки.
  2. Отключаем Selinux
  3. Отключаем ipv6, если он не используется в сети компании.
  4. Добавляем ip адрес и имя (в том числе и полное) в файл /etc/hosts
  5. Настраиваем синхронизацию времени с контролером домена (или любым другим источником времени)
  6. На сервере DNS должны быть внесена соответствующие A, MX и PTR записи
  7. Для работы DKIM и SPF в DNS должны быть внесены соответствующие TXT записи. Например:
    Для SPF
    dest.loc. IN TXT "v=spf1 a mx 192.168.10.104 ~all"
    
    После имени домена обязательно должна быть точка.
    Для DKIM:
    mail._domainkey IN TXT "v=DKIM1;k=rsa;p=_КЛЮЧ_СГЕНЕРИРОВАННЫЙ_СООТВЕТСТВУЮЩИМ_ПО_"
    
    Определяем политику использования DKIM в домене - добавляем в DNS еще одну TXT-запись
    _adsp._domainkey IN TXT "dkim=all"
    
    Где:
    unknown - отправка не подписанных сообщений разрешена (значение по умолчанию)
    all - отправка не подписанных сообщений запрещена
    discardable - все не подписанные сообщения должны быть заблокированы на стороне получателя

    После всех манипуляций можно найти какой-нибудь из множества сайтов, бесплатно осуществляющих проверку этих настроек, в т.ч. через отправку тестового письма.
  8. Будем считать, что MySQL уже установлен и настроен на сервере. Единственная рекомендация для данной установки: ограничить адреса подключений к серверу. Делается это путем добавления в файл конфигурации my.cnf одной строки:
    ......
    bind-address = 127.0.0.1
    ......
    
    После этого перезапускаем SQL сервер

Установка PostfixAdmin

Postfixadmin лучше установить до Postfix, чтобы потом сразу использовать правильные имена MySQL-таблиц Postfixadmin в конфигах Postfix.

Предполагается, что "apache2", "php5" и "mysql-server" - уже установлены. Их установка здесь не рассматривается.

Нужно в MySQL создать базу и пользователя для PostfixAdmin.

Устанавливаем необходимые пакеты:

yum install php-imap php-mbstring

Забираем исходник. На момент написание сего опуса самая свежая версия была 3.1:

wget https://sourceforge.net/projects/postfixadmin/files/postfixadmin/postfixadmin-3.1/postfixadmin-3.1.tar.gz

Распаковываем и помещаем в папку "/opt/www/html/postfixadmin/"
Создаем базу данных для работы postfixadmin и пользователя этой базы данных:

mysql -u root -p
create database postfixadmin_base default character set utf8 default collate utf8_general_ci;
grant all on postfixadmin_base.* to 'postadmin_user'@'localhost' identified by '_POSTFIXADMIN_SQL_PASSWORD_';

Открываем файл /opt/www/html/postfixadmin/conf.inc.php и вносим изменения:

$CONF['configured'] = true;
$CONF['default_languge'] = 'ru';
$CONF['database_user'] = 'postadmin_user';
$CONF['database_password'] = '_POSTFIXADMIN_SQL_PASSWORD_';
$CONF['database_name'] = 'postfixadmin_base';

Создаем дополнительную папку:

mkdir /opt/www/html/postfixadmin/templates_c
chown -R apache:apache /opt/www/html/postfixadmin/templates_c

И запускаем установщик в браузере: https://mail.dest.loc/postfixadmin/setup.php

 Установщик проверит корректность настроек и создаст необходимую структуру базы данных.

На странице требуется ввести пароль установщика. После ввода пароля страница перезагрузится и выдаст сообщение:

If you want to use the password you entered as setup password, edit config.inc.php or config.local.php and set
$CONF['setup_password'] = 'dsvhajh34525jbhwjt534tbsa887sfdbkj8sfljhlsfdg8shfl898wkj';

Т.е. требуется ввести этот хеш пароля в соответствующий раздел в файле conf.inc.php

После того, как внесли изменения в конфигурационный файл, вводим учетные данные пользователя Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в вашем браузере должен быть включен Javascript. и нажимаем "Добавить администратора"

После добавления администратора можно заходить на страницу https://mail.dest.loc/postfixadmin/ и вводить учетные данные вновь созданного администратора.

Создаем папку postfixadmin-log, назначаем владельца папки пользователя от имени которого запущен web-сервер.

mkdir /opt/www/html/postfixadmin/postfixadmin-log
chown -R apache:apache /opt/www/html/postfixadmin/postfixadmin-log

Создаем в этой папке файл .htaccess и настраиваем вывод содержимого папки с сортировкой по дате:

Options All Indexes
IndexOptions FancyIndexing FoldersFirst
#IndexOrderDefault Ascending Date
IndexOrderDefault Descending Date

Автоответчик (Vacation)

Данная возможность в PostfixAdmin реализована не очень удачно. Будем использовать аналогичный плагин к Dovecot (настройка описывается ниже)

Скрипты

Не все скрипты нужны, но на будущее будет легче быстро вносить изменения, если они уже будут готовы и настроены.
Первые два скрипта просто пишут логи. Последний - удаляет юзера из RoundCube и папку пользователя MailDir.

 Создаем скрипт, автоматом выполняемый после добавления новой почты через web-интерфейс PostfixAdmin addmail.sh

touch /opt/www/html/postfixadmin/addmail.sh
chown apache:apache /opt/www/html/postfixadmin/addmail.sh
chmod 0700 /opt/www/html/postfixadmin/addmail.sh

Содержимое скрипта:

#!/bin/bash
daten=`date -R`
printf "$daten \n CREATE mailbox: $1\n Domain: $2\n MailDir: $3\n Quota: $4 B\n\n" >> /opt/www/html/postfixadmin/postfixadmin-log/addmailbox.log

# if [[ -d /opt/mail/vmail/incron_mailuser_monitor/ ]]
# then
#     userdomain=(${1//@/ })
#     touch /opt/mail/vmail/incron_mailuser_monitor/${userdomain[1]}@${userdomain[0]}
# fi

Закомментированные строки в конце - раскомментим позже, когда будем настраивать автоматический мониторинг через incron папки "Отправленные" для каждого ящика.

Создаем скрипт, выполняемый после редактирования ящика через web-интерфейс PostfixAdmin editmail.sh

touch /opt/www/html/postfixadmin/editmail.sh
chown apache:apache /opt/www/html/postfixadmin/editmail.sh
chmod 0700 /opt/www/html/postfixadmin/editmail.sh

Содержимое скрипта:

#!/bin/bash
daten=`date -R`
printf "$daten \n EDIT mailbox: $1\n Domain: $2\n MailDir: $3\n Quota: $4 B\n\n" >> /opt/www/html/postfixadmin/postfixadmin-log/editmailbox.log

 

Создаем скрипт после удаления ящика через web-интерфейс PostfixAdmin (удаляет из RoundCube и папки* в папке почты домена) delmail.sh.
Почтовые папки удалит incron (т.к. владелец не "apache", а "vmail") !

touch /opt/www/html/postfixadmin/delmail.sh
chown apache:apache /opt/www/html/postfixadmin/delmail.sh
chmod 0700 /opt/www/html/postfixadmin/delmail.sh

Содержимое скрипта:

#!/bin/bash
daten=`date -R`

#del RoundCube user:
host="127.0.0.1"
user="_ROUNDCUBE_SQL_USER_ "
pass="_ROUNDCUBE_SQL_PASSWORD_"
db="_ROUNDCUBE_SQL_BASE_"

sql="SELECT user_id FROM users WHERE username = '$1'"
RES=`mysql --host=$host --port=3306 --user=$user --password=$pass --database=$db --execute="$sql"`

printf "$daten \n DELETE mailbox: $1\n Domain: $2\n MailDir: $3\n Quota: $4 B\n" >> /opt/www/html/postfixadmin/postfixadmin-log/delmailbox.log

printf " >>> RoundCube SQL-query START \n" >> /opt/www/html/postfixadmin/postfixadmin-log/delmailbox.log

for i in $RES; do
if [ "$i" != "user_id" ]; then
printf " ! FOUND RECORD: USER_ID = $i ! ( $1 )\n" >> /opt/www/html/postfixadmin/postfixadmin-log/delmailbox.log

# Find user_id:
printf " SQL: $sql \n" >> /opt/www/html/postfixadmin/postfixadmin-log/delmailbox.log

# Delete user from Cache:
sql="DELETE FROM cache WHERE user_id = $i"
RESD=`mysql --host=$host --port=3306 --user=$user --password=$pass --database=$db --execute="$sql"`
printf " SQL: $sql\n" >> /opt/www/html/postfixadmin/postfixadmin-log/delmailbox.log

# Delete user from ContactGroupMembers:
sql="DELETE FROM contactgroupmembers WHERE contactgroup_id IN (SELECT contactgroup_id FROM contactgroups WHERE user_id = $i)"
RESD=`mysql --host=$host --port=3306 --user=$user --password=$pass --database=$db --execute="$sql"`
printf " SQL: $sql\n" >> /opt/www/html/postfixadmin/postfixadmin-log/delmailbox.log

# Delete user from ContactGroups:
sql="DELETE FROM contactgroups WHERE user_id = $i"
RESD=`mysql --host=$host --port=3306 --user=$user --password=$pass --database=$db --execute="$sql"`
printf " SQL: $sql\n" >> /opt/www/html/postfixadmin/postfixadmin-log/delmailbox.log

# Delete user from Contacts:
sql="DELETE FROM contacts WHERE user_id = $i"
RESD=`mysql --host=$host --port=3306 --user=$user --password=$pass --database=$db --execute="$sql"`
printf " SQL: $sql\n" >> /opt/www/html/postfixadmin/postfixadmin-log/delmailbox.log

# Delete user from Identities:
sql="DELETE FROM identities WHERE user_id = $i"
RESD=`mysql --host=$host --port=3306 --user=$user --password=$pass --database=$db --execute="$sql"`
printf " SQL: $sql\n" >> /opt/www/html/postfixadmin/postfixadmin-log/delmailbox.log

# Delete user from Cache Messages
sql="DELETE FROM cache_messages WHERE user_id = $i"
RESD=`mysql --host=$host --port=3306 --user=$user --password=$pass --database=$db --execute="$sql"`
printf " SQL: $sql\n" >> /opt/www/html/postfixadmin/postfixadmin-log/delmailbox.log

# Delete user from Cache Thread
sql="DELETE FROM cache_thread WHERE user_id = $i"
RESD=`mysql --host=$host --port=3306 --user=$user --password=$pass --database=$db --execute="$sql"`
printf " SQL: $sql\n" >> /opt/www/html/postfixadmin/postfixadmin-log/delmailbox.log

# Delete user from Users:
sql="DELETE FROM users WHERE user_id = $i"
RESD=`mysql --host=$host --port=3306 --user=$user --password=$pass --database=$db --execute="$sql"`
printf " SQL: $sql\n" >> /opt/www/html/postfixadmin/postfixadmin-log/delmailbox.log

fi

done

printf " >>> RoundCube SQL-query END \n\n" >> /opt/www/html/postfixadmin/postfixadmin-log/delmailbox.log

# if [[ -d /opt/mail/vmail/incron_mailuser_monitor/ ]]
# then
#     userdomain=(${1//@/ })
#     if [[ -f /opt/mail/vmail/incron_mailuser_monitor/${userdomain[1]}@${userdomain[0]} ]]
#     then
#         rm /opt/mail/vmail/incron_mailuser_monitor/${userdomain[1]}@${userdomain[0]}
#     fi
# fi

Закомментированные строки в конце - раскомментим позже, когда будем настраивать автоматический мониторинг через incron папки "Отправленные" для каждого ящика
Возможно придется в скриптах откорректировать имена таблиц Postfixadmin.

Postfixadmin запускает скрипты приблизительно так:

/opt/www/html/postfixadmin/scripts/editmail.sh Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в вашем браузере должен быть включен Javascript.' 'dest.loc' 'dest.loc/test/' '1234567890'

Если пробовать скрипты из консоли - надо не забывать менять пользователя, в т.ч. у лог-файлов, т.к. будет "permission denied". Если что не так - смотреть error.log Apache2.

 Установка Postfix и Dovecot

Предпологаем, что на сервере уже установлены openssl и mysql. Установка и настройка данного ПО не рассматривается в рамках этой статьи.

Прежде чем начать установку Postfix, необходимо удалить из системы какие-либо установленные программы обработки почты (sendmail и подобные).

Устанавливаем необходимые пакеты:

yum install postfix dovecot dovecot-mysql dovecot-pigeonhole

Проверяем установку:

postconf -a
cyrus
dovecot

Конфигурационные файлы Postfix

В процессе установки пакета были созданы пользователь и группа postfix. От имени этого пользователя будет работать наш почтовый сервер.

Для дальнейшей работы нам необходимо создать еще одного пользователя и группу (для работы с виртуальными почтовыми ящиками):

groupadd -r -g 5000 vmail
useradd -r -g vmail -u 5000 vmail -d /opt/mail/vmail -m

Не забываем сделать копии основных конфигурационных файлов:

cp /etc/postfix/main.cf /etc/postfix/main.cf.orig
cp /etc/postfix/master.cf /etc/postfix/master.cf.orig

И приступаем к настройке.
Файл master.cf должен быть примерно такого содержания:

#
# Postfix master process configuration file. For details on the format
# of the file, see the master(5) manual page (command: "man 5 master").
#
#
# ==========================================================================
# service type private unpriv chroot wakeup maxproc command + args
#                   (yes)   (yes)   (yes)   (never)   (100)
# ==========================================================================

#smtp      inet  n       -       -       -       -       smtpd
# +++ Postscreen +++
smtpd     pass  -       -       n       -       -       smtpd
smtp       inet   n       -       n       -      1       postscreen
# -o soft_bounce=yes
tlsproxy  unix   -        -       n       -      0       tlsproxy
#dnsblog   unix  -       -       n       -       0       dnsblog
#
# Remap 25 port to 587 port
submission inet n       -       -       -       -       smtpd
  -o smtpd_tls_security_level=encrypt
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_sasl_type=dovecot
  -o smtpd_sasl_path=private/auth
  -o smtpd_sasl_security_options=noanonymous
  -o smtpd_sender_login_maps=mysql:/etc/postfix/mysql_virtual_maps.cf
  -o smtpd_client_restrictions=permit_sasl_authenticated,reject
  -o smtpd_sender_restrictions=reject_sender_login_mismatch
  -o smtpd_recipient_restrictions=reject_unverified_recipient,reject_unknown_recipient_domain,reject_non_fqdn_recipient,permit_sasl_authenticated,reject
#smtps     inet  n       -       -       -       -       smtpd
#628       inet  n       -       -       -       -       qmqpd
pickup     fifo  n       -       -       60      1       pickup
cleanup   unix  n       -       -       -       0       cleanup
qmgr       fifo  n       -       n       300     1       qmgr
#qmgr      fifo  n       -       -       300     1       oqmgr
tlsmgr      unix  -       -       -       1000?   1       tlsmgr
rewrite      unix  -       -       -       -       -       trivial-rewrite
bounce     unix  -       -       -       -       0       bounce
defer         unix  -       -       -       -       0       bounce
trace         unix  -       -       -       -       0       bounce
verify         unix  -       -       -       -       1       verify
flush         unix  n       -      -       1000?     0       flush
proxymap  unix  -       -       n       -       -       proxymap
smtp       unix  -       -       -       -       -       smtp
relay       unix  -       -       -       -       -       smtp
      -o fallback_relay=
      -o smtp_helo_timeout=5 -o smtp_connect_timeout=5
showq     unix  n       -       -       -       -       showq
error       unix  -       -       -       -       -       error
discard    unix  -       -       -       -       -       discard
#local      unix  -       n       n       -       -       local
#virtual    unix  -       n       n       -       -       virtual
lmtp       unix  -       -       -       -       -       lmtp
anvil       unix  -       -       -       -       1       anvil
scache    unix  -       -       -       -       1       scache
#
# ====================================================================
# Interfaces to non-Postfix software. Be sure to examine the manual
# pages of the non-Postfix software to find out what options it wants.
#
# Many of the following services use the Postfix pipe(8) delivery
# agent. See the pipe(8) man page for information about ${recipient}
# and other message envelope options.
# ====================================================================
#
# maildrop. See the Postfix MAILDROP_README file for details.
# Also specify in main.cf: maildrop_destination_recipient_limit=1
#
maildrop  unix  -       n       n       -       -       pipe
  flags=DRhu user=vmail argv=/usr/bin/maildrop -d ${recipient}
#
# See the Postfix UUCP_README file for configuration details.
#
uucp unix -       n       n       -       -       pipe
  flags=Fqhu user=uucp argv=uux -r -n -z -a$sender - $nexthop!rmail ($recipient)
#
# Other external delivery methods.
#
ifmail    unix  -       n       n       -       -       pipe
  flags=F user=ftn argv=/usr/lib/ifmail/ifmail -r $nexthop ($recipient)
bsmtp     unix  -       n       n       -       -       pipe
  flags=Fq. user=bsmtp argv=/usr/lib/bsmtp/bsmtp -t$nexthop -f$sender $recipient
scalemail-backend  unix  -       n       n       -       2       pipe
  flags=R user=scalemail argv=/usr/lib/scalemail/bin/scalemail-store ${nexthop} ${user} ${extension}
mailman   unix  -       n       n       -       -       pipe
  flags=FR user=list argv=/usr/lib/mailman/bin/postfix-to-mailman.py
  ${nexthop} ${user}
# python-postfix-policyd-spf
policyd-spf  unix  -       n       n       -       0       spawn
  user=nobody argv=/usr/bin/python /usr/bin/policyd-spf
retry       unix  -       -       -       -       -       error

Файл main.cf приводим приблизительно к такому виду:

# +++ Debug:
#debug_peer_level = 2
#debug_peer_list = 127.0.0.1
#debug_peer_list = 127.0.0.1, dest.loc

#syslog_facility = mail

smtpd_banner = $myhostname ESMTP
# +
# smtpd_banner = $myhostname ESMTP $mail_name (Debian/GNU)
#smtpd_banner = $myhostname ESMTP ($mail_version)

biff = no

# user@host => user@host.$mydomain (default=yes)
append_dot_mydomain = no

# + (help doc postfix)
#readme_directory = no

# + mydomain
mydomain = dest.loc

# + myorigin (add after '@' for output)
#myorigin = /etc/mailname
#myorigin = mail.dest.loc
myorigin = $mydomain

myhostname = mail.dest.loc
inet_protocols = ipv4

# !!! Do not use $mydomain for mydestination !!!
#mydestination = $myhostname, localhost.$mydomain
mydestination = $myhostname, localhost, localhost.$mydomain

#mynetworks_style = subnet
mynetworks_style = host
# + mynetworks
# Trusted networks
# If this parameter apply - "mynetworks_style" ignore
mynetworks = 127.0.0.1/32

#inet_interfaces = 1.2.3.4
# +
#inet_interfaces = all
inet_interfaces = 192.168.20.104, 127.0.0.1

# Replace address "user@host" => "user@$myorigin " (default: yes)
#append_at_myorigin = no

#masquerade_domains =
#masquerade_exceptions = root
#masquerade_classes = envelope_sender, header_sender, header_recipient

# +
# Authorisation - dovecot:
# smtpd_sasl_type = dovecot
#smtpd_sasl_path = private/auth
#smtpd_sasl_auth_enable = yes

# + relayhost (default - no relay host)
#relayhost =

# +
# BCC
# !!! Move to master.cf !!!
# recipient_bcc_maps = type:table
#recipient_bcc_maps = hash:/etc/postfix/recepient_bcc
#always_bcc = Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в вашем браузере должен быть включен Javascript.
#receive_override_options = no_address_mappings
#sender_bcc_maps = mysql:/etc/postfix/mysql_bcc_mailbox_maps.cf
sender_bcc_maps = mysql:/etc/postfix/mysql_bcc_mailbox_maps.cf, mysql:/etc/postfix/mysql_bcc_domain_maps.cf

# +
# parameter specifies the directory where UNIX-style mailboxes are kept.
# default # mailbox file is /var/spool/mail/user or /var/mail/user
# mail_spool_directory =
 
# +
# For a non virtual user setup ( as when Dovecot mail_location = maildir:~/.maildir ) :
mailbox_transport = lmtp:unix:private/dovecot-lmtp
#mailbox_transport = local
 
# address MAIL FROM for probe with "verify" (default=double-bounce@$myorigin)
address_verify_sender =
 
# This uses non-persistent storage only.
# empty = disable cache
# default = btree:$data_directory/verify_cache          # ($data_directory = /var/lib/postfix)
# address_verify_map =
 
# +
#virtual_destination_recipient_limit = 1
# +
# Version Postfix > 2.9
default_destination_recipient_limit = 1
#dovecot_destination_recipient_limit = 1
 
# !!!
# not needed if the Dovecot LDA or LMTP is used
# (these options are only relevant for the Postfix LDA: "virtual"):
#virtual_mailbox_base = /var/vmail
# End symbol "/" - maildir format
#virtual_mailbox_base = /var/vmail/
#virtual_minimum_uid = 100
#virtual_uid_maps = static:5000
#virtual_gid_maps = static:5000
 
#virtual_mailbox_domains = dest.loc, dest1.loc
# virtual_mailbox_domains = $mydomain, mysql:/etc/postfix/mysql_virtual_domains.cf
# virtual_mailbox_domains = $mydomain
virtual_mailbox_domains = mysql:/etc/postfix/mysql_virtual_domains.cf
 
# +
virtual_mailbox_maps = mysql:/etc/postfix/mysql_virtual_maps.cf
 
#virtual_alias_maps = hash:/etc/postfix/virtual
# +
#virtual_alias_maps = mysql:/etc/postfix/mysql_virtual_alias_maps.cf
virtual_alias_maps = mysql:/etc/postfix/mysql_virtual_alias_domain_maps.cf,mysql:/etc/postfix/mysql_virtual_alias_maps.cf
 
# +
#virtual_transport = dovecot
#virtual_transport = lmtp:unix:private/dovecot
virtual_transport = lmtp:unix:private/dovecot-lmtp
 
# Use "strict_rfc821_envelopes = no" to accept "RCPT TO:>".
# Postfix will ignore the "User Name" part and deliver to the  address.
strict_rfc821_envelopes = yes
 
# Disable for: stops some methods used to harvest email addresses during the connection to the server.
# def: no
# disable_vrfy_command = yes
 
 
# RULES and POLICES
 
smtpd_helo_required = yes
 
# * Note
# If a remote SMTP client is authenticated, the permit_sasl_authenticated access restriction can be used to permit relay (for dovecot?) access.
 
# !!! permit_sasl_authenticated - MOVE TO master.cf for submission (587 port for MUA)
 
# reject - for all others, which do not permit
# permit - for all others, which do not reject
 
# note! Postfix no check MX. need Policy
 
smtpd_client_restrictions =
 permit_mynetworks,
 reject_unknown_client_hostname,
 permit_sasl_authenticated,
# check spam (blacklist servers)
# reject_rhsbl_client blackhole.securitysage.com,
# reject_rhsbl_sender blackhole.securitysage.com,
# reject_rbl_client bl.spamcop.net,
# reject_rbl_client dnsbl.sorbs.net,
# reject_rbl_client zen.spamhaus.org,
# reject_rbl_client dnsbl-1.uceprotect.net
#
# reject_rbl_client zombie.dnsbl.sorbs.net,
# reject_rbl_client cbl.abuseat.org,
# reject_rbl_client multihop.dsbl.org,
# reject_rbl_client work.rsbs.express.ru,
 permit
# reject_unknown_reverse_client_hostname
# check_client_access hash:/etc/postfix/client_access
 
 
smtpd_helo_restrictions =
 permit_mynetworks,
 reject_invalid_helo_hostname,
 reject_non_fqdn_helo_hostname,
 reject_unknown_helo_hostname,
 check_helo_access hash:/etc/postfix/hello_access,
 permit
 
smtpd_sender_restrictions =
 reject_unknown_sender_domain,
 reject_non_fqdn_sender,
# reject_unverified_sender, - rejected automailers? Maybe make trust list?
 permit
 
smtpd_recipient_restrictions =
 permit_mynetworks,
 permit_sasl_authenticated,
 reject_unknown_recipient_domain,
 reject_non_fqdn_recipient,
 reject_unverified_recipient,
 reject_unauth_destination,
# postgrey:
 check_policy_service inet:127.0.0.1:10023,
# policy-spf (see master.cf):
 check_policy_service unix:private/policyd-spf,
 permit
#127.0.0.1:10023_time_limit = 180  ##Only for line by "master.cf"
## check_policy_service unix:public/postgrey
# check_recipient_access hash:/etc/postfix/maps/access_recipient,
 
#smtpd_policy_service_max_idle = 300
#smtpd_policy_service_max_ttl = 1000
#smtpd_policy_service_timeout = 100
command_time_limit = 240
#policyd-spf_time_limit = 3600
policyd-spf_time_limit = 180
 
# Need: install dkim-milter and sid-milter
##smtpd_milters = unix:public/dkim-filter
##non_smtpd_milters = unix:public/dkim-filter
##milter_protocol = 6
 
# DKIM + ClamAV
# OpenDkim with Milter:
milter_default_action = accept
milter_protocol = 6
#smtpd_milters = inet:localhost:8891
#non_smtpd_milters = inet:localhost:8891
smtpd_milters = inet:127.0.0.1:8891, inet:127.0.0.1:7357
non_smtpd_milters = inet:127.0.0.1:8891, inet:127.0.0.1:7357
 
# +++ Postscreen +++
#postscreen_watchdog_timeout = 10 (default: 10s)
#postscreen_cache_cleanup_interval (default: 12h)
#postscreen_cache_retention_time (default: 7d)
postscreen_cache_retention_time = 90d
postscreen_access_list = permit_mynetworks,
  cidr:/etc/postfix/postscreen_access.cidr
#postscreen_reject_footer = Postscreen Test
#postscreen_dnsbl_threshold = 2
#postscreen_dnsbl_sites = zen.spamhaus.org*2
#    bl.spamcop.net*1 b.barracudacentral.org*1
#postscreen_dnsbl_reply_map = texthash:/etc/postfix/dnsbl_reply
postscreen_cache_map = btree:$data_directory/postscreen_cache
# wait greet banner before send:
postscreen_greet_banner = Hello from $mydomain !
postscreen_greet_wait = 10s
# reject 550 and logging:
postscreen_greet_action = enforce
# wait answr after command:
postscreen_pipelining_enable = yes
# reject 550 and logging:
postscreen_pipelining_action = enforce
# non-SMTP command and header ("...: text")
postscreen_non_smtp_command_enable = yes
postscreen_forbidden_commands = CONNECT, GET, POST
# reject 550 and logging:
postscreen_non_smtp_command_action = enforce
# test end-symbols:
postscreen_bare_newline_enable = yes
# reject 550 and logging:
postscreen_bare_newline_action = enforce
 
#unknown_address_reject_code = 554
#unknown_hostname_reject_code = 554
#unknown_client_reject_code = 554
#unknown_local_recipient_reject_code = 550
#unverified_recipient_reject_code = 450
 
smtpd_tls_cert_file=/etc/postfix/ssl.cert.pem
smtpd_tls_key_file=/etc/postfix/ssl.key.pem
 
# (old - "smtpd_use_tls"). Value: "no", "may" (at client), "encript" (TLS only)
# setting "smtpd_tls_security_level = encrypt" implies "smtpd_tls_auth_only = yes"
smtpd_tls_security_level = may
smtp_tls_security_level = may
smtpd_tls_ask_ccert = yes
 
smtpd_tls_loglevel = 1
smtp_tls_loglevel = 1
 
smtpd_tls_received_header = yes
smtpd_tls_session_cache_database = btree:/var/lib/postfix/smtpd_scache
smtp_tls_session_cache_database = btree:/var/lib/postfix/smtp_scache
#smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
#smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache
 
# +
# data_directory > Postfix 2.5
# Not need - default!
#data_directory = /var/lib/postfix
 
# For local users:
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
 
#canonical_maps = hash:/etc/postfix/canonical
 
smtp_generic_maps = hash:/etc/postfix/aliases_smtp_output
lmtp_generic_maps = hash:/etc/postfix/aliases_lmtp
#lmtp_generic_maps = mysql:/etc/postfix/mysql_virtual_alias_domain_maps.cf,mysql:/etc/postfix/mysql_virtual_alias_maps.cf,hash:/etc/postfix/aliases_lmtp
 
# +
# after "user" before "@" extension - Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в вашем браузере должен быть включен Javascript.
recipient_delimiter = +
 
#local_recipient_maps = unix:passwd.byname $alias_maps
#local_recipient_maps = proxy:unix:passwd.byname $alias_maps
#local_recipient_maps =
 
#mailbox_size_limit = 0
mailbox_size_limit = 1024000000
message_size_limit = 20480000
 
# Default:
#queue_run_delay = 300s
#minimal_backoff_time = 300s
#master_service_disable =
 
#content_filter = Email content filter
queue_directory = /var/spool/postfix
 
# Mail notice (default "postmaster") :
delay_notice_recipient = Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в вашем браузере должен быть включен Javascript.
bounce_notice_recipient = Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в вашем браузере должен быть включен Javascript.
2bounce_notice_recipient = Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в вашем браузере должен быть включен Javascript.
error_notice_recipient = Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в вашем браузере должен быть включен Javascript.

reject_rbl_client - имеет смысл включать только на период спам-атак. Иначе они могут сильно навредить, поскольку сторонние сервисы: во-первых - часто ошибаются, во-вторых - замедляют работу почты и создают дополнительную нагрузку.

reject_unverified_sender - аналогично, поскольку проверка всех отправителей приведет к тому, что не будут доходить письма списков рассылки, которые чаще всего не принимают обратных писем (при проверке используется эмуляция отправки обратного письма).

Дополнительные файлы с данными и параметрами.

Форматы таблиц данных - в основном "hash" (возможны "cidr" и др.). После создания файла формата "hash", должна быть создана база, командой postmap (см. ниже пример). Особенностью некоторых форматов является то, что после изменений необходимо перечитать (или перезагрузить) Postfix ("postfix reload"), иначе изменения не будут задействованы (зато выше скорость чтения данных).

ВАЖНО! Необходимо создать файлы и базы со списками, которые были подключены в конфиге выше, даже если они будут пустыми.

Файл для правила "check_helo_access hash:/etc/postfix/hello_access"

mail.dest.loc REJECT Don't use my server name
dest.loc REJECT Don't use my server name

Затем выполняем команду:

postmap /etc/postfix/hello_access

Тестирование может выглядеть примерно так (в консоли из внешнего сервера - после окончания всей настройки!):

# telnet mail.domain.tld 25
Trying ip1.ip2.ip3.ip4...
Connected to mail.domain.tld.
Escape character is '^]'.
220 mail.domain.tld ESMTP

# helo mail.domain.tld
250 mail.domain.tld

# mail from:
250 2.1.0 Ok

# rcpt to:
554 5.7.1 : Helo command rejected: Don't use my server name

# quit
221 2.0.0 Bye

Файл для правила "check_client_access hash:/etc/postfix/client_access"

ip.ip.ip.ip ПРАВИЛО

ВАЖНО! - необходимо заменить "ip.ip.ip.ip" и "ПРАВИЛО" на те для которых это будет выполняться (например "1.2.3.4 REJECT").
Выполняем :

postmap /etc/postfix/client_access

Аналогично, если это будет использоваться, необходимо создать файлы и базы (таблицы) для правил:

"check_recipient_access hash:/etc/postfix/maps/access_recipient" - список получателей и правил для них (можно отсекать прием для ящика рассылки)

"canonical_maps = hash:/etc/postfix/canonical"

Прежде, чем демон cleanup передаст входящую почту в incoming, он использует таблицу канонического преобразования, чтобы переписать все адреса в окружении сообщения, и в заголовках сообщения, локальных или удаленных. Маппинг канонических адресов удобен для приведения указанных имен к виду "Firstname.Lastname", или для замены недействительных доменов на допустимые. В дополнение к каноническому маппингу, использующемуся для обоих адресов: отправителя и получателя, можно указать отдельные канонические таблицы, только для адреса отправителя или только для адреса получателя.

Канонические преобразования sender_canonical_maps и recipient_canonical_maps происходят до общих canonical_maps.

Пример таблицы замены в файле /etc/postfix/cononical

vasy       Vasiliy.Pupkin

ВАЖНО! Нельзя забывать, что "sender" и "recipient" зависят от направления почты - входящая/исходящая. Т.е. "Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в вашем браузере должен быть включен Javascript." может быть "sender" в случае отправки почты от его имени, и тогда для него сработает правило sender_canonical_maps, но в случае приема почты в его адрес, он уже будет "recipient", и тогда правило sender_canonical_maps его не коснется.
Протестировать можно следующим образом:
Создадим ящики "Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в вашем браузере должен быть включен Javascript." и "Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в вашем браузере должен быть включен Javascript.".
Сделаем "Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в вашем браузере должен быть включен Javascript." алиасом для "Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в вашем браузере должен быть включен Javascript." с использованием canonical_maps.

 

  • При получении почты с внешнего адреса на подопытный "Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в вашем браузере должен быть включен Javascript.", письмо доставляется в ящик "Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в вашем браузере должен быть включен Javascript.". В письме изменяется только "Delivered-To: ;" и встречается упоминание в верхнем "Received: ..." - "... for ;; ...".
    В остальных "Received: ..." фигурирует "... for ;; ...", как и в "To: ... ;"
  • При отправке почты от "Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в вашем браузере должен быть включен Javascript." (в т.ч. через sendmail) на внешний адрес, изучение заголовков у получателя показывает, что все "Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в вашем браузере должен быть включен Javascript." заменены на "Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в вашем браузере должен быть включен Javascript.". Единственное место, где может остаться упоминание о "Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в вашем браузере должен быть включен Javascript." - это "From: ; (test)".
    Важно также то, что цифровая подпись (DKIM) валидна - по-видимому наложение подписи происходит после обработки canonical_maps.

Канонические преобразования могут быть отключены принудительно - глобально или избирательно.

"smtp_generic_maps = hash:/etc/postfix/aliases_smtp_output" - подмена локальных адресов отправителя для почты наружу.

Параметр smtp_generic_maps производит подмену адресов отправителей только для почты, уходящей за пределы домена (через SMTP-клиент). Можно указывать конкретные адреса, а можно только домены.

ВАЖНО! Могут возникнуть проблемы при совместном использовании smtp_generic_maps и DKIM

* С версии 2.3 можно аналогично для LMTP использовать lmtp_generic_maps.

Например создаем файл /etc/postfix/aliases_smtp_output с содержимым:

root     Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в вашем браузере должен быть включен Javascript.

Выполняем команду:

postmap /etc/postfix/aliases_smtp_output

Отправим из консоли почту для "Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в вашем браузере должен быть включен Javascript.", находясь под "root"

echo "Test generic mapping" | sendmail  Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в вашем браузере должен быть включен Javascript.

Пара замечаний по примеру:

  • Поскольку обработка идет только для SMTP-клиента, то замена адреса будет произведена только для исходящей (наружу) почты
  • При попытке подмены адреса получателя, происходит следующее - сервер пытается доставить на изначальный домен письмо с новым получателем. Поэтому если там его нет, то доставка не произойдет.
  • Не забываем про очередность - подмена адресов этим способом происходит после формирования BCC (а также после канонического преобразования и т.п.). Например, sender_bcc_maps - скрытая копия локального отправителя "root", будет сопоставлена изначальному (не измененному) отправителю, хотя адресату за пределы домена письмо придет с измененным отправителем. Кроме того, скрытая копия так-же может быть будет пропущена через преобразование адресов - если она отправляется наружу.
  • В приведенном выше примере письмо удаленному получателю поступит почти без следов "root". Отправитель будет заменен везде, за исключением одного упоминания From: Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в вашем браузере должен быть включен Javascript. (root) .

Этим способом можно, например, организовать подмену адреса отправителя для пользователя "apache" для писем отправляемых сайтом через PHP

"lmtp_generic_maps = hash:/etc/postfix/aliases_lmtp".

  • Поскольку обрабатывается почта проходящая только через LMTP, то замена адреса будет произведена как для входящей (снаружи) почты, так и для почты отправляемой в пределах родного домена (друг другу), но не затронет почту, отправляемую изнутри наружу.
  • Этот параметр производит замену адреса как отправителя, так и получателя (баг или фича?) снаружи внутрь, и изнутри - внутрь.
  • От отправителя он не оставляет почти никаких следов (кроме хоста MTA и может быть упоминания в "X-Sender:").
  • С получателем сложнее. Он изменяется в "Delivered-To:" и "To:" (и доставляется на измененный адрес), но остается и след первоначального адреса - упоминание в каждом "Received:" после "for"
  • Обработка адреса происходит после создания BCC. Поэтому, если скрытая копия пройдет через LMTP (внутрь сервера), то ее адрес тоже может быть подвергнут обработке.

ВАЖНО! Для вышеперечисленных файлов обязательно завершающее создание базы для каждого командой: postmap ...

Файлы для правил:

  • "alias_maps = hash:/etc/aliases"
  • "alias_database = hash:/etc/aliases"

Файл /etc/aliases обычно присутствует в системе изначально. Предназначен для доставки почты локальным пользователям. Например:

root:    Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в вашем браузере должен быть включен Javascript.

Локальная почта, предназначенная для пользователя "root" перенаправится на адрес Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в вашем браузере должен быть включен Javascript.
После внесений изменений в данный файл необходимо пересобрать базу данных командой

newaliases

Файл для правила "postscreen_access_list permit_mynetworks, cidr:/etc/postfix/postscreen_access.cidr" (если будет использоваться специальный список доступа для Postscreen)

ip.ip.ip.ip ПРАВИЛО

ВАЖНО! - необходимо заменить "ip.ip.ip.ip" и "ПРАВИЛО" на те для которых это будет выполняться (например "1.2.3.4/32 permit").
Этот формат не требует никаких последующих действий для создания базы.

ВАЖНО! Некоторые файлы могут быть пустыми, но они должны быть созданы!

После создания всех файлов необходимо выполнить команду:

postfix reload

Создадим файлы, хранящие SQL-запросы, проверяя имена таблиц и полей

/etc/postfix/mysql_virtual_domains.cf

user = _POSTFIXADMIN_SQL_USER_
password = _POSTFIXADMIN_SQL_PASSWORD_
hosts = 127.0.0.1
dbname = _POSTFIXADMIN_SQL_BASE_
query = SELECT domain FROM domain WHERE domain = '%s' AND backupmx = '0' AND active = '1'

/etc/postfix/mysql_virtual_maps.cf

user = _POSTFIXADMIN_SQL_USER_
password = _POSTFIXADMIN_SQL_PASSWORD_
hosts = 127.0.0.1
dbname = _POSTFIXADMIN_SQL_BASE_
query = SELECT username FROM mailbox WHERE username='%s' AND active = '1'

Запрос для авто-BCC ящика зарегистрированного пользователя /etc/postfix/mysql_bcc_mailbox_maps.cf

user = _POSTFIXADMIN_SQL_USER_
password = _POSTFIXADMIN_SQL_PASSWORD_
hosts = 127.0.0.1
dbname = _POSTFIXADMIN_SQL_BASE_
query = SELECT CONCAT('%u', '+bccflag', '@', '%d') FROM mailbox WHERE username='%s' AND active = '1'

Запрос ящика для авто-BCC не зарегистрированных пользователей родного домена /etc/posfix/mysql_bcc_domain_maps.cf

user = _POSTFIXADMIN_SQL_USER_
password = _POSTFIXADMIN_SQL_PASSWORD_
hosts = 127.0.0.1
dbname = _POSTFIXADMIN_SQL_BASE_
query = SELECT Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в вашем браузере должен быть включен Javascript.' FROM domain WHERE domain='%d' AND active = '1'

eMail-алиасы /etc/postfix/mysql_virtual_alias_maps.cf

user = _POSTFIXADMIN_SQL_USER_
password = _POSTFIXADMIN_SQL_PASSWORD_
hosts = 127.0.0.1
dbname = _POSTFIXADMIN_SQL_BASE_
query = SELECT goto FROM alias WHERE address='%s' AND active = '1'

Доменные алиасы /etc/postfix/mysql_virtual_alias_domain.cf

user = _POSTFIXADMIN_SQL_USER_
password = _POSTFIXADMIN_SQL_PASSWORD_
hosts = 127.0.0.1
dbname = _POSTFIXADMIN_SQL_BASE_
query = SELECT CONCAT('%u', '@', target_domain) FROM alias_domain WHERE alias_domain = '%d' AND active = '1'

Выставим права на все конфиги:

chgrp postfix /etc/postfix/*.cf
chmod u=rw,g=r,o= /etc/postfix/*.cf

ВАЖНО! Здесь параметр hosts надо указывать тот же, что указан в "my.cnf" MySQL (bind-address)!

После того, как все подготовили, перезапускаем postfix:

systemctl restart postfix

Вносим первые данные в наш почтовый сервер.

Теперь вернемся к Posfixadmin и внесем первые данные через его web-интерфейс по адресу: https://dest.loc/postfixadmin/

  1. Внесем свой новый домен - dest.loc
  2. Временно внесем еще один тестовый домен - test.com (его потом надо будет удалить !!!)
  3. Алиас ДЛЯ домена dest.loc - вся почта домена test.com перенаправляется на dest.loc
  4. Создаем ящик - postmaster@dest.loc
  5. Превращаем ящик postmaster@dest.loc в алиас для test@dest.loc (этот ящик заводить не нужно - достаточно вписать его, как целевой для ящика-алиаса postmaster@dest.loc).
  6. Обязательно (!) создаем ящик - bccsnd@dest.loc

* Тут важно не запутаться. В редактировании домена создется алиас ДЛЯ редактируемого домена, а в редактировании ящика - уже сам редактируемый ящик превращается в алиас для перечисленных.

** Кстати при создании ящика обязательно надо слать приветственное письмо, т.к. за создание папки отвечает Dovecot (Posfix вообще к этим папкам не имеет доступа - любой физический доступ осуществляется ЧЕРЕЗ Dovecot).

*** Аутентификация будет происходить очень интересно. Наличие/отсутствие имен ящиков, Postfix будет проверять сам в таблицах PostfixAdmin. Пароли Postfix в своих таблицах запрашивать не будет - они будут проверяться средствами Dovecot, но... в таблицах PostfixAdmin. :)

Проверки.

Проверяем домен:

postmap -q dest.loc mysql:/etc/postfix/mysql_virtual_domains.cf

должно вернуть dest.loc

Юзер@домен найден:

postmap -q Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в вашем браузере должен быть включен Javascript. mysql:/etc/postfix/mysql_virtual_maps.cf

должно вернуть Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в вашем браузере должен быть включен Javascript.

BCC - Юзер@домен найден:

postmap -q Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в вашем браузере должен быть включен Javascript. mysql:/etc/postfix/mysql_bcc_mailbox_maps.cf

должно вернуть Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в вашем браузере должен быть включен Javascript.

BCC - Юзер@домен НЕ найден:

postmap -q Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в вашем браузере должен быть включен Javascript. mysql:/etc/postfix/mysql_bcc_mailbox_maps.cf

Пустой ответ

BCC - домен найден:

postmap -q Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в вашем браузере должен быть включен Javascript. mysql:/etc/postfix/mysql_bcc_domain_maps.cf

должно вернуть Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в вашем браузере должен быть включен Javascript.

BCC - Юзер@домен НЕ найден:

postmap -q Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в вашем браузере должен быть включен Javascript. mysql:/etc/postfix/mysql_bcc_domain_maps.cf

Пустой ответ

Для ящика-алиаса:
* вернет список ящиков для пересылки (рассылки) для ящика X - список может содержать любые валидные (домены ящиков проверяется через DNS) имена (напр ***@gmail.com)!

postmap -q Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в вашем браузере должен быть включен Javascript. mysql:/etc/postfix/mysql_virtual_alias_maps.cf

должно вернуть Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в вашем браузере должен быть включен Javascript.'

Для домена-алиаса:
В данном экзотическом варианте - вернет список рассылки ящика-алиаса, ДЛЯ которого запрашиваемый ящик является алиасом.
* К алиас-домену привязываются имена ВСЕХ ящиков основного домена, но ТОЛЬКО те, что есть в основном домене.

postmap -q Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в вашем браузере должен быть включен Javascript. mysql:/etc/postfix/mysql_virtual_alias_domain_maps.cf

должно вернуть Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в вашем браузере должен быть включен Javascript.'

Postgrey

Это проверенная временем технология, суть которой в том, что для "новичков" (неизвестных ранее) допуск дается только после проверки их настойчивости - не с первого раза. Сначала происходит мягкий отказ (с кодом напр.: "450"), после чего ожидаются повторные попытки. Расчет идет на то, что серверы спамеров экономят ресурсы и не тратят время на стандартную процедуру повторных попыток, которая по умолчанию используется большинством нормальных MTA. Далее работает уже белый список, в котором информация без обновления хранится около месяца (это настраивается) и отказов уже не происходит - проверенная однажды почта, в дальнейшем принимается сразу.

В ОС Rosa Cobalt данный пакет отсутствует в репозитариях. В CentOS он присутствует в репозитариях EPEL. Поэтому далее речь пойдет на реализации для CentOS.

Устанавливается просто:

yum install postgrey

Postgrey сохраняет записи-триплеты вида: "IP_клиента"/"Отправитель"/"Получатель". в базах, которые по умолчанию находятся /var/lib/postgrey
Белые списки клиентов: /etc/postgrey/whitelist_clients
Белые списки получателей: /etc/postgrey/whitelist_recipients
Подключение Postgrey к Postfix находится в файле /etc/postfix/main.cf (для Rosa Cobalt их нужно отключить):

...
smtpd_recipient_restrictions = ...,
 ...,
 check_policy_service inet:127.0.0.1:10023
...

Параметр check_policy_service лучше указывать после всех остальных "smtpd_recipient_restrictions". Важно, чтобы он был указан после reject_unauth_destination, иначе система превратиться в открытый релей. Очевидно также, что Postgrey-policy нужно подключать до "policy-spf", т.к. нет смысла производить эти проверки в обратном порядке.

Настройки самого Postgrey хранятся в файле /etc/default/postgrey . Можно увеличить в нем, например, задержку писем от "новичков" до 30 минут (по умолчанию - 300 сек), уменьшить время неприкосновенности уже "допущенных" до 10 дней ( по умолчанию - 35 дней, и любая активность рестартит этот срок), и после 20 принятых писем автоматом переносить клиента в белый список (по умолчанию - 5). Настраиваем Postgrey в файле /etc/default/postgrey:

...
POSTGREY_OPTS="--inet=10023 --delay=200 --max-age=40 --auto-whitelist-clients=4"
...

200 сек отказывать новичкам (по умолчанию 300 сек),
40 дней без обновления хранить информацию о них в белом листе (по умолчанию 35 дней),
4 раза принимать письма с проверкой, после чего автоматом добавлять в белый лист.
Перезапускаем сервис:

systemctl restart postgrey

Получение отчета из лога о текущих "отказниках":

cat /var/log/maillog | postgreyreport --nosingle_line --check_sender=mx,a --show_tries --separate_by_subnet=":-----------------------\n"

Postscreen

Зомби-блокировщик Postscreen - это первый уровень защиты, доступных в Postfix. Postscreen доступен в Postfix с версии 2.8 и выше, а некоторые функции (например "cache sharing") - с версии 2.9.
ВАЖНО! Postscreen не может сосуществовать на одном порту с MUA!

Большинство писем является спамом, а большинство спама рассылается зомби-ботами. Зомби-боты - это зараженные компьютеры, хозяева которых могут и не знать о том, что они источники спама. Разработчик Postfix Wietse Venema предсказывает, что в дальнейшем проблема зомби-ботов будет нарастать и ситуация будет только ухудшаться. Идея защиты состоит в том, что такие компьютеры, как правило, не соблюдают все стандарты SMTP-протокола, и кроме того, могут проявлять неестественную настойчивость, подключаясь после отказа снова и снова. Для того чтобы не нагружать smtpd, и используется postscreen. Postscreen проводит ряд тестов SMTP-клиента, и, если выявляет признаки "зомби", удерживает его на эмуляции SMTP-сессии, не давая подключиться к основному демону - smtpd.

При этом Postscreen поддерживает временный белый список для клиентов, к которым эти тесты не применяются.

Настройка в конфигах "/etc/postfix/master.cf" и "/etc/postfix/main.cf", описанные ранее.

Там же - описание "/etc/postfix/postscreen_access.cidr" для параметра postscreen_access_list в файле "/etc/postfix/main.cf".

 Polycyd-SPF

SPF - это TXT-запись в DNS, в которой, в простейшем варианте должен быть указан IP сервера, которому разрешено отправлять почту.

Описание того как это должно выглядеть в DNS описывалось выше.

ОС Rosa Cobalt данный пакет не входит. В CentOS он присутствует в репозитариях EPEL.Установка:

yum install pypolicyd-spf

Настройка в конфигах "/etc/postfix/master.cf" и "/etc/postfix/main.cf", описанных выше.

Кроме того проверяем и донастраиваем файл /etc/python-policyd-spf/policyd-spf.conf:

# For a fully commented sample config file see policyd-spf.conf.commented

debugLevel = 0
defaultSeedOnly = 0

#HELO_reject = SPF_Not_Pass
HELO_reject = False
#Mail_From_reject = Fail
Mail_From_reject = False

PermError_reject = False
TempError_Defer = False

#skip_addresses = 127.0.0.0/8,::ffff:127.0.0.0//104,::1//128
skip_addresses = 127.0.0.1/32

После этого заставляем Postfix прочитать новую конфигурацию:

service postfix restart

Проверка:
Посылаем письмо снаружи и смотрим на заголовки у себя. В письме, прошедшем SPF-проверку, должно быть что-то вроде:

...
Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=1.2.3.4; helo=mail.outside.tld; envelope-from=Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в вашем браузере должен быть включен Javascript.; receiver=Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в вашем браузере должен быть включен Javascript.
...

OpenDKIM

В репозитариях Rosa Cobalt отсутствует. Настраиваем на CentOS
Установка:

yum install opendkim

О настройке DKIM в DNS описывалось выше.
Создадим папки:

mkdir -pv /etc/opendkim/mail/
chown -Rv opendkim:opendkim /etc/opendkim
chmod go-rwx /etc/opendkim/*
cd /etc/opendkim/mail/

Сначала создаем файл в котором перечислены хосты, для которых подпись не нужна /etc/opendkim/mail/opendkimhosts

127.0.0.1
localhost
domain
# Your IP addresses (one per line)
192.168.20.104

#Your hostnames (one per line)
dest.loc

Генерируем ключи:

opendkim-genkey -D /etc/opendkim/mail/ -b 1024 -d dest.loc -s mail

-r - означает, что только для почты
-s - селектор
Раздаем права на файлы:

# cd /etc/opendkim/mail/
# chown opendkim:opendkim *
# chmod u=rw,go-rwx *

Настраиваем OpenDKIM в файле /etc/opendkim.conf. Комментируем все настройки и добавляем:

...
Domain dest.loc
KeyFile /etc/opendkim/mail/mail.private
Selector mail
InternalHosts /etc/opendkim/mail/opendkimhosts
ExternalIgnoreList /etc/opendkim/mail/opendkimhosts
AutoRestart yes
Background yes
Canonicalization simple
DNSTimeout 5
Mode sv
SignatureAlgorithm rsa-sha256
SubDomains yes
#UseASPDiscard no
#Version rfc4871

Настраиваем порт в /etc/default/opendkim. Так же все комментируем и добавляем строку:

...
SOCKET="inet:8891@localhost"

Настройки DKIM в Postfix - в файле "/etc/postfix/main.cf". В Rosa Cobalt их комментируем:

...
milter_default_action = accept
milter_protocol = 2
smtpd_milters = inet:localhost:8891
non_smtpd_milters = inet:localhost:8891
...

Первая строка говорит о том, чтобы все же принимать даже ту почту, которая не подписана.
Открытый ключ (сгенерированный ранее) должен быть здесь: /etc/opendkim/mail/mail.txt
Копируем его в DNS (см. выше как). Там же создаем TXT-запись о политике использования DKIM в домене.
ВАЖНО! Ключ в DNS должен быть указан одной длинной строкой. Добавляется только то, что в кавычках - вместе с кавычками.
Если все сделали, то рестарт сервисов:

/etc/init.d/opendkim restart
service postfix restart

ClamAV-Milter

Антивирус ClamAV может быть подключен к Postfix разными способами. У системы, которая хорошо защищена и не слишком нагружена (имеет достаточный резерв ресурсов), ClamAV может быть подключен до очереди, и успевать проверять письма до завершения SMTP-сессии. Это позволит давать немедленный отказ клиентам, даже не принимая сообщение в очередь.

Если до антивируса будет доходить только те письма, которые уже прошли Postscreen и Postgrey, то можно рассчитывать на резерв ресурсов, достаточный для того, чтобы ClamAV успевал отработать.

У нас ClamAV будет подключен через Milter-протокол.

yum install clamav clamav-scanner clamav-update clamav-milter libtommath

Базы находятся в каталоге /var/lib/clamav/
После установки пакетов необходимо обновить вирусные базы. Редактируем файл /etc/freshclam.conf. Комментируем параметр Example. Добавляем (раскоментируем) следующие строки:

DatabaseDirectory /var/lib/clamav
UpdateLogFile /var/log/freshclam.log
LogFileMaxSize 20M
LogTime yes
LogRotate yes
PidFile /var/run/freshclam.pid
AllowSupplementaryGroups yes
DatabaseMirror database.clamav.net
NotifyClamd /etc/clam.d/scan.conf
Check 4

Остальные строки оставляем без изменений.
Запускаем обновление баз:

freshclam

Настраиваем сервис clamd в файле /etc/clam.d/scan.conf. Комментируем строку Example. Остальные параметры:

LogFile /var/log/clamd.scan
LogFileMaxSize 20M
LogTime yes
LogSyslog no
LogFacility LOG_MAIL
LogRotate yes
ExtendetDetectionInfo yes
PidFile /var/run/clamd.scan/clamd.pid
TemporaryDirectory /var/tmp
DatabaseDirectory /var/lib/clamav
LocalSocket /var/run/clamd.scan/clamd.sock
LocalSocketMode 660
FixStaleSocket yes
TCPSocket 3310
TCPAddr 127.0.0.1
StreamMinPort 30000
StreamMaxPort 32000
MaxThreads 20
ReadTimeout 300
MaxQueue 200
IdleTimeout 60
User clamscan
AllowSupplementaryGroups yes
ScanMail yes
PhishingSignatures yes
PhishingScanURLs yes
MaxScanSize 150M
MaxFileSize 30M

Запускаем сервис:

/etc/init.d/clamd.scan start

Добавляем автозапуск:

chkconfig --level 2345 clamd.scan on

Настраиваем ClamAV-milter в файле /etc/mail/clamav-milter.conf. Комментируем строку Example. Остальные настройки:

#MilterSocket /var/run/clamav-milter/clamav-milter.socket
MilterSocket inet:7357@127.0.0.1
MilterSocketMode 660
FixStaleSocket yes
User clamilt
AllowSupplementaryGroups yes
ReadTimeOut 300
PidFile /var/run/clamav-milter/clamav-milter.pid
TemporaryDirectory /var/tmp
ClamdSocket unix:/var/run/clamd.scan/clamd.sock
OnClean Accept
OnInfected Reject
OnFail Reject
RejectMsg "Virus detectd: %v. Mail delivery error (reject from virus scanner)."
AddHeader Add
LogFile /var/log/clamav-milter.log
LogFileUnlock yes
LogFileMaxSize 50M
LogTime yes
LogSyslog no
LogInfected Full
LogClean Basic

Запускаем сервис:

/etc/init.d/clamav-milter start

Добавляем автозапуск:

chkconfig --level 2345 clamav-milter on

В конфигурационном файле Postfix /etc/postfix/main.cf (см. выше), необходимо добавить через запятую к параметрам smtpd_milters и non_smtpd_milters значения, касющиеся ClamAV:

...
smtpd_milters = inet:127.0.0.1:8891, inet:127.0.0.1:7357
non_smtpd_milters = inet:127.0.0.1:8891, inet:127.0.0.1:7357
...

В письме присланном снаружи должны присутствовать строки заголовка подобные следующим:

...
X-Virus-Status: Clean
X-Virus-Scanned: clamav-milter 0.97.8 at domain
...

Для того чтобы проверить свой антивирус, можно послать себе письмо, которое будет распознано как зараженное. Для это существует т.н. "тестовый вирус" EICAR-Test-File. Нужно вставить эту выделенную жирным часть текста в поисковик :) и найти тестовую строку на одном из сайтов (например в Википедии). После чего скопировать прямо в содержание письма, указанную там тестовую строку, и послать себе из внешнего почтовика (можно из GMail). Через непродолжительное время (скорее всего несколько секунд) должно вернуться сообщение о том, что письмо не доставлено. В нем должно присутствовать указанное чуть выше в настройках сообщение (Virus detected: "%v". ) и код ответа (550).

Вообще, с помощью теста EICAR-Test-File удобно налаживать работу антивирусной системы.

Настройка Dovecot

Установку Dovecot мы провели ранее, вместе с установкой Postfix. Теперь пришло время его настроить. Для того, что бы посмотреть текущие настройки, в консоле нужно ввести команду:

doveconf

В рассматриваемой конфигурации Dovecot будет слушать пока только 143 (IMAP) порт и только на локалхосте (127.0.0.1).

На этот порт будет подключаться MUA - RoundCube. Наружу используется 25 порт (Postfix). При этом для отправки писем RoundCube использует другой порт - 587 (Postfix).

Настройка протоколов.

Удаляем ненужные протоколы. В файле /etc/dovecot/dovecot.conf пишем:

protocols = imap lmtp sieve
...
!include conf.d/*.conf
...

Все необходимые нам для данной конфигурации файлы.

/etc/dovecot/dovecot.conf

protocols = imap lmtp sieve

dict {
#quota = mysql:/etc/dovecot/dovecot-dict-sql.conf.ext
#expire = sqlite:/etc/dovecot/dovecot-dict-sql.conf.ext
}

!include conf.d/*.conf
#!include_try local.conf


/etc/dovecot/conf.d/10-auth.conf

# Connect only after start SSL/TLS
# If not local network only !
disable_plaintext_auth = yes
auth_cache_size = 1M
auth_cache_negative_ttl = 0
auth_username_chars = abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890.-_@
auth_master_user_separator = *
auth_mechanisms = plain

#!include auth-deny.conf.ext
#!include auth-master.conf.ext
#!include auth-system.conf.ext
!include auth-sql.conf.ext
#!include auth-ldap.conf.ext
#!include auth-passwdfile.conf.ext
#!include auth-checkpassword.conf.ext
#!include auth-vpopmail.conf.ext
#!include auth-static.conf.ext


/etc/dovecot/conf.d/10-director.conf

service director {
  unix_listener login/director {
    #mode = 0666
  }
  fifo_listener login/proxy-notify {
    #mode = 0666
  }
  unix_listener director-userdb {
    #mode = 0600
  }
  inet_listener {
    #port = 
  }
}
# Enable director for the wanted login services by telling them to
# connect to director socket instead of the default login socket:
service imap-login {
  #executable = imap-login director
}
#service pop3-login {
  #executable = pop3-login director
#}
# Enable director for LMTP proxying:
protocol lmtp {
  #auth_socket_path = director-userdb
}


/etc/dovecot/conf.d/10-logging.conf

# Log file to use for error messages. "syslog" logs to syslog,
# /dev/stderr logs to stderr.
log_path = /var/log/dovecot.log
info_log_path = /var/log/dovecot-info.log
debug_log_path = /var/log/dovecot-debug.log
auth_verbose = no
auth_verbose_passwords = no
auth_debug = no
auth_debug_passwords = no
mail_debug = no
verbose_ssl = no
#plugin {
#}
#log_timestamp = "%b %d %H:%M:%S "
#login_log_format_elements = user= method=%m rip=%r lip=%l mpid=%e %c
#login_log_format = %$: %s
#mail_log_prefix = "%s(%u): "
# Format to use for logging mail deliveries. You can use variables:
#  %$ - Delivery status message (e.g. "saved to INBOX")
#  %m - Message-ID
#  %s - Subject
#  %f - From address
#  %p - Physical size
#  %w - Virtual size
#deliver_log_format = msgid=%m: %$

Возможно придется изменить права на файле /var/log/dovecot.log на 666 Информацию об ошибках и других событиях, связаных с работой почтовой системы нужно так же искать в файлах:
/var/log/dovecot.log
/var/log/maillog

Для настройки и мониторинга системы полезно будет внести в конец файла /etc/rsyslog.conf следующие строки:

...
# Add
# Postfix + Dovecot
local1.*                          -/var/log/dovecot.log
local1.info                       -/var/log/dovecot.info
local1.warn                       -/var/log/dovecot.warn
local1.err                        -/var/log/dovecot.err
:msg,contains,"stored mail into mailbox"	-/var/log/dovecot.lmtp

Перезапускаем сервис:

service rsyslog restart

Что бы не забился диск на сервере, логи нужно периодически обнулять. Делаем ротацию логов. Содаем файл /etc/logrotate.d/dovecot со следующим содержимым:

/var/log/dovecot.log
/var/log/dovecot.info
/var/log/dovecot.warn
/var/log/dovecot.err
/var/log/dovecot.lmtp
{
        weekly
        rotate 52
        missingok
        notifempty
        compress
        delaycompress
        create 640 root root
        sharedscripts
        postrotate
        /bin/kill -USR1 'cat /var/run/dovecot/master.pid 2>/dev/null' 2>/dev/null || true
        endscript
}

В следующем конфиге ("10-mail.conf") присутствует namespace virt, для которого плагин virtual должен быть включен в трех конфигах:

  • 20-imap.conf
  • 20-lmtp.conf
  • 15-lda.conf
  • 20-managesieve.conf

ВАЖНО! В конфигах "15-lda.conf" и "20-managesieve.conf" включение плагинов должно быть без дублирования уже включенных: mail_plugins = ... virtual, а в остальных - с дублированием: mail_plugins = $mail_plugins ... virtual

В конфиге "10-mail.conf" строка "location = " для "namespace virt" настраивает плагин так, что каталог с правилами будет общий для всех пользователей, а индексные каталоги - у каждого свои.

Но сначала создадим необходимые каталоги (в консоли):

mkdir /opt/mail/dovecot/virtual
mkdir /opt/mail/dovecot/virtual/Folder1
chown -hR vmail:vmail /opt/mail/dovecot/virtual
chmod -R 700 /opt/mail/dovecot/virtual

ВАЖНО! В дальнейшем для всех подпапок внутри /opt/mail/dovecot/virtual нужно будет так же изменять владельца и права!

Папка с индексами "virtual_index" для виртуальных каталогов будет создаваться у каждого ящика автоматически при любом доступе.

Файл с фильтрами для виртуального каталога может выглядеть так (для виртуальной папки Folder1) /opt/mail/dovecot/virtual/Folder1/dovecot-virtual:

virtual/Folder1
  inthread refs x-mailbox INBOX

Настраиваем дальше.

/etc/dovecot/conf.d/10-mail.conf

mail_location = maildir:/opt/mail/vmail/%d/%n:INBOX=/opt/mail/vmail/%d/%n/Inbox
namespace virt {
#  type = private
  prefix = virtual/
  separator = /
  location = virtual:/opt/mail/dovecot/virtual:INDEX=/opt/mail/vmail/%d/%n/virtual_index:CONTROL=/opt/mail/vmail/%d/%n/virtual_index
  inbox = no
  hidden = yes
  list = yes
  subscriptions = yes
  #mailbox Folder1 {
  #  auto=subscribe
  #}
}

namespace allusers {
  type = public
  separator = /
  prefix = "allmail/%d/"
  location = maildir:/opt/mail/vmail/%d:LAYOUT=fs:INDEX=/opt/mail/vmail/%d/%n/allmail_index
  inbox = no
  hidden = yes
  list = yes
  subscriptions = no
}

namespace system_users {
  type = private
  separator = /
  prefix = "system_users/"
  location = mbox:/var/mail/:INDEX=/opt/mail/vmail/system_users_index
  inbox = no
  hidden = yes
  list = yes
  subscriptions = yes
}

namespace inbox {
  type = private
  separator = /
  prefix =
  inbox = yes
  hidden = no
  list = yes
  subscriptions = yes
}

mail_uid = 5000
mail_gid = 5000

#mail_nfs_storage = no
#mail_nfs_index = no
#first_valid_uid = 500
#last_valid_uid = 0
#first_valid_gid = 1
#last_valid_gid = 0
#mail_attachment_dir =
#mail_attachment_min_size = 128k
#mail_attachment_fs = sis posix
# Hash format to use in attachment filenames. You can add any text and
# variables: %{md4}, %{md5}, %{sha1}, %{sha256}, %{sha512}, %{size}.
# Variables can be truncated, e.g. %{sha256:80} returns only first 80 bits
#mail_attachment_hash = %{sha1}

Чтобы читать почту системных юзеров (namespace system_users) надо дать разрешение на папку "/var/mail/" и на файл каждого пользователя - чтение и запись для всех

/etc/dovecot/conf.d/10-master.conf

#default_process_limit = 100
#default_client_limit = 1000
#default_vsz_limit = 256M
#default_login_user = dovenull
#default_internal_user = dovecot
service imap-login {
  inet_listener imap {
   address = 127.0.0.1
   port = 143
   #ssl = yes
  }

  inet_listener imaps {
   #port = 993
   port = 0
   #ssl = yes
  }
  #service_count = 1
  #process_min_avail = 0
  #vsz_limit = $default_vsz_limit
}

#service pop3-login {
  #inet_listener pop3 {
   #port = 110
  #}

  #inet_listener pop3s {
   #port = 995
   #ssl = yes
  #}
#}

service lmtp {
  unix_listener lmtp {
  path = /var/spool/postfix/private/dovecot-lmtp
  group = postfix
  mode = 0660
  user = postfix
  ##mode = 0666
  }

 #unix_listener /var/spool/postfix/private/dovecot-lmtp {
 #  group = postfix
 #  mode = 0660
 #  user = postfix
 # }

# process_min_avail = 5
  executable = lmtp -L
}

service imap {
  #vsz_limit = $default_vsz_limit
  # Max. number of IMAP processes (connections)
  #process_limit = 1024
  #executable = imap
}

#service pop3 {
  # Max. number of POP3 processes (connections)
  #process_limit = 1024
#}

service auth {
  unix_listener auth {
   path = /var/spool/postfix/private/auth
   mode = 0660
   user = postfix
   group = postfix
  }
  user = $default_internal_user
}

service auth-worker {
  user = $default_internal_user
}

# Detail Process title in ps
#verbose_proctitle = yes

#service dict {
  #unix_listener dict {
  #}
#}

/etc/dovecot/conf.d/10-ssl.conf

#ssl = yes
ssl = required
ssl_cert = ‹/etc/dovecot/ssl.cert.pem
ssl_key = ‹/etc/dovecot/ssl.key.pem
#ssl_key_password =
#ssl_ca =
#ssl_require_crl = yes
#ssl_verify_client_cert = no
#auth_ssl_username_from_cert=yes.
#ssl_cert_username_field = commonName
#ssl_parameters_regenerate = 168
ssl_parameters_regenerate = 0
ssl_protocols = !SSLv2
#ssl_cipher_list = ALL:!LOW:!SSLv2:!EXP:!aNULL
#ssl_crypto_device =

/etc/dovecot/conf.d/10-tcpwrapper.conf

# service name for hosts.{allow|deny} are those defined as
# inet_listener in master.conf
#
#login_access_sockets = tcpwrap
#
#service tcpwrap {
#  unix_listener login/tcpwrap {
#    group = $default_login_user
#    mode = 0600
#    user = $default_login_user
#  }
#}

/etc/dovecot/conf.d/15-lda.conf

postmaster_address = Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в вашем браузере должен быть включен Javascript.
hostname = dest.loc
#quota_full_tempfail = no
#sendmail_path = /usr/sbin/sendmail
#submission_host =
#rejection_subject = Rejected: %s
#  %n = CRLF, %r = reason, %s = original subject, %t = recipient
rejection_reason = Your message to  was automatically rejected:%n%r
#recipient_delimiter = +
#lda_original_recipient_header =
#lda_mailbox_autocreate = no
#lda_mailbox_autosubscribe = no
protocol lda {
  mail_plugins = sieve virtual
#  log_path = /var/log/mail-dovecot-lda-errors.log
#  info_log_path = /var/log/mail-dovecot-lda.log
#  auth_socket_path = /var/run/dovecot/auth-master
#  auth_socket_path = auth-userdb
#  global_script_path = /var/lib/dovecot/sieve/global/globalsieverc
}

Отключаем 15-mailboxes.conf, т.к. мы его пока не используем:

mv /etc/dovecot/conf.d/15-mailboxes.conf /etc/dovecot/conf.d/15-mailboxes.conf_

/etc/dovecot/conf.d/20-imap.conf

protocol imap {
  mail_plugins = $mail_plugins imap_acl imap_quota mail_log notify acl quota virtual
  ssl_cert = ‹/etc/dovecot/ssl.cert.pem
  ssl_key = ‹/etc/dovecot/ssl.key.pem
  info_log_pth = /var/log/dovecot-imap.log
  #iap_max_line_length = 64k
  #mail_max_userip_connections = 10
  # IMAP logout format string:
  # %i - total number of bytes read from client
  # %o - total number of bytes sent to client
  #imap_logout_format = bytes=%i/%o
  #imap_capability =
  #imap_idle_notify_interval = 2 mins
  #imap_id_send =
  #imap_id_log =
  # Workarounds for various client bugs:
  # delay-newmail:
  # tb-extra-mailbox-sep:
  # tb-lsub-flags:
  # The list is space-separated.
  #imap_client_workarounds =
}

/etc/dovecot/conf.d/20-lmtp.conf

#lmtp_proxy = no
#lmtp_save_to_detail_mailbox = no
protocol lmtp {
  mail_plugins = $mail_plugins quota sieve virtual
  postmaster_address = Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в вашем браузере должен быть включен Javascript.
  #info_log_path = /var/log/dovecot-lmtp.log
}

/etc/dovecot/conf.d/20-managesieve.conf

service managesieve-login {
  inet_listener sieve {
    address = 127.0.0.1
    port = 4190
  }
  service_count = 1
  #process_min_avail = 0
  vsz_limit = 64M
}

#service managesieve {
  # Max. number of ManageSieve processes (connections)
  #process_count = 1024
#}

mail_plugins = virtual

protocol sieve {
  #managesieve_max_line_length = 65536
  #mail_max_userip_connections = 10
  #mail_plugins = virtual
  # MANAGESIEVE logout format string:
  #  %i - total number of bytes read from client
  #  %o - total number of bytes sent to client
  #managesieve_logout_format = bytes=%i/%o
  #managesieve_implementation_string = Dovecot Pigeonhole
  #managesieve_sieve_capability =
  #managesieve_notify_capability =
  #managesieve_max_compile_errors = 5
}

/etc/dovecot/conf.d/90-acl.conf

plugin {
  #acl = vfile:/etc/dovecot/acl/%d:cache_secs=300
  acl = vfile:/etc/dovecot/acl/%d
}

plugin {
  #acl_shared_dict = file:/var/lib/dovecot/shared-mailboxes
}

Здесь "%d" - папка, совпадающая с доменным именем.
Чуть ниже - пара примеров настройки ACL для всех пользователей.

Следующая настройка запрещает пользователю всё, кроме чтения/просмотра/удаления, но разрешает сохранение для LDA.
В каталоге с именем домена указываем ACL для папки ".Sent".

/etc/dovecot/acl/dest.loc/Sent

owner lrwstpe

Аналогично можно настроить остальные папки

Закрываем доступ для всех кроме LDA к файлу ".dovecot.lda-dupes", который может быть виден в MUA как фантомная папка "lda-dupes":

mkdir /etc/dovecot/acl/dest.loc/dovecot/

ВАЖНО! - точка воспринимается как маркер вложенной папки.

/etc/dovecot/acl/domain.tld/dovecot/lda-dupes

anyone rp

/etc/dovecot/conf.d/90-plugin.conf

plugin {
# mail_plugins = $mail_plugins mail_log notify acl quota
# For Plugin mail_log:
  mail_log_events = copy
  mail_log_fields = uid box msgid size
}

/etc/dovecot/conf.d/90-quota.conf

plugin {
  quota = dict:user::file:/opt/mail/vmail/%d/%n/dovecot-quota
  quota_rule = *:storage=1GB
  quota_rule2 = Trash:storage=+10%%
}

# Note that % needs to be escaped as %%, otherwise "% " expands to empty.
plugin {
  #quota_warning = storage=95%% quota-warning 95 %u
  #quota_warning2 = storage=80%% quota-warning 80 %u
}

#service quota-warning {
#  executable = script /usr/local/bin/quota-warning.sh
#  user = dovecot
#  unix_listener quota-warning {
#    user = vmail
#  }
#}

plugin {
  #quota = dirsize:User quota
  #quota = maildir:User quota
  #quota = dict:User quota::proxy::quota
  #quota = fs:User quota
}

plugin {
  #quota = dict:user::proxy::quota
  #quota2 = dict:domain:%d:proxy::quota_domain
  #quota_rule = *:storage=102400
  #quota2_rule = *:storage=1048576
}

Здесь указана квота для пользователя 1 ГБ, а для Корзины - 10 процентов от общей квоты.

Sieve

Очень полезный плагин для организации сортировки писем на стороне сервера (до того, как пользователь откроет свой почтовый клиент).

Все глобальные скрипты и конфигурационные файлы будут находится в соответствующих папках в: /opt/mail/dovecot/sieve/global/

Все персональные настройки и файлы будут находится либо в папках пользователей, либо в каталоге: /opt/mail/dovecot/sieve/private/ - в соответствующих папках.

Создаем необходимые папки и назначаем права доступа:

mkdir /opt/mail/dovecot/sieve/
mkdir /opt/mail/dovecot/sieve/global/
mkdir /opt/mail/dovecot/sieve/private/
chown -hR root:root /opt/mail/dovecot/sieve/
chown -hR root:root /opt/mail/dovecot/sieve/global/
chown -hR vmail:root /opt/mail/dovecot/sieve/private/
chmod -R 755 /opt/mail/dovecot/sieve/
chmod -R 755 /opt/mail/dovecot/sieve/global/
chmod -R 700 /opt/mail/dovecot/sieve/private/

После всех остальных настроек (в конфиге ниже), папки в каталоге "/opt/mail/dovecot/sieve/private/" будут создаваться автоматически (включая каталог домена) при первом доступе пользователя к фильтру в настройках MUA RoundCube.

/etc/dovecot/conf.d/90-sieve.conf

plugin {
#  sieve_user_log = /var/lib/dovecot/sieve/private/%d/%n/.main.peronal.log
  sieve = /opt/mail/dovecot/sieve/private/%d/%n/.main.personal.sieve
  #sieve_default = /opt/mail/dovecot/sieve/default.sieve
  sieve_dir = /opt/mail/dovecot/sieve/private/%d/%n
  sieve_global_dir = /opt/mail/dovecot/sieve/global/
  #sieve_before2 =
  sieve_before = /opt/mail/dovecot/sieve/global/incoming_deduplicate.sieve
  #sieve_after =
  #sieve_after2 =
  sieve_extensions = +editheader
  sieve_global_extensions = +vnd.dovecot.duplicate
  sieve_duplicate_period = 1d
  #sieve_plugins =
  recipient_delimiter = +
  #sieve_max_script_size = 1M
  #sieve_max_actions = 32
  #sieve_max_redirects = 4
  #sieve_quota_max_scripts = 0
  #sieve_quota_max_storage = 0
}

Немного подробнее о глобальном sieve-скрипте "incoming_deduplicate.sieve" и контроле всех отправляемых писем.

В данной конфигурации реализовано сохранение всей исходящей почты - в т.ч. отправленной с неучтенных ящиков или из внешнего MUA. Реализация включает в себя Sieve-скрипты в Dovecot, а также некоторые настройки Postfix.

Суть метода в том, что для любых писем отправленных через Postfix создается дополнительная копия, доставляемая отправителю (только если отправитель в "родном" домене). При этом, если отправитель неучтенный (отсутствует в базе Postfixadmin), то BCC-копия доставляется в единый ящик для неизвестных отправителей. Эта копия маркируется прямо в Postfix - в заголовке письма модифицируется адрес доставки "Delivered-To" примерно так: "user+bccflag@dest.loc" (либо "bccsnd+bccflag@dest.loc" - для неучтенных отправителей). При доставке письма в ящик (через Dovecot) Sieve-скрипт отлавливает эти маркированные письма и пропускает их через временную базу учета дубликатов с помощью расширения vnd.dovecot.duplicate (дубликаты отслеживаются по уникальному ID письма). Кроме того, проверке подвергаются письма, принудительно "перепосланные" из папки "Отправленные" - пропускаются через ту же базу дубликатов. Для этого, письма, отправленные "родным" MUA, проверяются (с помощью incron они "ловятся" при появлении в папке "Отправленные") и, если нет маркера - маркируются (заголовок модифицируется - добавляется "X-Deduplicate: IMAP refiltering") и пересылаются через Dovecot-LDA во "Входящие", где распознаются как подлежащие проверке на предмет дублирования. Какое из маркированных (с помощью Postfix или incron) писем придет первым - то и сохранится окончательно в "Отправленные" (последующие дубликаты уничтожаются).
Побочным эффектом всей схемы является проблема при принудительном перемещении писем в Отправленные через MUA (например мышью в web-интерфейсе) - некоторые из таких писем просто попадают во "Входящие". Эта проблема может быть частично решена через Dovecot-ACL.

Модули, задействованные в данном процессе:

  • Posfix - параметр sender_bcc_maps, конфига "main.cf"
  • Posfix - файлы /etc/postfix/mysql_bcc_mailbox_maps.cf и /etc/postfix/mysql_bcc_domain_maps.cf - для параметра sender_bcc_maps
  • Posfix - параметр recipient_delimiter (конфиг "main.cf")
  • Dovecot - параметры sieve_before, sieve_extensions, sieve_global_extensions и прочие конфига "90-sieve.conf"
  • Dovecot - параметр recipient_delimiter (конфиг "15-lda.conf")
  • Dovecot - параметр recipient_delimiter (конфиг "90-sieve.conf")
  • Dovecot - Sieve-скрипт "incoming_deduplicate.sieve" контроля дубликатов во входящих.
  • Dovecot - Sieve-скрипт "move_to_lda_refiltering.sieve" переотправки письма из "Отправленные" во "Входящие" через Dovecot-LDA.
  • Roundcube - распознавание маркированного "двойного" адреса, параметр: "$CONF['recipient_delimiter']" - описание ниже
  • Postfixadmin - скрипты постобработки добавления/удаления ящика, для файлов в служебной папке "incron_mailuser_monitor"
  • incron - задание "/etc/incron.d/00-del_mailuser_dir_monitor" наблюдения за удалением файлов из служебной папки "/opt/mail/vmail/incron_mailuser_monitor".
  • incron - задание "/etc/incron.d/00-add_mailuser_dir_monitor" наблюдения за добавлением файлов в служебную папку "/opt/mail/vmail/iincron_mailuser_monitor".
  • Скрипт - "/etc/dovecot/add_del_mailuser_monitor.sh" запускающийся из заданий "/etc/incron.d/00-del_mailuser_dir_monitor" и "/etc/incron.d/00-add_mailuser_dir_monitor".
  • incron - файлы заданий "/etc/incron.d/maildomain@mailuser" наблюдения за папками пользователей "Отправленные" (каждому ящику - в отдельном файле). Эти задания создаются/удаляются скриптом "add_del_mailuser_monitor.sh".
  • Скрипт - "/etc/dovecot/sent_refilter.sh" запускающийся из заданий наблюдения за папками пользователей "Отправленные".

ВАЖНО! Рекомендую изменить названия служебных папок для большей безопасности.

Добавим глобальный скрипт, который будет запускаться по событию входящей почты. Sieve-скрипт для sieve_before конфига "90-sieve.conf"

 

/opt/mail/dovecot/sieve/global/incoming_deduplicate.sieve

require ["vnd.dovecot.duplicate", "editheader", "fileinto", "envelope", "subaddress", "imap4flags"];
if allof (not exists "X-Deduplicate", anyof (envelope :detail "to" "bccflag", not exists "Delivered-To")) {
    if duplicate {
        discard;
        stop;
    }
    else {
        if not exists "Delivered-To" {
            # addheader :last "X-Deduplicate" "IMAP refiltering";
            addheader "X-Deduplicate" "IMAP refiltering";
            setflag "\\flagged";
        }
        else {
            # addheader :last "X-Deduplicate" "bccflag";
            addheader "X-Deduplicate" "bccflag";
        }
        fileinto "Sent";
    }
}

Создадим Sieve-скрипт для обработки виртуальных почтовых папок "Sent", который будет запускаться с помощью инструмента sieve-test

/opt/mail/dovecot/sieve/global/move_to_lda_refiltering.sieve

if not exists "X-Deduplicate" {
	discard;
	stop;
}

Компилируем скрипты , проверяя, чтобы не было никаких ошибок:

sievec /opt/mail/dovecot/sieve/global/incoming_deduplicate.sieve
sievec /opt/mail/dovecot/sieve/global/move_to_lda_refiltering.sieve

Устанавливаем incron:

yum install incron
systemctl enable incrond
systemctl start incrond

Даем разрешение root в /etc/incron.allow

root

Создаem служебную папку. В папке PostfixAdmin будет создавать и удалять пустые файлы с соответствующим именем, при создании и удалении почтовых ящиков. После этого устанавливаем наблюдение за этой папкой (через incron).

mkdir /opt/mail/vmail/incron_mailuser_monitor
chmod 670 /opt/mail/vmail/incron_mailuser_monitor
chown root:apache /opt/mail/vmail/incron_mailuser_monitor

Формат файла для каждого ящика в этой папке должен быть следующий:

"maildomain@mailuser".

Т.е. это почтовый адрес, в котором домен и пользователь заменяны местами (например для "user@dest.loc", имя файла будет "dest.loc@user").

Раскомментируем последние строки в скриптах пост-обработки PostfixAdmin, отвечающие за добавление/удаление файлов-пустышек в служебной папке параллельно с добавлением/удалением ящиков

 /opt/www/html/postfixadmin/scripts/addmail.sh

...

if [[ -d /opt/mail/vmail/incron_mailuser_monitor/ ]]
then
    userdomain=(${1//@/ })
    touch /opt/mail/vmail/incron_mailuser_monitor/${userdomain[1]}@${userdomain[0]}
fi


/opt/www/html/postfixadmin/scripts/delmail.sh

...

if [[ -d /opt/mail/vmail/incron_mailuser_monitor/ ]]
then
    userdomain=(${1//@/ })
    if [[ -f /opt/mail/vmail/incron_mailuser_monitor/${userdomain[1]}@${userdomain[0]} ]]
    then
        rm /opt/mail/vmail/incron_mailuser_monitor/${userdomain[1]}@${userdomain[0]}
    fi
fi

При появлении/удалении в служебной папке "incron_mailuser_monitor" файла с именем почтового ящика (описанного выше формата) будет запускаться скрипт "add_del_mailuser_monitor.sh", в аргументах которого будет присутствовать имя файла. Главное же здесь то, что этот скрипт будет запускаться от "root" - ради этого и реализована идея промежуточной т.н. "служебной папки".

/etc/incron.d/00-del_mailuser_dir_monitor

/opt/mail/vmail/incron_mailuser_monitor/ IN_DELETE /etc/dovecot/add_del_mailuser_monitor.sh $# del

Создаем задание наблюдения за добавлением файлов в служебной папке в incron

/etc/incron.d/00-add_mailuser_dir_monitor

/opt/mail/vmail/incron_mailuser_monitor/ IN_CREATE /etc/dovecot/add_del_mailuser_monitor.sh $# add

Перезапускаем incron:

systemctl restart incrond

ВАЖНО! Появление файла в служебной папке будет вызывать появление задания наблюдения за папкой "Отправленные" соответствующего ящика через incron, а удаление файла в служебной папке будет вызывать не только удаления задания наблюдения за "Отправленные", но и автоматическое удаление Maildir-папки со всеми письмами этого ящика!

Создадим теперь сам скрипт "add_del_mailuser_monitor.sh". Этот скрипт будет, при появлении нового ящика, добавлять задание в incron - наблюдать за папкой "Отправленные" (".../.Sent/cur/") этого ящика. А при удалении ящика - удалять это задание из incron.

/etc/dovecot/add_del_mailuser_monitor.sh

#!/bin/bash
if [[ "$2" == del ]]
then
       userdomain=(${1//@/ })
       if [[ -f /etc/incron.d/$1 ]]
       then
              `rm /etc/incron.d/$1`
              `/bin/systemctl restart incrond`
       fi

       if [[ -d /opt/mail/vmail/${userdomain[0]}/ ]]
       then
              if [[ -d /opt/mail/vmail/${userdomain[0]}/${userdomain[1]}/ ]]
              then
                      `rm -rf /opt/mail/vmail/${userdomain[0]}/${userdomain[1]}`
              fi
       fi
fi

if [[ "$2" == add ]]
then
       userdomain=(${1//@/ })
       # /usr/libexec/dovecot/dovecot-lda -d ${userdomain[1]}@${userdomain[0]} -p /etc/dovecot/mail_for_new
       `sleep 3s`
       printf "/opt/mail/vmail/${userdomain[0]}/${userdomain[1]}/.Sent/cur/ IN_MOVED_TO /etc/dovecot/sent_refilter.sh /opt/mail/vmail/${userdomain[0]}/${userdomain[1]}/ ${userdomain[1]}@${userdomain[0]} \$#" >> /etc/incron.d/$1
       `/bin/systemctl restart incrond`
fi

"printf ..." - должен быть одной строкой без переносов!!!

sleep 3s - 3 секундная задержка нужна, чтобы Dovecot успел создать Maildir-папки.
Если Maildir-папки не успеют создаться, то новое задание наблюдения за папкой "Отправленные" будет выдавать ошибку о том. что incron не может найти наблюдаемую папку. В этом случае необходимо было бы каждый раз перезапускать incron.

/usr/libexec/dovecot/dovecot-lda ... - закоментированная строка отправляет приветственное письмо через Dovecot-LDA. Если это будет использовано, то такое письмо нужно будет создать (в файле "/etc/dovecot/mail_for_new").

ВАЖНО! Строки, отвечающие за удаление Maildir-каталога стоит использовать только если есть уверенность в полной безопасности (выделено жирным шрифтом).

Создадим скрипт, который будет вызываться по событию в папках "Отправленные"

/etc/dovecot/sent_refilter.sh

#!/bin/bash
qresult="$(sieve-test -l $1 /opt/mail/dovecot/sieve/global/move_to_lda_refiltering.sieve $1/.Sent/cur/$3)"
if [[ "$qresult" == *discard* ]]
then
       /usr/libexec/dovecot/dovecot-lda -d $2 -p $1/.Sent/cur/$3
       rm $1/.Sent/cur/$3
       doveadm index -u $2 mailbox Sent
fi

Назначаем права:

chmod 700 /etc/dovecot/add_del_mailuser_monitor.sh
chmod 700 /etc/dovecot/sent_refilter.sh

Теперь все отправляемые письма, как и чем бы они не отправлялись (в т.ч. внешним MUA) - попадут в папку "Отправленные" к тому, от чьего имени они были отправлены. А письма, которые были отправлены от незарегистрированных пользователей - попадут в специальный ящик для таких писем. Это позволит четко контролировать отправляемую почту, в т.ч. и контролировать возможный захват почтовых инструментов спамерами.

Для проверки можно завести ящик пользователя "www-data@dest.loc" и отправить кому-нибудь тестовое письмо из PHP-скрипта. Письмо должно появиться в папке "Отправленные" почтового ящика. После чего следует удалить ящик и отправить письмо из PHP-скрипта еще раз. Теперь оно должно появиться в ящике, предназначенном для отправленных писем неучтенных (без ящика) пользователей "bccsnd@dest.loc".

Далее.

/etc/dovecot/conf.d/auth-sql.conf.ext

#passdb {
#  driver = passwd-file
#  args = username_format=%u /var/vmail/auth.d/%d/passwd
#}
# Master-user:
auth_master_user_separator = *
#auth_debug = yes
passdb {
  driver = sql
  args = /etc/dovecot/dovecot-sql-master.conf.ext
  master = yes
  pass = yes
}
passdb {
  driver = sql
  args = /etc/dovecot/dovecot-sql.conf.ext
#  default_fields = userdb_gid=5000 userdb_uid=5000
}
userdb {
  driver = prefetch
}

userdb {
  driver = sql
  args = /etc/dovecot/dovecot-sql.conf.ext
#  default_fields = uid=5000 gid=5000
}

Создаем SQL-конфиги.

/etc/dovecot/dovecot-sql.conf.ext

driver = mysql

connect = host=127.0.0.1 dbname=_POSTFIXADMIN_SQL_BASE_ user=_POSTFIXADMIN_SQL_USER_ password=_POSTFIXADMIN_SQL_PASSWORD_

#default_pass_scheme = PLAIN-MD5
default_pass_scheme = MD5-CRYPT

#   %u = entire user@domain
#   %n = user part of user@domain
#   %d = domain part of user@domain

password_query = SELECT username as user, password, '%u' AS userdb_master_user, CONCAT('/opt/mail/vmail/', maildir) AS userdb_home, 5000 AS userdb_uid, 5000 AS userdb_gid, CONCAT('*:storage=', quota, 'B') as userdb_quota_rule FROM mailbox WHERE username = '%u' AND active = '1'

user_query = SELECT CONCAT('/opt/mail/vmail/', maildir) AS home, 5000 AS uid, 5000 AS gid, CONCAT('*:storage=', quota, 'B') as quota_rule FROM mailbox WHERE username = '%u' AND active = '1'

ВАЖНО!
password_query = ..., user_query = ... - должны быть ОДНОЙ строкой (без переносов)!
Кроме того, в этом конфиге надо использовать только "127.0.0.1"! При использования "localhost", коннект происходит на файловый сокет. Этот адрес должен совпадать с указанным в "/etc/misql/my.conf".

/etc/dovecot/dovecot-sql-master.conf.ext

driver = mysql
#default_pass_scheme = PLAIN-MD5
default_pass_scheme = MD5-CRYPT

connect = host=127.0.0.1 dbname=_POSTFIXADMIN_SQL_BASE_ user=_POSTFIXADMIN_SQL_USER_ password=_POSTFIXADMIN_SQL_PASSWORD_

password_query = SELECT username AS user, password FROM admin WHERE username = '%u' AND active = '1'

Отключаем пока неиспользуемые конфиги:

mv /etc/dovecot/conf.d/auth-checkpassword.conf.ext /etc/dovecot/conf.d/auth-checkpassword.conf.ext_
mv /etc/dovecot/conf.d/auth-deny.conf.ext /etc/dovecot/conf.d/auth-deny.conf.ext_
mv /etc/dovecot/conf.d/auth-master.conf.ext /etc/dovecot/conf.d/auth-master.conf.ext_
mv /etc/dovecot/conf.d/auth-passwdfile.conf.ext /etc/dovecot/conf.d/auth-passwdfile.conf.ext_
mv /etc/dovecot/conf.d/auth-static.conf.ext /etc/dovecot/conf.d/auth-static.conf.ext_
mv /etc/dovecot/conf.d/auth-system.conf.ext /etc/dovecot/conf.d/auth-system.conf.ext_
mv /etc/dovecot/conf.d/auth-vpopmail.conf.ext /etc/dovecot/conf.d/auth-vpopmail.conf.ext_

Задаем права и владельца конфигов:

chgrp vmail /etc/dovecot/*.conf
chmod g+r /etc/dovecot/*.conf
chgrp vmail /etc/dovecot/*.ext
chmod g+r /etc/dovecot/*.ext
chgrp vmail /etc/dovecot/conf.d/*.conf
chmod g+r /etc/dovecot/conf.d/*.conf
chgrp vmail /etc/dovecot/conf.d/*.ext
chmod g+r /etc/dovecot/conf.d/*.ext

Сертификаты

Если есть валидные сертификаты, или есть возможность создать такие, то лучше использовать их. Здесь мы рассмотрим вариант использования самоподписанных сертификатов.

Создаем для использования Postfix:

openssl req -new -x509 -days 3650 -nodes -out /etc/postfix/ssl.cert.pem -keyout /etc/postfix/ssl.key.pem
chmod o= /etc/postfix/ssl.key.pem

Создаем для использования Dovecot:

openssl req -new -x509 -days 3650 -nodes -out /etc/dovecot/ssl.cert.pem -keyout /etc/dovecot/ssl.key.pem
chmod 444 /etc/dovecot/ssl.cert.pem
chmod 400 /etc/dovecot/ssl.key.pem
chown root:root /etc/dovecot/ssl.cert.pem
chown root:root /etc/dovecot/ssl.key.pem

Проверка работы SSL

openssl s_client -tls1 -crlf -connect localhost:25
openssl s_client -tls1 -crlf -connect mail.dest.loc:25

openssl s_client -starttls smtp -showcerts -connect localhost:25
openssl s_client -starttls smtp -showcerts -connect mail.dest.loc:25

openssl s_client -starttls smtp -crlf -connect mail.dest.loc:25

openssl s_client -starttls imap -crlf -connect localhost:143

Последняя команда может выдавать ошибку, если IMAP на 143 порту для localhost настроен без TLS.

Перезапускаем dovecot:

systemctl restart dovecot

Проверяем работу dovecot.
Проверка авторизации, где _USER_ - полностью имя ящика, а _PASSWORD_ - пароль

doveadm auth -x service=imap -x rip=127.0.0.1 _USER_ _PASSWORD_

Проверка конфигурации:

doveconf -a

В конце вывода не должно быть ошибок.

Установка web-клиента Roundcube

Доустанавливаем необходимые пакеты:

yum install php-xml php-intl php-gd php-pear ImageMagick ImageMagick-devel java

Вносим изменения в /etc/php.ini

error_reporting E_ALL & ~E_NOTICE & ~E_STRICT
memory_limit = 128MB
post_max_size = 16M
file_uploads On
upload_max_filesize = 10M
date.timezone = Europe/Moscow ;Установить вашу временную зону session.auto_start = 0 mbstring.func_overload = 0

Добавляем модуль imagick:

pecl install imagick

Начнется процесс компиляции модуля. На вопрос: “Please provide the prefix of Imagemagick installation” отвечаем: “all” и жмём enter. Процесс завершится приблизительно такими строками:

Build process completed successfully
install ok: channel://pecl.php.net/imagick-3.0.1
You should add "extension=imagick.so" to php.ini

добавляем модуль в конфигурацию php:

echo "extension=imagick.so" > /etc/php.d/imagick.ini

Перезапускаем web-сервер:

systemctl restart httpd
cd /opt/www/html

Скачиваем у разработчика последнюю стабильную верси. На момент написания статьи это была версия 1.3.2:

https://github.com/roundcube/roundcubemail/releases/download/1.3.2/roundcubemail-1.3.2-complete.tar.gz

Распакованные файлы помещаем в каталог /opt/www/html
Назначаем владельца:

chown -R apache:apache /opt/www/html/*

Устанавливаем composer, следуя инструкциям на https://getcomposer.org/download/
Далее выполняем:

cp /opt/www/html/composer.json-dist /opt/www/html/composer.json

В файле composer.json необходимо перенести строку "kolab/Net_LDAP3": "dev-master" из раздела "suggest" в раздел "require". Это нам понадобится в дальнейшем для организации корпаративной адресной книги.
Далее выполняем:

php composer.phar install --nodev

Проверяем наличие и права доступа на каталоги:

/op/www/html/logs
/opt/www/html/temp

Web-сервер должен иметь право на запись в эти каталоги.

Далее содаем бызу данных для Roundcube:

#mysql -p
> CREATE DATABASE roundcubemail DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
> GRANT ALL PRIVILEGES ON roundcubemail.* to roundcube@localhost IDENTIFIED BY '_ROUNDCUBE_SQL_PASSWORD_';
quit

Далее создаем таблицы в этой базе данных:

mysql -u roundcube -p roundcubemail  /opt/www/html/SQL/mysql.initial.sq

Подготовительные опрерации завершены. Можно приступать к настройке Roundcube. В браузере открываем страницу установщика: http://mail.dest.loc/installer/. На этой странице диагностики по всем пунктам, кроме неустановленных баз данных, должно стоять "Ok". Если это не так, то смотрим, что не устраивает и исправляем. После того, как все исправлено жмем кнопку "NEXT" и переходим на страницу создания конфига. Заполняем необходимые поля:

  • product_name - Название организации. Отображается на странице клиента
  • database password  - Пароль созданного пользователя roundcube
  • default_host - tls://127.0.0.1
  • smtp_server - tls://127.0.0.1
  • language ru_RU
  • Выбираем плагины, которые необходимо подключить

Жмем "Create config". Конфигурационный файл запишется. Жмем "Continue" и переходим на страницу тестов.

На странице проверяем везде ли стоит признак "Ok", проверяем возможность подключения по SMTP и IMAP. Если все в порядке, то основные настройки закончены и можно открывать на основной странице сайта почтовый клиент.

Осталось только настроить всевозможные плагины. В данной статье о них речь не пойдет.

Для доступа с почтовых клиентов включаем IMAPs. Открываем параметры в файле /etc/dovecot/conf.d/10-master.conf

service imap-login {
       inet_listener imap {
            address = 127.0.0.1
            port = 143
       }
       inet_listener imaps {
            address = 192.168.20.104
            port = 993
            ssl = yes
       }
}

Для того, что бы пользователи со своих ПК с помощью почтовых клиентов смогли отправлять почту через postfix, в файле /etc/postfix/main.cf комментируем строчку ограничения SMTP (при желании можно будет настроить позже под свои потребности:

# check_helo_access hash:/etc/postfix/hello_access,

После этого перезапускаем Postfix

Открываем соответствующий порт в файерволе:

firewall-cmd --permanent --add-port=993/tcp
firewall-cmd --reload

В итоге мы получили готовый почтовый сервер, управление пользователями (добавление-удаление-настройка) на котором производится посредством web-интерфейса Postfixadmin. А что делать, если в сети уже развернута структура Active Directory с множеством пользователей и каждому требуется доступ к почтовому сервису. Заводить для каждого почтовый ящик это не вариант. Решение описано дальше.

Active Directory

Вводные данные:

  • Доступ к службам реализован только с помощью SSL по соображениям безопасности;
  • Уровень домена и леса Active Directory должен быть не выше Windows 2008 R2;
  • В данной версии инструкции не рассматривается конфигурация для подключения Microsoft Exchange на основе MAPI или EWS;
  • Для подключения в данной конфигурации можно использовать Microsoft Outlook версии, начиная с 2003 в режиме подключения почты по IMAP;

Важно:

Доступ к серверу LDAP осуществляется по протоколу ldap без шифрования. Для SambaDC отключите обязательный ldaps в /etc/samba/smb.conf в секции [global]:

ldap server require strong auth = no

Создание пользователей в Active Directory.

Создаётся пользователь vmail с не истекающей учётной записью:

samba-tool user create -W Users vmail
samba-tool user setexpiry vmail --noexpiry

В каталоге /etc/postfix изменяем файлы для домена dest.loc:

main.cf

mailbox_command = /usr/libexec/dovecot/dovecot-lda -f "$SENDER" -a "$RECIPIENT"
virtual_mailbox_maps = mysql:/etc/postfix/mysql_virtual_maps.cf,ldap:/etc/postfix/ad_local_recipients.cf
virtual_alias_maps = mysql:/etc/postfix/mysql_virtual_alias_domain_maps.cf,mysql:/etc/postfix/mysql_virtual_alias_maps.cf,ldap:/etc/postfix/ad_mail_groups.cf
local_transport = virtual
local_recipient_maps = $virtual_mailbox_maps

smtpd_use_tls = yes
#smtpd_tls_security_level = encrypt
smtpd_tls_security_level = may
smtpd_sasl_auth_enable = yes
smtpd_sasl_local_domain = dest.loc
smtpd_sasl_path = private/auth
smtpd_sasl_type = dovecot
smtpd_sender_login_maps = ldap:/etc/postfix/ad_sender_login.cf
#smtpd_tls_auth_only = yes
#smtpd_recipient_restrictions = permit_mynetworks, reject_unauth_destination, permit_sasl_authenticated, reject
#smtpd_sender_restrictions = reject_authenticated_sender_login_mismatch

master.cf

dovecot   unix  -       n       n       -       -       pipe
  flags=DRhu user=mail:mail argv=/usr/libexec/dovecot/deliver -d ${recipient}
smtps     inet  n       -       n       -       -       smtpd
  -o smtpd_tls_wrappermode=yes
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_client_restrictions=permit_sasl_authenticated,reject

Создаем файл /etc/postfix/ad_local_recipients.cf

version = 3
server_host = dest-dc-01.dest.loc.loc:389
search_base = ou=Firma,dc=dest,dc=loc
scope = sub
query_filter = (&(|(mail=%s)(otherMailbox=%u@%d))(sAMAccountType=805306368))
result_filter = %s
result_attribute = mail
special_result_attribute = member

bind = yes
bind_dn = cn=vmail,cn=users,dc=dest,dc=loc
bind_pw = Pa$$word

Создаем файл /etc/postfix/ad_mail_groups.cf

version = 3
server_host = dest-dc-01.dest.loc.alt:389
search_base = ou=Firma,dc=dest,dc=loc
timeout = 3
scope = sub
#query_filter = (&(mail=%s)(sAMAccountType=268435456))
query_filter = (&(objectclass=group)(mail=%s))
result_filter = %s
#result_attribute = mail
leaf_result_attribute = mail
special_result_attribute = member

bind = yes
bind_dn = cn=vmail,cn=users,dc=dest,dc=loc
bind_pw = Pa$$word

Создаем файл /etc/postfix/ad_sender_login.cf

version = 3
server_host = dest-dc-01.dest.loc:389
search_base = ou=Firma,dc=dest,dc=loc
scope = sub
query_filter = (&(objectClass=user)(|(sAMAccountName=%s)(mail=%s)))
result_attribute = mail

bind = yes
bind_dn = cn=vmail,cn=users,dc=test,dc=alt
bind_pw = Pa$$word

В данном случае в свойствах пользователя Active Directory должны быть заполнены атрибуты "mail" и "otherMailbox" (они должны быть одинаковы и содержать имя пользователя (желательно совпадающее с логином) и имя локального домена - Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в вашем браузере должен быть включен Javascript.)

Проверяем конфигурацию Postfix и перезапускаем:

postconf >/dev/null
systemctl restart postfix

Проверяем LDAP-запросы.

Проверка наличия почтового ящика у пользователя test

postmap -q Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в вашем браузере должен быть включен Javascript. ldap:/etc/postfix/ad_local_recipients.cf
Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в вашем браузере должен быть включен Javascript.

Если все правильно, то выдаст почтовый адрес пользователя test. Если вывод пустой, то либо неправильно заполнены атрибуты пользователя, либо ошибка в запросе.

Проверка входа:

# postmap -q Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в вашем браузере должен быть включен Javascript. ldap:/etc/postfix/ad_sender_login.cf
Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в вашем браузере должен быть включен Javascript.

Создаем в Active Directory группу распространения. Присваиваем ей адрес (например Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в вашем браузере должен быть включен Javascript.). Добавляем в эту группу пользователей с заполненными почтовыми атрибутами. Это группа будет являтся группой рассылки с указанным адресом (Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в вашем браузере должен быть включен Javascript.). Для нашего примера в группу будут входить пользователя test и test2. Проверяем:

# postmap -q Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в вашем браузере должен быть включен Javascript. ldap:/etc/postfix/ad_mail_groups.cf
Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в вашем браузере должен быть включен Javascript.,Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в вашем браузере должен быть включен Javascript.

Настраиваем dovecot.

Создаём файл /etc/dovecot/dovecot-ldap.conf.ext

hosts            = dest-dc-01.dest.loc:3268
ldap_version     = 3
auth_bind        = yes
dn               = cn=vmail,cn=Users,dc=test,dc=alt
dnpass           = Pa$$word
base             = ou=Firma,dc=dest,dc=loc
scope            = subtree
deref            = never

user_filter = (&(objectClass=user)(|(mail=%Lu)(sAMAccountName=%Lu)))
user_attrs  = =uid=5000,gid=5000,mail=user
pass_filter = (&(objectClass=user)(|(mail=%Lu)(sAMAccountName=%Lu)))
pass_attrs = mail=user

Важно! Значение base не должно содержать только значения dc, иначе при попытке использования будет 'Operation error'.

Вносим правки в конфиги Dovecot

10-auth.conf:

#auth_username_format = %Lu
#auth_gssapi_hostname = "$ALL"
#auth_krb5_keytab = /etc/dovecot/dovecot.keytab
#auth_use_winbind = no
#auth_winbind_helper_path = /usr/bin/ntlm_auth
#auth_failure_delay = 2 secs
auth_mechanisms = plain
!include auth-ldap.conf.ext

10-mail.conf

mail_location = maildir:/opt/mail/vmail/%d/%n:UTF-8:INBOX=/opt/mail/vmail/%d/%n/Inbox
mail_uid = 5000
mail_gid = 5000
first_valid_uid = 5
first_valid_gid = 5

10-master.conf

service imap-login {
  inet_listener imap {
    address = 127.0.0.1
    port = 143
#    port = 0
  }
  inet_listener imaps {
    address = 192.168.20.104
    port = 993
    ssl = yes
  }
}
service pop3-login {
  inet_listener pop3 {
    port = 0
  }
  inet_listener pop3s {
    port = 0
  }
}
service lmtp {
  unix_listener lmtp {
    path = /var/spool/postfix/private/dovecot-lmtp
    group = postfix
    mode = 0660
    user = postfix
  }
  executable = lmtp -L
}
service imap {
}
service pop3 {
}
service auth {
  unix_listener auth {
      path = /var/spool/postfix/private/auth
      mode = 0660
      user = postfix
      group = postfix
  }
  unix_listener auth-userdb {
  }
#  unix_listener /var/spool/postfix/private/auth {
#    mode = 0600
#   user = postfix
#    group = postfix
#  }
  user = $default_internal_user
}
service auth-worker {
  user = $default_internal_user
}
service dict {
  unix_listener dict {
  }
}

15-lda.conf

protocol lda {
  hostname = dest.loc
  postmaster_address = Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в вашем браузере должен быть включен Javascript.
}

15-mailboxes.conf

namespace inbox {
  mailbox Drafts {
    auto = subscribe
    special_use = \Drafts
  }
  mailbox Junk {
    auto = subscribe
    special_use = \Junk
  }
  mailbox Trash {
    auto = subscribe
    special_use = \Trash
  }
  mailbox Sent {
    auto = subscribe
    special_use = \Sent
  }
  mailbox "Sent Messages" {
    special_use = \Sent
  }
}

Проверяем и перезапускаем Dovecot:

doveconf >/dev/null
systemctl restart dovecot

В связи с тем, что конфигурационные файлы содержат пароль пользователя LDAP, их необходимо сделать недоступным для чтения прочим пользователям:

chown dovecot:root /etc/dovecot/dovecot-ldap.conf.ext
chmod 0640 /etc/dovecot/dovecot-ldap.conf.ext
chown root:postfix /etc/postfix/ad_local_recipients.cf /etc/postfix/ad_mail_groups.cf /etc/postfix/ad_sender_login.cf
chmod 0640 /etc/postfix/ad_local_recipients.cf /etc/postfix/ad_mail_groups.cf /etc/postfix/ad_sender_login.cf

Подключение адресной книги локальных пользователей. Для большой организации как правило пользователям нужна адресная книга, которая содержит все почтовые адреса организации. Настроим такую в клиенте Roundcube. Открываем файл /opt/www/html/config/config.inc.php и добавляем следующие строки:

// Active Directory Address Book
$config['ldap_public'] = array(
   'MyAdLdap' =>
   array (
      'name' => 'Фирма',
      'hosts' =>
      array (
         0 => 'dest-dc-01.dest.loc, dest-dc-02.dest.loc',
      ),
      'sizelimit' => 6000,
      'port' => 389,
      'use_tls' => false,
      'user_specific' => false,
      'base_dn' => 'ou=Firma,dc=dest,dc=loc',
      'bind_dn' => Адрес электронной почты защищен от спам-ботов. Для просмотра адреса в вашем браузере должен быть включен Javascript.',
      'bind_pass' => 'pa$$word',
      'writable' => false,
      'ldap_version' =>3,
      'search_fields' =>
      array (
         0 => 'mail',
         1 => 'cn',
      ),
      'name_field' => 'cn',
      'email_field' => 'mail',
      'first_field' => 'giveName',
      'sort' => 'sn',
      'scope' => 'sub',
      'filter' => '(&(mail=*)(|(&(objectClass=user)(!(objectClass=computer)))(objectClass=group)))',
      'global_search' => true,
      'fuzzy_search' => true,
   ),
);

Итог.

Мы получили работающий почтовый сервер, который использует базу Active Directory для локальных адресов пользователей и mysql для прочих доменов. Управление локальными пользователями осуществляется псредством Active Directory, а управление прочими пользователями через PostfixAdmin.

Дополнительная информация

  • Так же интересно:
Прочитано 23918 раз Последнее изменение Пятница, 10 ноября 2017 16:22
Авторизуйтесь, чтобы получить возможность оставлять комментарии
Top
Этот шаблон Joomla был скачан с сайта ДжуМикс.