コンテンツにスキップ

PostfixとDovecotのLDAP認証設定

Postfixのローカル受信者検索とDovecotのpassdb・userdbをLDAPへ接続し、LDAPユーザーでSMTP AUTH、LMTP配送、IMAPログインを行う。


項目 値
OS Debian 13.x
メールサーバー mail.example.com / 192.0.2.10
LDAPサーバー ldap.example.com / 192.0.2.20
メールドメイン example.com
Base DN dc=example,dc=com
ユーザー配置先 ou=people,dc=example,dc=com
グループ配置先 ou=groups,dc=example,dc=com
LDAP管理者DN cn=admin,dc=example,dc=com
メールユーザー alice@example.com、bob@example.com
メールボックス /var/vmail/<ユーザー名>/Maildir
SMTP TCP 25、STARTTLS任意
Submission TCP 587、STARTTLS必須、SMTP AUTHあり
IMAP TCP 143、STARTTLS必須
IMAPS TCP 993、Implicit TLS

mail.example.comとldap.example.comをそれぞれのIPアドレスへ名前解決できるようにする。DNSを使わない場合は、メールサーバー、LDAPサーバー、検証用クライアントの/etc/hostsへ登録する。

メールサーバー用にはSANにDNS:mail.example.comを含む証明書、LDAPのStartTLS用にはSANにDNS:ldap.example.comを含む証明書を使用する。証明書の作成はServer Certificateの作成、LDAPサーバー側の設定はLinuxユーザー認証の設定(StartTLS)を参照する。


区分 内容
必須 LDAPユーザー、PostfixのLDAP受信者map、DovecotのLDAP passdb・userdb、メールボックス所有権、SMTP AUTH、LMTP、IMAP
どちらか一方を選択 LDAP接続のTLSなし版、StartTLS版
StartTLS版で必須 LDAPサーバー証明書を検証するCA証明書
LDAPの匿名検索が禁止されている場合に必須 検索用Bind DNとパスワード
任意 IPv6の待受、TLS最小バージョンの明示

1. パッケージをインストールする

Section titled “1. パッケージをインストールする”

メールサーバーへインストールする。

Terminal window
sudo apt update
sudo apt install \
postfix postfix-ldap \
dovecot-core dovecot-imapd dovecot-lmtpd dovecot-ldap \
ldap-utils

postfix-ldapはPostfixのLDAP lookup table、dovecot-ldapはDovecotのLDAP passdb・userdbを提供する。

Postfixの設定形式を聞かれた場合はInternet Site、System mail nameはexample.comを指定する。

Terminal window
postconf mail_version
dovecot --version
postconf -m | grep '^ldap$'

Postfix 3.10系、Dovecot 2.4系、lookup table typeのldapが表示されることを確認する。


2. LDAPへメールユーザーを追加する

Section titled “2. LDAPへメールユーザーを追加する”

LDAPサーバーで、Alice用とBob用のパスワードハッシュを対話的に生成する。

Terminal window
slappasswd
slappasswd

1つ目をAlice、2つ目をBobのuserPasswordへ設定する。

mail-accounts.ldif
dn: cn=mailusers,ou=groups,dc=example,dc=com
objectClass: posixGroup
cn: mailusers
gidNumber: 20000
dn: uid=alice,ou=people,dc=example,dc=com
objectClass: inetOrgPerson
objectClass: posixAccount
uid: alice
cn: Alice Mail User
sn: User
uidNumber: 20001
gidNumber: 20000
homeDirectory: /var/vmail/alice
userPassword: {SSHA}Aliceのハッシュ
dn: uid=bob,ou=people,dc=example,dc=com
objectClass: inetOrgPerson
objectClass: posixAccount
uid: bob
cn: Bob Mail User
sn: User
uidNumber: 20002
gidNumber: 20000
homeDirectory: /var/vmail/bob
userPassword: {SSHA}Bobのハッシュ

uidNumberとgidNumberは、Dovecotがメールボックスへアクセスするときの実効UID・GIDになる。既存のローカルユーザーやLDAPユーザーと重複しない値を使用する。

LDAPへ追加する。

Terminal window
ldapadd \
-x \
-D "cn=admin,dc=example,dc=com" \
-W \
-f mail-accounts.ldif
Terminal window
sudo slapcat

uid=alice、uid=bob、各ユーザーのuidNumber、gidNumber、homeDirectoryが表示されることを確認する。


3. メールボックスのホームを作成する

Section titled “3. メールボックスのホームを作成する”

メールサーバーで作成する。

Terminal window
sudo install -d -o root -g root -m 755 /var/vmail
sudo install -d -o root -g root -m 700 \
/var/vmail/alice /var/vmail/bob
sudo chown 20001:20000 /var/vmail/alice
sudo chown 20002:20000 /var/vmail/bob

名前ではなく数値の所有者を確認する。

Terminal window
ls -ldn /var/vmail/alice /var/vmail/bob

Aliceが20001:20000、Bobが20002:20000であることを確認する。Maildir自体は、Dovecotでユーザー検索を確認した後に作成する。


4. メールサーバー証明書を配備する

Section titled “4. メールサーバー証明書を配備する”

mail.example.com用のfullchain.pemとprivkey.pemをメールサーバーへ置き、次の権限で配備する。

Terminal window
sudo install -d -o root -g root -m 700 \
/etc/postfix/tls/mail.example.com \
/etc/dovecot/tls/mail.example.com
sudo install -o root -g root -m 644 fullchain.pem \
/etc/postfix/tls/mail.example.com/fullchain.pem
sudo install -o root -g root -m 600 privkey.pem \
/etc/postfix/tls/mail.example.com/privkey.pem
sudo install -o root -g root -m 644 fullchain.pem \
/etc/dovecot/tls/mail.example.com/fullchain.pem
sudo install -o root -g root -m 600 privkey.pem \
/etc/dovecot/tls/mail.example.com/privkey.pem
Terminal window
openssl x509 -in fullchain.pem -noout -subject -issuer -dates \
-ext subjectAltName
openssl x509 -in fullchain.pem -pubkey -noout | sha256sum
openssl pkey -in privkey.pem -pubout | sha256sum

SANにDNS:mail.example.comがあり、2つのSHA-256値が一致することを確認する。


Terminal window
sudoedit /etc/postfix/main.cf

既存内容を次の設定へ置き換える。

/etc/postfix/main.cf
compatibility_level = 3.10
myhostname = mail.example.com
mydomain = example.com
myorigin = $mydomain
mydestination = $myhostname, localhost.$mydomain, localhost, $mydomain
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
local_recipient_maps = $alias_maps, proxy:ldap:/etc/postfix/ldap-local-recipients.cf
inet_interfaces = all
inet_protocols = ipv4
mynetworks = 127.0.0.0/8
smtpd_relay_restrictions = permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination
mailbox_transport = lmtp:unix:private/dovecot-lmtp
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
smtpd_sasl_auth_enable = no
smtpd_tls_cert_file = /etc/postfix/tls/mail.example.com/fullchain.pem
smtpd_tls_key_file = /etc/postfix/tls/mail.example.com/privkey.pem
smtpd_tls_security_level = may
smtp_tls_security_level = may

local_recipient_mapsは、エイリアスまたはLDAPに存在するローカル受信者だけをTCP 25で受理する。LDAP mapが返したuidの値そのものは配送先として使わず、検索結果が存在することを確認する。

mailbox_transportは、Linux passwdデータベースにユーザーが存在しなくても、ローカル宛てメールをDovecot LMTPへ渡す。DovecotがLDAP userdbから実際のメールボックス所有者を取得する。

smtpd_sasl_auth_enable = noはTCP 25でSMTP AUTHを提供しない。TCP 587だけで有効にする。

IPv4とIPv6の両方を使用する場合は、次の2行へ変更する。

inet_protocols = all
mynetworks = 127.0.0.0/8, [::1]/128

このIPv6設定は任意である。


/etc/postfix/master.cfで既存のsubmission行が有効なら、その行と配下の-oを次の内容へ置き換える。有効な行がなければ末尾へ追加する。

Terminal window
sudoedit /etc/postfix/master.cf
/etc/postfix/master.cf
submission inet n - y - - smtpd
-o smtpd_tls_security_level=encrypt
-o smtpd_sasl_auth_enable=yes
-o smtpd_client_restrictions=permit_sasl_authenticated,reject

TCP 587ではSTARTTLSとSMTP AUTHの両方を必須にする。Postfixは認証要求をprivate/authソケットからDovecotへ渡し、DovecotのLDAP passdbが検証する。


Terminal window
sudoedit /etc/postfix/ldap-local-recipients.cf
/etc/postfix/ldap-local-recipients.cf
server_host = ldap://ldap.example.com:389
version = 3
search_base = ou=people,dc=example,dc=com
scope = sub
domain = example.com
query_filter = (&(objectClass=posixAccount)(uid=%u))
result_attribute = uid
bind = no
start_tls = no

domain = example.comは、このmapによる検索をexample.comの完全なメールアドレスに限定する。%uはalice@example.comのローカル部aliceへ展開され、LDAPフィルターの特殊文字はPostfixがエスケープする。

result_attribute = uidは、一致したエントリから返す値を明示する。local_recipient_mapsでは値の内容ではなく、結果が存在するかどうかを使用する。

Terminal window
sudoedit /etc/dovecot/ldap.conf.ext
/etc/dovecot/ldap.conf.ext
ldap_uris = ldap://ldap.example.com:389
ldap_version = 3
ldap_base = ou=people,dc=example,dc=com
ldap_scope = subtree
ldap_starttls = no
passdb ldap {
bind = yes
ldap_filter = (&(objectClass=posixAccount)(uid=%{user}))
fields {
user = %{ldap:uid}
}
}
userdb ldap {
ldap_connection_group = userdb
ldap_filter = (&(objectClass=posixAccount)(uid=%{user}))
fields {
uid = %{ldap:uidNumber}
gid = %{ldap:gidNumber}
home = %{ldap:homeDirectory}
}
}

bind = yesは、検索で見つけたユーザーDNと利用者が入力したパスワードで認証Bindを行う。userdbはLMTPとIMAPが必要とするUID、GID、homeを取得する。

ldap_connection_group = userdbは、認証Bindによって接続中のBind DNが切り替わるpassdbと、通常検索を行うuserdbでLDAP接続を分ける。

LDAPサーバー証明書を発行したCA証明書をldap-ca.crtとしてメールサーバーへ用意する。

Terminal window
sudo install -d -o root -g root -m 755 \
/etc/postfix/ldap-ca /etc/dovecot/ldap-ca
sudo install -o root -g root -m 644 ldap-ca.crt \
/etc/postfix/ldap-ca/root-ca.crt
sudo install -o root -g root -m 644 ldap-ca.crt \
/etc/dovecot/ldap-ca/root-ca.crt
Terminal window
sudoedit /etc/postfix/ldap-local-recipients.cf
/etc/postfix/ldap-local-recipients.cf
server_host = ldap://ldap.example.com:389
version = 3
search_base = ou=people,dc=example,dc=com
scope = sub
domain = example.com
query_filter = (&(objectClass=posixAccount)(uid=%u))
result_attribute = uid
bind = no
start_tls = yes
tls_ca_cert_file = /etc/postfix/ldap-ca/root-ca.crt
tls_require_cert = yes

start_tls = yesはLDAP接続をTLSへ切り替える。tls_require_cert = yesは、CAによる署名、有効期間、ldap.example.comとの名前一致を検証条件にする。

Terminal window
sudoedit /etc/dovecot/ldap.conf.ext
/etc/dovecot/ldap.conf.ext
ldap_uris = ldap://ldap.example.com:389
ldap_version = 3
ldap_base = ou=people,dc=example,dc=com
ldap_scope = subtree
ldap_starttls = yes
ssl_client_ca_file = /etc/dovecot/ldap-ca/root-ca.crt
ssl_client_require_valid_cert = yes
passdb ldap {
bind = yes
ldap_filter = (&(objectClass=posixAccount)(uid=%{user}))
fields {
user = %{ldap:uid}
}
}
userdb ldap {
ldap_connection_group = userdb
ldap_filter = (&(objectClass=posixAccount)(uid=%{user}))
fields {
uid = %{ldap:uidNumber}
gid = %{ldap:gidNumber}
home = %{ldap:homeDirectory}
}
}

ldap_starttls = yesはLDAP検索と認証BindをTLS内で行う。ssl_client_ca_fileとssl_client_require_valid_certは、DovecotがLDAPクライアントとしてサーバー証明書を検証する設定である。

Terminal window
sudo chown root:postfix /etc/postfix/ldap-local-recipients.cf
sudo chmod 640 /etc/postfix/ldap-local-recipients.cf
sudo chown root:root /etc/dovecot/ldap.conf.ext
sudo chmod 600 /etc/dovecot/ldap.conf.ext

既存設定を保存する。

Terminal window
sudo cp -a /etc/dovecot/dovecot.conf \
/etc/dovecot/dovecot.conf.original
sudoedit /etc/dovecot/dovecot.conf

既存内容を次の設定へ置き換える。

/etc/dovecot/dovecot.conf
dovecot_config_version = 2.4.0
dovecot_storage_version = 2.4.0
protocols {
imap = yes
lmtp = yes
}
listen = 0.0.0.0
mail_driver = maildir
mail_path = ~/Maildir
first_valid_uid = 20000
namespace inbox {
inbox = yes
}
auth_mechanisms = plain login
auth_allow_cleartext = no
auth_username_format = %{user | username}
!include /etc/dovecot/ldap.conf.ext
ssl = required
ssl_server_cert_file = /etc/dovecot/tls/mail.example.com/fullchain.pem
ssl_server_key_file = /etc/dovecot/tls/mail.example.com/privkey.pem
service imap-login {
inet_listener imap {
port = 143
}
inet_listener imaps {
port = 993
ssl = yes
}
}
service auth {
unix_listener /var/spool/postfix/private/auth {
user = postfix
group = postfix
mode = 0660
}
}
service lmtp {
unix_listener /var/spool/postfix/private/dovecot-lmtp {
user = postfix
group = postfix
mode = 0660
}
}
protocol lmtp {
postmaster_address = postmaster@example.com
}

auth_username_formatはalice@example.comをaliceへ変換し、LDAPのuidと対応させる。ドメイン部分は検索前に除かれるため、この構成は1つのメールドメインを扱う。

first_valid_uid = 20000は、LDAPのメールユーザーに割り当てたUIDより低いシステムアカウントをメール利用者として扱わないための下限である。

ssl = requiredとauth_allow_cleartext = noは、IMAPのPLAIN・LOGIN認証をTLSで保護する。これはldap_starttlsとは別の接続に対する設定である。

TLS 1.2以上を明示する場合は、任意で次を追加する。

ssl_min_protocol = TLSv1.2

9. 匿名検索できないLDAPへ接続する

Section titled “9. 匿名検索できないLDAPへ接続する”

LDAP ACLがou=people配下の匿名検索を許可しない場合は、検索専用のサービスDNを使用する。この設定は該当するACLでのみ必要である。

Dovecotのldap.conf.extで、ldap_baseの後に追加する。

ldap_auth_dn = uid=mail-reader,ou=services,dc=example,dc=com
ldap_auth_dn_password = ReaderPassword

Postfixのldap-local-recipients.cfでは次の3行へ変更する。

bind = yes
bind_dn = uid=mail-reader,ou=services,dc=example,dc=com
bind_pw = ReaderPassword

サービスDNには、uid、objectClass、uidNumber、gidNumber、homeDirectoryを検索・参照する権限を与える。利用者のuserPasswordを読み取る権限は与えない。利用者パスワードの検証は、DovecotがユーザーDNで行う認証Bindが担当する。


Terminal window
sudoedit /etc/aliases

既存のエイリアスを残し、postmasterをLDAPユーザーへ転送する。

/etc/aliases
postmaster: alice
Terminal window
sudo newaliases

TLSなし版では次を実行する。

Terminal window
ldapsearch \
-x \
-H ldap://ldap.example.com:389 \
-b "ou=people,dc=example,dc=com" \
'(&(objectClass=posixAccount)(uid=alice))' \
uid uidNumber gidNumber homeDirectory

StartTLS版ではCA証明書を指定し、StartTLSを必須にする。

Terminal window
LDAPTLS_CACERT=/etc/dovecot/ldap-ca/root-ca.crt \
ldapsearch \
-x \
-H ldap://ldap.example.com:389 \
-ZZ \
-b "ou=people,dc=example,dc=com" \
'(&(objectClass=posixAccount)(uid=alice))' \
uid uidNumber gidNumber homeDirectory

Aliceの属性が表示されることを確認する。StartTLS版で証明書チェーンまたはホスト名が不正な場合は、この段階で接続が失敗する。


12. PostfixとDovecotのLDAP lookupを確認する

Section titled “12. PostfixとDovecotのLDAP lookupを確認する”

PostfixのLDAP mapを直接検索する。

Terminal window
sudo postmap -q alice@example.com \
ldap:/etc/postfix/ldap-local-recipients.cf
sudo postmap -q unknown@example.com \
ldap:/etc/postfix/ldap-local-recipients.cf

1つ目はaliceを返し、2つ目は何も返さないことを確認する。

Dovecotの設定とユーザー情報を確認する。

Terminal window
sudo doveconf -n
sudo doveadm user alice
sudo doveadm user bob@example.com
sudo doveadm auth test alice@example.com

AliceはUID 20001、GID 20000、home /var/vmail/alice、BobはUID 20002、GID 20000、home /var/vmail/bobになることを確認する。doveadm auth testにはLDAPのAlice用パスワードを入力し、auth succeededになることを確認する。

Maildirを作成する。

Terminal window
sudo doveadm mailbox create -u alice INBOX
sudo doveadm mailbox create -u bob INBOX
sudo find /var/vmail -maxdepth 2 -type d -name Maildir -printf '%u:%g %p\n'

AliceとBobのホーム配下にMaildirが作成されることを確認する。


Terminal window
sudo postfix check
sudo doveconf -n

エラーがなければ再起動する。

Terminal window
sudo systemctl restart dovecot
sudo systemctl restart postfix
sudo systemctl is-active dovecot postfix
Terminal window
sudo ss -lntp | grep -E ':(25|143|587|993)\b'
sudo ls -l \
/var/spool/postfix/private/auth \
/var/spool/postfix/private/dovecot-lmtp

PostfixがTCP 25と587、DovecotがTCP 143と993で待ち受け、認証用とLMTP用のUNIXドメインソケットが存在することを確認する。


14. LDAPユーザーで送受信を確認する

Section titled “14. LDAPユーザーで送受信を確認する”

検証用クライアントから、AliceのLDAPパスワードでSMTP AUTHを行い、Bobへ送信する。

Terminal window
swaks \
--server mail.example.com:587 \
--tls \
--tls-verify \
--auth LOGIN \
--auth-user alice@example.com \
--auth-password 'AlicePassword' \
--from alice@example.com \
--to bob@example.com \
--header 'Subject: LDAP authentication test' \
--body 'submitted with LDAP authentication'

235 2.7.0 Authentication successfulと、メッセージをキューへ受け入れた250応答を確認する。

存在しないローカル受信者がSMTP対話中に拒否されることを確認する。

Terminal window
swaks \
--server mail.example.com:25 \
--from sender@example.net \
--to unknown@example.com \
--quit-after RCPT

User unknown in local recipient tableを含む550応答になることを確認する。

LMTP配送を確認する。

Terminal window
postqueue -p
sudo find /var/vmail/bob/Maildir/new \
-maxdepth 1 -type f -printf '%f\n'
sudo journalctl -u postfix -u dovecot --since '-5 minutes'

BobのMaildirへメールが作成され、Postfixログにprivate/dovecot-lmtpへの配送成功が表示されることを確認する。

IMAP STARTTLSへ接続する。

Terminal window
openssl s_client \
-starttls imap \
-connect mail.example.com:143 \
-servername mail.example.com \
-verify_hostname mail.example.com \
-verify_return_error \
-CAfile /etc/ssl/certs/ca-certificates.crt

証明書検証が成功した後、BobのLDAPパスワードでログインする。

a LOGIN bob@example.com BobPassword
b SELECT INBOX
c FETCH 1 BODY.PEEK[HEADER.FIELDS (FROM TO SUBJECT)]
d LOGOUT

a OKでログインし、送信した件名が表示されることを確認する。


  • PostfixのLDAP mapがAliceとBobだけをローカル受信者として検索できる。
  • 未登録のunknown@example.comをSMTPのRCPT段階で拒否する。
  • DovecotのpassdbがLDAP認証Bindでパスワードを検証する。
  • DovecotのuserdbがLDAPからUID、GID、homeを返す。
  • LDAP属性と/var/vmail配下の数値所有者が一致する。
  • SMTP AUTHとIMAPの両方で同じLDAPパスワードを使用できる。
  • Postfixがローカル宛てメールをDovecot LMTPへ渡す。
  • DovecotがBobのMaildirへメールを保存する。
  • StartTLS版ではPostfixとDovecotの両方がLDAPサーバー証明書を検証する。
  • TCP 587とIMAPの認証はメールサーバー用TLSで保護される。