
Уходим из office365. Почтовый сервер на Postfix+Dovecot + LDAP
Создание почтового сервера, максимально соответствующего функционалу office365 для организации с интеграцией в Active Directory, и с последующей миграцией из облака Microsoft, для тех, кто там побывал.
Конечно, протокол MAPI невозможно заменить "один к одному", поэтому строятся максимальные аналоги работы
Реализация
Debian почтовый сервер postfix с хранением в IMAP через DOVECOT, с авторизацией в AD по параметру mail, возможностью сортировки писем на сервере, веб-клиентом почты, календарей, контактов и конференций в nextcloud.
Состав:
- postfux - MTA (LDAP)
- dovecot - IMAP (LDAP)
- amavis + clamav + spamassasin
- nextcloud с модулями
*SnappyMail - webmail
*AppOrder - показ приложений
*Calendar - caldav
*Contacts - carddaw
*LDAP user and group backend
*Talk - конференции
и тд (рекомендованные)
Сеть:
- открытые входящие порты
*80 443 - www
*22 - ssh
*3478 - stun
*25 465 993 - mail
*4190 - sieve
*10050 10051 - zabbix
- смонтировано NFS шара хранилища, async mode, 12 theads (синхронный режим NFS нагружает систему и замедляет работу с imap)
/etc/fstab:
192.168.0.20:/c/vmail /home/vmail nfs defaults 0 0
, где 192.168.0.20 - адрес NFS хранилища
mail.domain.ru - почтовый сервер для настройки
ad.domain.local - контроллер домена AD
Установка:
apt-get install postfix dovecot-imapd dovecot-pop3d mailutils postfix-ldap dovecot-core dovecot-imapd dovecot-pop3d dovecot-lmtpd dovecot-ldap dovecot-sieve dovecot-managesieved
Директория хранения - /home/vmail
sudo groupadd -g 5000 vmail
sudo useradd -g vmail -u 5000 vmail -d /home/vmail -m
chown vmail:vmail /home/vmail
Конфигурация Postfix
/etc/postfix/main.cf - основной файл конфигурации
readme_directory = /usr/share/doc/postfix/README_FILES
html_directory = /usr/share/doc/postfix/html
setgid_group = postdrop
command_directory = /usr/sbin
manpage_directory = /usr/share/man
#daemon_directory = /usr/lib/postfix
data_directory = /var/lib/postfix
newaliases_path = /usr/bin/newaliases
mailq_path = /usr/bin/mailq
queue_directory = /var/spool/postfix
mail_owner = postfix
#inet_protocols = all
inet_protocols = ipv4
mynetworks_style = host
smtpd_banner = mail2
unknown_local_recipient_reject_code = 550
myhostname = mail.domain.ru
alias_maps = hash:/etc/aliases
virtual_alias_maps = hash:/etc/postfix/virtual
alias_database = hash:/etc/aliases
myorigin = /etc/mailname
mydestination =
relayhost =
mynetworks = /etc/postfix/mynetworks
mailbox_size_limit = 0
recipient_delimiter = +
inet_interfaces = all
#message size to 25Mb
message_size_limit = 26000000
# CC in one message -7
smtpd_recipient_limit = 30
smtpd_delay_reject = yes
strict_rfc821_envelopes = yes
address_verify_sender = adm@domain.ru
virtual_transport = dovecot
dovecot_destination_recipient_limit = 1
transport_maps = hash:/etc/postfix/transport
virtual_mailbox_domains = domain.ru, domain2.ru, domain.com
virtual_mailbox_base = /home/vmail/%n
#virtual_mailbox_maps = hash:/etc/postfix/vmaps
virtual_mailbox_maps = ldap:/etc/postfix/ldap_mailbox_maps.cf
#dovecot/users
virtual_minimum_uid = 5000
virtual_uid_maps = static:5000
virtual_gid_maps = static:5000
maps_rbl_reject_code = 554
disable_vrfy_command = yes
# фильтры
content_filter = scan:[127.0.0.1]:10024
#SASL options
smtpd_sasl_auth_enable = yes
#smtpd_sasl_exceptions_networks = $mynetworks
smtpd_sasl_security_options = noanonymous
broken_sasl_auth_clients = yes
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
# enable TLS
smtp_use_tls = yes
smtpd_use_tls = yes
#smtpd_tls_auth_only = yes
smtpd_helo_required = yes
smtpd_tls_cert_file = /etc/ssl/private/full.crt
smtpd_tls_key_file = /etc/ssl/private/domain.ru.key
#smtpd_sasl_path = /var/run/dovecot/auth-client
# пассивная защита от спама
smtpd_relay_restrictions =
permit_mynetworks
permit_sasl_authenticated
reject_unauth_destination
smtpd_sender_restrictions = permit_mynetworks,
check_sender_access hash:/etc/postfix/sender_access,
reject_unknown_sender_domain,
reject_non_fqdn_sender,
reject_sender_login_mismatch,
permit_sasl_authenticated,
check_client_access hash:/etc/postfix/rbl_override,
reject_rhsbl_sender dsn.rfc-ignorant.org
smtpd_recipient_restrictions = permit_mynetworks,
reject_unknown_recipient_domain,
reject_non_fqdn_recipient,
permit_sasl_authenticated,
reject_unauth_destination,
reject_unauth_pipelining,
reject_unlisted_recipient,
reject_unknown_sender_domain
smtpd_helo_restrictions = permit_mynetworks,
check_helo_access hash:/etc/postfix/helo_access,
permit_sasl_authenticated,
smtpd_client_restrictions = permit_mynetworks,
permit_sasl_authenticated,
reject_rbl_client virbl.dnsbl.bit.nl,
reject_rbl_client dynablock.wirehub.net,
reject_rbl_client blackholes.wirehub.net,
reject_rbl_client dialups.mail-abuse.org,
reject_rbl_client blackholes.mail-abuse.org,
reject_rbl_client dialups.mail-abuse.org,
reject_rbl_client dul.dnsbl.sorbs.net,
reject_rhsbl_client sbl.spamhaus.org,
reject_rhsbl_client dnsbl.sorbs.net
/etc/postfix/ldap_mailbox_maps.cf - конфиг работы с AD
server_host = ad.domain.local
server_port = 389
version = 3
search_base = dc=domain,dc=local
query_filter = (&(objectClass=user)(mail=%s)(!(userAccountControl:1.2.840.113556.1.4.803:=2)))
result_attribute = mail
scope = sub
#bind = yes
bind_dn = userad@domain.local
bind_pw = password123
debuglevel = 0r
master.cf - существенные изменения
# для связки с dovecot
submission inet n - n - - smtpd
-o smtpd_tls_security_level=may
-o smtpd_sasl_auth_enable=yes
-o smtpd_sasl_type=dovecot
-o smtpd_sasl_path=/var/spool/postfix/private/auth
-o smtpd_sasl_security_options=noanonymous
-o smtpd_sasl_local_domain=$myhostname
smtps inet n - n - - smtpd
-o syslog_name=postfix/smtps
-o smtpd_tls_wrappermode=yes
-o smtpd_sasl_auth_enable=yes
-o smtpd_client_restrictions=permit_sasl_authenticated,reject
dovecot unix - n n - - pipe
flags=DRhu user=vmail:vmail argv=/usr/lib/dovecot/deliver -d ${recipient}
# для связки с amavis
scan unix - - n - 16 smtp
-o smtp_send_xforward_command=yes
-o smtp_enforce_tls=no
127.0.0.1:10025 inet n - n - 16 smtpd
-o content_filter=
-o receive_override_options=no_unknown_recipient_checks,no_header_body_checks
-o smtpd_helo_restrictions=
-o smtpd_client_restrictions=
-o smtpd_sender_restrictions=
-o smtpd_recipient_restrictions=permit_mynetworks,reject
-o mynetworks_style=host
-o smtpd_authorized_xforward_hosts=127.0.0.0/8:
Карты
/etc/postfix/mynetworks - доверенные сети
127.0.0.0/8
172.16.0.0/16
192.168.0.0/24
104.47.0.0/16
, последняя - microsoft, для настройки транспорта с облака "Exchange admin center/mailflow/connectors"
в случае, если office365 прописан в mx - записи домена
/etc/postfix/transport - карта транспорта
#user1@domain.ru smtp:[domain-ru.mail.protection.outlook.com]:25
user2@domain.ru smtp:[domain-ru.mail.protection.outlook.com]:25
user3@domain.ru smtp:[domain-ru.mail.protection.outlook.com]:25
, где user1 уже перемещен, а почта остальных всё еще уходит в облако
#/etc/postfix/helo_access доверенные по HELO
domain.ru OK
#/etc/postfix/rbl_override доверенные rbl
mail.domain.ru OK
#/etc/postfix/sender_access доверенные отправители
domain.ru OK
domain2.ru OK
.domain.ru OK
domain.com OK
#/etc/postfix/virtual виртуальные ящики (aliases не работают в мультидоменной конфигурации корректно)
adm@domain.ru user1@domain.ru user2@domain.ru user3@domain.ru
all@domain.ru user1@domain.ru user2@domain.ru user3@domain.ru
и тд..
№/etc/postfix/apply-changes.sh применение изменений всех карт
postmap transport
postmap virtual
postmap sender_access
/etc/init.d/postfix reload
Dovecot
#/etc/dovecot/dovecot-ldap.conf.ext конфигурация в ldap
hosts = ad.domain.local:389
ldap_version = 3
auth_bind = yes
dn = userad@domain.local
dnpass = password123
base = dc=domain,dc=local
scope = subtree
deref = never
user_attrs = homeDirectory=/home/vmail/%d/%n,uid=5000,gid=5000
user_filter = (&(objectClass=user)(mail=%u)(!(userAccountControl:1.2.840.113556.1.4.803:=2)))
pass_filter = (&(objectClass=user)(mail=%u)(!(userAccountControl:1.2.840.113556.1.4.803:=2)))
#/etc/dovecot/conf.d/10-mail.conf: отредактировать
auth_username_format = %Lu
auth_mechanisms = plain login digest-md5 cram-md5
disable_plaintext_auth = no
mail_location = maildir:/home/vmail/%d/%n
!include auth-ldap.conf.ext
#/etc/dovecot/10-mail.conf: отредактировать
mail_location = maildir:/home/vmail/%d/%n
mail_home = /var/vmail/%d/%n/sieve
mail_uid = vmail
mail_gid = vmail
#/etc/dovecot/10-master.conf: отредактировать
service auth {
unix_listener auth-userdb {
mode = 0600
user = vmail
group = vmail
}
unix_listener /var/spool/postfix/private/auth {
mode = 0660
user = postfix
group = postfix
}
}
service stats {
unix_listener stats-reader {
user = vmail
group = vmail
mode = 0660
}
unix_listener stats-writer {
user = vmail
group = vmail
mode = 0660
}
}
#/etc/dovecot/10-ssl.conf
ssl = yes
ssl_cert = </etc/ssl/private/full.crt
ssl_key = </etc/ssl/private/domian.ru.key
#/etc/dovecot/conf.d/15-lda.conf
protocol lda {
mail_plugins = $mail_plugins sieve
}
#/etc/dovecot/15-mailboxes.conf
namespace inbox {
mailbox Drafts {
special_use = \Drafts
}
mailbox Junk {
special_use = \Junk
}
mailbox Trash {
special_use = \Trash
}
mailbox Черновики {
auto = subscribe
special_use = \Drafts
}
mailbox Спам {
auto = subscribe
special_use = \Junk
}
mailbox Spam {
auto = no
special_use = \Junk
}
mailbox "Junk E-mail" {
auto = no
special_use = \Junk
}
mailbox "Deleted Messages" {
auto = no
special_use = \Trash
}
mailbox Отправленные {
auto = subscribe
special_use = \Sent
}
mailbox Удаленные {
auto = subscribe
special_use = \Trash
}
mailbox Sent {
special_use = \Sent
}
mailbox "Sent Messages" {
special_use = \Sent
}
mailbox Sent {
auto = no
special_use = \Sent
}
mailbox "Sent Messages" {
auto = no
special_use = \Sent
}
mailbox "Sent Items" {
auto = no
special_use = \Sent
}
}
#/etc/dovecot/20-managesieve.conf: отредактировать
protocols = $protocols sieve
...
service managesieve-login {
inet_listener sieve {
port = 4190
}
...
#/etc/dovecot/90-sieve.conf: отредактировать
...
plugin {
...
sieve = /home/vmail/%d/%n/sieve/dovecot.sieve
sieve_global_path = /etc/dovecot/sieve/default.sieve
sieve_dir = /home/vmail/%d/%n/sieve
sieve_global_dir = /etc/dovecot/sieve/global/
...
Донастройка Sieve:
#mkdir -p /etc/dovecot/sieve/global
#chown dovecot:dovecot -R /etc/dovecot/sieve
AMAVIS + clamav + spamassassin
Установка
apt-get install amavisd-new clamav clamav-daemon spamassassin
usermod -a -G amavis clamav
/etc/amavis/conf.d/15-content_filter_mode отредактировать
...
@bypass_virus_checks_maps = (
\%bypass_virus_checks, \@bypass_virus_checks_acl, \$bypass_virus_checks_re);
...
@bypass_spam_checks_maps = (
\%bypass_spam_checks, \@bypass_spam_checks_acl, \$bypass_spam_checks_re);
...
/etc/amavis/conf.d/50-user добавить
$allowed_header_tests{'multiple'} = 0;
$allowed_header_tests{'missing'} = 0;
$spam_quarantine_to = "spam\@domain.ru";
$virus_quarantine_to = "virus\@domain.ru";
systemctl enable clamav-daemon amavis
Обновить clamav можно вручную, разместив скачанные каким либо с адресов
https://database.clamav.net/main.cvd
https://database.clamav.net/daily.cvd
https://database.clamav.net/bytecode.cvd
файлы в /var/lib/clamav
Обновить спам базы
sa-update --nogpg --verbose
Обучение:
# обучение спаму
#sa-learn --spam /home/vmail/_spam
# обучение ошибочных определений спама
#sa-learn --ham /home/vmail/_am
# статистика
#sa-learn --dump magic
Перезапуск:
#systemctl restart amavis && systemctl restart dovecot && systemctl restart postfix
Тестирование:
Проверка открытых портов
#netstat -tpln
Проверка postmap
#postmap -vq user@domain.ru ldap:/etc/postfix/ldap_mailbox_maps.cf
Отправка SMTP
#echo "Test mail" | mail -s "Test mail" user@domain.ru
Проверка ldap
#ldapsearch -x -h ad.domain.ocal -D 'userad' -W -b 'cn=Users,dc=domain,dc=local'
Проверка IMAP
#openssl s_client -crlf -connect 127.0.0.1:993
#tag login user@domain.ru password123
NextCloud
Установка
Для функционирования требуется стандартный LAMP (Linux, Apache, MySQL/MariaDB, PHP). с рекомендуемыми модулями, описанными в
Настроить базу данных для nextcloud MySQL или SQLite
Скачать со страницы загрузки nextcloud последнюю стабильную версию
https://download.nextcloud.com/server/releases/
Распаковать в root директорию веб-сервера
Применить права
#chown -R www-data:www-data /var/www/nextcloud/
Использовать веб или консольную установку
Обновление Nextcloud
Сделать бэкап data/ и config/
Режим обслуживания и остановить apache
sudo -u www-data php occ maintenance:mode --on
/etc/init.d/apache2 stop
mv /var/www/nextcloud/ /var/www/_nextcloud/
Скачать и распаковать дистрибутив
wget https://download.nextcloud.com/server/releases/nextcloud-24.0.7.zip
или актуальную
unzip nextcloud-24.0.7.zip -d /var/www/
Перезаписать config/
chown -R www-data:www-data nextcloud
find nextcloud/ -type d -exec chmod 750 {} \;
find nextcloud/ -type f -exec chmod 640 {} \;
Запустить apache и обновление
/etc/init.d/apache2 start
sudo -u www-data php occ upgrade
Выход из режима обслуживания
sudo -u www-data php occ maintenance:mode --off
Настройка
Полезное в сonfig.php:
Вынести директорию /data в другое расположение
'datadirectory' => '/home/vcloud',
Указать доверенные домены функционирования
'trusted_domains' =>
array (
0 => 'mail.domain.ru',
1 => 'mail.domain.com',
),
Приложения
Приложение user_external
Позволяет авторизоваться пользователям по определенному протоколу
https://github.com/nextcloud/user_external#readme
Например IMAP
Прописать в config.php:
'user_backends' => array(
array(
'class' => '\OCA\UserExternal\IMAP',
'arguments' => array(
'192.168.0.1', 993, 'ssl', 'domain.ru', false, false
),
),
),
Если используется LDAP - данное приложение не нужно
Приложение LDAP user and group backend
Позволяет добавлять пользователей домена
Настройка по ссылке https://$nextcloudserver/index.php/settings/admin/ldap
Параметры:
Сервер:
Сервер ad.domain.local 389
user password
dc=domain,dc=local
Пользователи:
(&(objectClass=user)(mail=*)(!(userAccountControl:1.2.840.113556.1.4.803:=2)))
Учетные данные:
(&(objectClass=user)(mail=%uid)(!(userAccountControl:1.2.840.113556.1.4.803:=2)))
Эксперт:
Атрибут для внутреннего имени: mail
Дополнительно:
Поле отображаемого имени пользователя - name
База дерева пользователей - dc=domain,dc=local
Атрибуты поиска пользователей - mail
displayName - name
Поле адреса email - mail
apporder
Настраивает порядок приложений и первое открывающееся прописать в config.php:
'defaultapp' => 'apporder',
SnappyMail Webmail
Работает шустрее и гибче чем штатный mail
Управление
https://$nextcloudserve/index.php/apps/snappymail/?admin#
- в разделе домены добавить свой домен с настройками сервера приема/отправки/сортировки(sieve)
(желательно с localhost для быстроты)
Talk
Приложение конференций.
Работает из коробки, но желательно настроить свои STUN / TURN сервера.
apt install coturn
/etc/turnserver.conf:
server-name=mail.domain.ru
use-auth-secret
static-auth-secret=<yourChosen/GeneratedSecret>
total-quota=0
bps-capacity=0
stale-nonce
realm=domain.ru
listening-port=3478
listening-ip=1.1.1.1
fingerprint
total-quota=100
bps-capacity=0
stale-nonce
no-multicast-peers
#no-stdout-log
log-file=/var/log/tun.log
syslog
simple-log
Операции с OCC
Удаление пользователя
# sudo -u www-data php occ user:delete user@domain.ru
Сброс пароля пользователя
# sudo -u www-data php user:resetpassword user
Клиенты
MS Office Outlook
Авто-настройка
Согласно документации, при автоматической настройке, outlook опрашивает:
https://<SMTP-address-domain>/autodiscover/autodiscover.xml
https://autodiscover.<smtp-address-domain>/autodiscover/autodiscover.xml
Причем он делает это не методом GET, а методом POIST.
Нужно создать скрипт autodicover.php:
<?php
//get raw POST data so we can extract the email address
$request = file_get_contents("php://input");
// optional debug log
# file_put_contents( 'request.log', $request, FILE_APPEND );
// retrieve email address from client request
preg_match( "/\<EMailAddress\>(.*?)\<\/EMailAddress\>/", $request, $email );
// check for invalid mail, to prevent XSS
if (filter_var($email[1], FILTER_VALIDATE_EMAIL) === false) {
throw new Exception('Invalid E-Mail provided');
}
// get domain from email address
$domain = substr( strrchr( $email[1], "@" ), 1 );
// POP settings
$popServer = 'mail.' . $domain; // pop.example.com
$popPort = 995;
$popSSL = true;
// IMAP settings
$imapServer = 'mail.' . $domain; // imap.example.com
$imapPort = 993;
$imapSSL = true;
// SMTP settings
$smtpServer = 'mail.' . $domain; // smtp.example.com
$smtpPort = 465;
$smtpSSL = true;
//set Content-Type
header( 'Content-Type: application/xml' );
?>
<?php echo '<?xml version="1.0" encoding="utf-8" ?>'; ?>
<Autodiscover xmlns="http://schemas.microsoft.com/exchange/autodiscover/responseschema/2006" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" >
<Response xmlns="http://schemas.microsoft.com/exchange/autodiscover/outlook/responseschema/2006a">
<Account>
<AccountType>email</AccountType>
<Action>settings</Action>
<Protocol>
<Type>IMAP</Type>
<Server><?php echo $imapServer; ?></Server>
<Port><?php echo $imapPort; ?></Port>
<DomainRequired>off</DomainRequired>
<LoginName><?php echo $email[1]; ?></LoginName>
<SPA>off</SPA>
<SSL><?php echo $imapSSL ? 'on' : 'off'; ?></SSL>
<AuthRequired>on</AuthRequired>
</Protocol>
<Protocol>
<Type>POP3</Type>
<Server><?php echo $popServer; ?></Server>
<Port><?php echo $popPort; ?></Port>
<LoginName><?php echo $email[1]; ?></LoginName>
<DomainRequired>off</DomainRequired>
<SPA>off</SPA>
<SSL><?php echo $popSSL ? 'on' : 'off'; ?></SSL>
<DomainRequired>off</DomainRequired>
</Protocol>
<Protocol>
<Type>SMTP</Type>
<Server><?php echo $smtpServer; ?></Server>
<Port><?php echo $smtpPort; ?></Port>
<DomainRequired>off</DomainRequired>
<LoginName><?php echo $email[1]; ?></LoginName>
<SPA>off</SPA>
<SSL><?php echo $smtpSSL ? 'on' : 'off'; ?></SSL>
<AuthRequired>on</AuthRequired>
<UsePOPAuth>off</UsePOPAuth>
<SMTPLast>off</SMTPLast>
</Protocol>
</Account>
</Response>
</Autodiscover>
Разместить его в веб директории и создать 301 редирект
правилами nginx
location = /autodiscover/autodiscover.xml {
return 301 $scheme://autodiscover.vzlot.ru/autodiscover/autodiscover.php;
}
или .htaccess для apache
Ссылка для онлайн для проверки
https://testconnectivity.microsoft.com/tests/Ola/input
Ручная настройка
выглядит так:
IMAP Сервер
mail.domain.ru
Логин - email
SSL Порт 993
SMTP Сервер
mail.domain.ru
Логин - email
SSL Порт465
OutlookCalDavSynchronizer
Надстройка для Outlook для синхронизации календарей и контактов для M$ OutLook
Создать профиль календаря:
CalDav адрес можно скопировать с персональной страницы календаря nextcloud
https://$nextcloudserver/remote.php/dav/calendars/$email/personal/
username - email
+ Use pop3/IMAP accaumt passwordу
Создать профиль контактом
CardDav адрес можно скопировать с персональной страницы контактов nextcloud
https://nextcloudserver/remote.php/dav/addressbooks/users/$email/contacts/
username - email
+ Use pop3/IMAP accaumt password
Можно подключить системную адресную книгу Nextcloud со всеми пользователями облака по адресу
https://$nextcloudserver/remote.php/dav/addressbooks/system/system/system/
Android OpenSync
Клиент для Android для формирования и синхронизации CalDav/CardDav
Настройка:
Адрес (системная адресная книга):
https://$nextcloudserver/remote.php/dav/addressbooks/system/system/system/
username - email
Остальные источники синхронизации подхватятся сами.
Решения проблем
Сообщение в dovecot-errors.log типа
Обычно в серверах с большим количеством пользователей
exceeded, disabling. Increase /proc/sys/fs/inotify/max_user_instances
В /etc/sysctl.conf прописать 256 (может и более)
fs.inotify.max_user_instances=256
fs.inotify.max_user_watches=256
Применить
sysctl -p
Перманентно пропадают пометки "отвечено"/"переслано" в Microsoft Outlook 2013/2016
Якобы происходит из-за надстроек.
Рекомендуется запустить в безопасном режиме (CTRL+R -> outlook.exe /safe), потом в обычно
Lisolog / 2022