ActiveDirectory/PostfixDovecot

Материал из ALT Linux Wiki

Настройка почты для аутентификации пользователей в Active Directory.

Задача

Настроить почтовую систему на базе Postfix и Dovecot для работы с базой пользователей в ActiveDirectory.

Параметр Значение
Имя домена test.alt
Размещение почты /var/mail/<имя домена>/<имя пользователя>
Формат хранения Maildir
Порт чтения почты 993 (IMAPS)
Порт отправки почты 465 (SMTPS)
Аутентификации: Имя пользователя или полный email
Журнал работы journalctl -fu postfix -fu dovecot

Принятые ограничения

  • Не рассматриваются многодоменные конфигурации;
  • уровень домена и леса Active Directory не должен превышать Windows 2008 R2;
  • не рассматривается конфигурация для подключения Microsoft Exchange на основе MAPI или EWS;
  • в данной конфигурации можно использовать Microsoft Outlook начиная с версии 2003 в режиме подключения почты по IMAP;
  • из соображений безопасности доступ к службам реализован только с помощью SSL.
Внимание! Доступ к LDAP-серверу по протоколу ldap осуществляется без шифрования. Для SambaDC отключите обязательный ldaps в секции [global] файла /etc/samba/smb.conf:
ldap server require strong auth = no

Подготовка

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

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

Установка

apt-get install postfix-ldap dovecot

Настройки служб

Postfix

Внимание! /etc/postfix/mydestination должен быть пустым
/etc/postfix/main.cf  
mailbox_command = /usr/libexec/dovecot/dovecot-lda -f "$SENDER" -a "$RECIPIENT"
inet_protocols = ipv4

# Mappings
virtual_mailbox_base = /var/mail
virtual_mailbox_domains = test.alt
virtual_mailbox_maps = ldap:/etc/postfix/ad_local_recipients.cf
virtual_alias_maps = ldap:/etc/postfix/ad_mail_groups.cf
virtual_transport = dovecot
local_transport = virtual
local_recipient_maps = $virtual_mailbox_maps

# SSL/TLS
smtpd_use_tls = yes
smtpd_tls_security_level = encrypt
#smtpd_tls_security_level = may
smtpd_sasl_auth_enable = yes
smtpd_sasl_local_domain = test.alt
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_tls_cert_file = /var/lib/ssl/certs/dovecot.cert
smtpd_tls_key_file = /var/lib/ssl/private/dovecot.key
smtpd_tls_CAfile = /var/lib/ssl/certs/dovecot.pem

smtpd_recipient_restrictions = permit_mynetworks, reject_unauth_destination, permit_sasl_authenticated, reject
smtpd_sender_restrictions = reject_authenticated_sender_login_mismatch
default_destination_recipient_limit = 1
/etc/postfix/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              = test.alt:389
search_base              = dc=test,dc=alt
scope                    = sub
query_filter             = (&(|(mail=%s)(proxyAddresses=smtp:%u@%d))(sAMAccountType=805306368))
result_filter            = %s
result_attribute         = mail
special_result_attribute = member
bind                     = yes
bind_dn                  = cn=vmail,cn=users,dc=test,dc=alt
bind_pw                  = Pa$$word
/etc/postfix/ad_mail_groups.cf  
version                  = 3
server_host              = test.alt:389
search_base              = dc=test,dc=alt
timeout                  = 3
scope                    = sub
# Искать почтовые адреса групп не только безопасности, но и рассылки/распространения:
query_filter             =  (&(|(mail=%s)(proxyAddresses=smtp:%u@%d))(|(sAMAccountType=268435456)(sAMAccountType=268435457)))
result_filter            = %s
leaf_result_attribute    = mail
special_result_attribute = member
bind                     = yes
bind_dn                  = cn=vmail,cn=users,dc=test,dc=alt
bind_pw                  = Pa$$word
/etc/postfix/ad_sender_login.cf  
version          = 3
server_host      = test.alt:389
search_base      = dc=test,dc=alt
scope            = sub
query_filter     = (&(objectClass=user)(|(sAMAccountName=%s)(mail=%s)(proxyAddresses=smtp:%u@%d)))
result_attribute = mail
bind             = yes
bind_dn          = cn=vmail,cn=users,dc=test,dc=alt
bind_pw          = Pa$$word

При желании русифицировать сообщения почтовика следует в /etc/postfix/main.cf добавить опцию:

bounce_template_file = /etc/postfix/bounce.cf

...и создать прописанный в ней файл (обязательно с пустой строкой в его конце):

/etc/postfix/bounce.cf  
failure_template = <<EOF
Charset: utf-8
From: =?UTF-8?B?0KHQu9GD0LbQsdCwINC/0L7Rh9GC0L7QstC+0Lkg0LTQvtGB0YLQsNCy0LrQuAo==?= <MAILER-DAEMON>
Subject: =?UTF-8?B?0JLQvtC30LLRgNCw0YIg0L3QtdC00L7RgdGC0LDQstC70LXQvdC90L7Qs9C+INGB0L7QvtCx0YnQtdC90LjRjwo==?=
Postmaster-Subject: Postmaster Copy: Undelivered Mail

Почтовая служба на сервере $myhostname уведомляет, что ваше сообщение (см. ниже) доставить не удалось.

За разъяснениями обращайтесь по адресу postmaster@$mydomainname, включив данную ошибку.
При этом текст вашего исходного сообщения в закрепе можно удалить.

                                      Ваш электронный почтальон
EOF

delay_template = <<EOF
Charset: utf-8
From: =?UTF-8?B?0KHQu9GD0LbQsdCwINC/0L7Rh9GC0L7QstC+0Lkg0LTQvtGB0YLQsNCy0LrQuAo==?= <MAILER-DAEMON>
Subject: =?UTF-8?B?0JTQvtGB0YLQsNCy0LrQsCDQv9C+0YfRgtGLINC30LDQtNC10YDQttC40LLQsNC10YLRgdGPCg==
Postmaster-Subject: Postmaster Warning: Delayed Mail

Почтовая служба на сервере $myhostname уведомляет, что ваше сообщение (см. ниже)
не удаётся доставить в течение $delay_warning_time_hours часов.

######################################################################
# Это лишь предупреждение. Отправлять сообщение повторно не следует. #
######################################################################

Попытки повторной отправки продлятся $maximal_queue_lifetime_days дней.

За разъяснениями обращайтесь по адресу postmaster@$mydomainname, включив данную ошибку.
При этом текст вашего исходного сообщения в закрепе можно удалить.

                                      Ваш электронный почтальон
EOF

success_template = <<EOF
Charset: utf-8
From: =?UTF-8?B?0KHQu9GD0LbQsdCwINC/0L7Rh9GC0L7QstC+0Lkg0LTQvtGB0YLQsNCy0LrQuAo==?= <MAILER-DAEMON>
Subject: =?UTF-8?B?0J/QvtGH0YLQsCDQvtGC0L/RgNCw0LLQu9C10L3QsAo=

Почтовая служба на сервере $myhostname уведомляет, что ваше сообщение (см. ниже)
отправлено получателям по означенному списку.

Если сообщение получено адресатом, дальнейших уведомлений не последует.
В противном случае могут поступать отчёты о недоставке от других серверов.

                                      Ваш электронный почтальон
EOF

verify_template = <<EOF
Charset: utf-8
From: =?UTF-8?B?0KHQu9GD0LbQsdCwINC/0L7Rh9GC0L7QstC+0Lkg0LTQvtGB0YLQsNCy0LrQuAo==?= <MAILER-DAEMON>
Subject: =?UTF-8?B?0KHQvtGB0YLQvtGP0L3QuNC1INC+0YLQv9GA0LDQstC60Lgg0YHQvtC+0LHRidC10L3QuNGPCg==

Почтовая служба на сервере $myhostname приводит запрошенный вами отчёт по доставке.

                                      Ваш электронный почтальон
EOF

Dovecot

/etc/dovecot/dovecot-ldap.conf.ext  
hosts        = test.alt:3268
ldap_version = 3
auth_bind    = yes
dn           = cn=vmail,cn=Users,dc=test,dc=alt
dnpass       = Pa$$word
# Параметр 'base' должен содержать не только 'dc=...', иначе возникнет 'Operation error'.
base         = cn=Users,dc=test,dc=alt
scope        = subtree
deref        = never
user_filter  = (&(objectClass=user)(|(mail=%Lu)(proxyAddresses=smtp:%Lu)(sAMAccountName=%Lu)))
user_attrs   = =uid=8,gid=12,mail=user
pass_filter  = (&(objectClass=user)(|(mail=%Lu)(sAMAccountName=%Lu)))
pass_attrs   = mail=user
/etc/dovecot/conf.d/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
/etc/dovecot/conf.d/10-mail.conf  
mail_location   = maildir:/var/mail/%d/%n:UTF-8:INBOX=/var/mail/%d/%n/Inbox
mail_uid        = mail
mail_gid        = mail
first_valid_uid = 5
first_valid_gid = 5
/etc/dovecot/conf.d/10-master.conf  
service imap-login {
    inet_listener imap {
        port = 0
    }
    inet_listener imaps {
    }
}
service pop3-login {
    inet_listener pop3 {
        port = 0
    }
    inet_listener pop3s {
        port = 0
    }
}
service lmtp {
    unix_listener lmtp {
    }
}
service imap {
}
service pop3 {
}
service auth {
    unix_listener auth-userdb {
        mode  = 0660
        user  = mail
        group = dovecot
    }
    unix_listener /var/spool/postfix/private/auth {
        mode  = 0600
        user  = postfix
        group = postfix
    }
}
service stats {
    unix_listener stats-reader {
        user = dovecot
        group = mail
        mode = 0660
    }
    unix_listener stats-writer {
        user = dovecot
        group = mail
        mode = 0660
    }
}
service auth-worker {
}
service dict {
    unix_listener dict {
    }
}
/etc/dovecot/conf.d/15-lda.conf  
protocol lda {
    hostname = test.alt
    postmaster_address = postmaster@test.alt
}
/etc/dovecot/conf.d/15-mailboxes.conf  
namespace inbox {
    inbox = yes
    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
    }
}
Внимание! По завершении настроек файлы, содержащие LDAP-пароль, следует закрыть на чтение прочим пользователям:
# chown root:postfix /etc/postfix/ad_*.cf
# chown dovecot:root /etc/dovecot/dovecot-ldap.conf.ext
# chmod 0640 /etc/postfix/ad_*.cf /etc/dovecot/dovecot-ldap.conf.ext


Запуск служб

  • Впервые и навсегда:
    systemctl enable --now postfix dovecot
  • Если уже запущены, но не настроены на запуск при старте системы:
    for ACT in enable restart; do systemctl $ACT postfix dovecot; done

Тесты на работоспособность

  1. Проверка настроек (не должно выводиться никаких сообщений):
    for S in post dove; do ${S}conf >/dev/null; done
    Если после правки настроек выводится ошибка:
    t_readlink(/run/dovecot/dovecot.conf) failed: readlink() failed: No such file or directory
    
    ...перезапустить службу, и уже после этого ориентироваться на вывод команды.
  2. Проверка почты пользователя petrov:
    postmap -q petrov@test.alt ldap:/etc/postfix/ad_local_recipients.cf
    petrov@test.alt
    
  3. Проверка входа:
    postmap -q petrov@test.alt ldap:/etc/postfix/ad_sender_login.cf
    petrov@test.alt
    
  4. Проверка общего адреса e-mail:
    samba-tool group add --mail-address=sales@test.alt Sales
    Added group Sales
    samba-tool group addmembers Sales ivanov,petrov
    Added members to group Sales
    postmap -q sales@test.alt ldap:/etc/postfix/ad_mail_groups.cf
    ivanov@test.alt,petrov@test.alt
    

Отладка

SMTP

  1. Перезапустить postfix, заменив в /etc/postfix/master.cf:
    smtps     inet  n       -       n       -       -       smtpd
    
    на:
    smtps     inet  n       -       n       -       -       smtpd -v
    
  2. Запустить отслеживание его работы:
    journalctl -fu postfix
  3. Проверить отправку, следя за журналом:
    date | mailx -s test petrov@test.alt && mailq
    Mail queue is empty
    

IMAP

  1. Перезапустить dovecot, добавив в /etc/dovecot/conf.d/10-logging.conf:
    mail_debug   = yes
    auth_debug   = yes
    auth_verbose = yes
    
  2. Запустить отслеживание его работы:
    journalctl -fu dovecot
  3. Проверить вход, следя за журналом (выход по Ctrl+D или Ctrl+C):
    openssl s_client -crlf -connect test.alt:993
    ...
    * OK [CAPABILITY IMAP4rev1 SASL-IR LOGIN-REFERRALS ID ENABLE IDLE LITERAL+ AUTH=PLAIN] Dovecot ready.
    tag login petrov@test.alt Pa$$word
    ...
    tag OK [CAPABILITY IMAP4rev1 LITERAL+ SASL-IR LOGIN-REFERRALS ID ENABLE IDLE SORT SORT=DISPLAY THREAD=REFERENCES THREAD=REFS THREAD=ORDEREDSUBJECT MULTIAPPEND URL-PARTIAL CATENATE UNSELECT CHILDREN NAMESPACE UIDPLUS LIST-EXTENDED I18NLEVEL=1 CONDSTORE QRESYNC ESEARCH ESORT SEARCHRES WITHIN CONTEXT=SEARCH LIST-STATUS BINARY MOVE] Logged in
    

Ссылки