LDAPデータベースの構築

移転しました

独自ドメインサイトへ移行しました。5秒後に

https://straypenguin.winfield-net.com/

へジャンプします。

バーチャルメールユーザのアカウント情報は、389 Directory Server の備える mailRecipient オブジェクトクラスを利用して作成/管理する。

※ LDAP の "ディレクトリ" という語彙はファイルシステムの "ディレクトリ" と区別しにくいため、当ドキュメントでは敢えて「データベース」と呼ぶことにする。

389 Directory Server のインストールと設定

389 Directory Server のインストール、デプロイ、設定を行う。別ページにまとめたので、389 Directory Server のページを参照して、「ディレクトリサーバのマルチインスタンス化」以外の全ての作業を完了させておいていただきたい。

LDAP Directory 基本情報
Suffix dc=hoge,dc=cxm
実際のデータ格納Directory ou=People,dc=hoge,dc=cxm
root DN cn=Directory Manager
メールアカウント情報読み取り専用DN cn=userretriever,dc=hoge,dc=cxm
メールアカウント情報編集用DN cn=usermanager,dc=hoge,dc=cxm
パスワード格納形式 SMD5

運用に使用する LDAP Directory ツリーは、左図の構造とする。

実際のバーチャルメールドメインユーザは 389 DS 作りつけの ou "People" の下で管理する (左図の uid=strayuid=penguin など)。PostfixDovecot, SASL からの問い合わせに使う LDAP参照専用管理ユーザ cn=userretriever と、メールユーザの登録や修正のできる管理ユーザ cn=usermanager は、 "dc=hoge,dc=cxm" 直下に置く。389 DS では、LDAPスーパーユーザ "cn=Directory Manager" はどの oudc にも属さない特殊な位置づけだ。

メールユーザの登録

エントリ属性の解説

mailRecipient オブジェクト (OID: 2.16.840.1.113730.3.2.3) の持つ属性のうち、下表のものを活用する。属性の味付けや使い方は PostfixDovecotLDAP参照定義でどうにでもなるのだが、一部を除き、なるべく mailRecipient そもそもの規格に逆らわない使い方をすることにする。Attribute, 型, その用途などは、以下のサイトでも調べることができる。

ユーザ属性一覧
[凡例]  
必須 列: ◎=属性規格上も運用上も必須, □=属性の規格上必須, ○=運用上必須, △=省略可能
列: IA5=文字列型, int=数値, OctStr=オクテット文字列, DirStr=LDAPディレクトリ文字列
Case 列: 検索時に大文字小文字の区別がされるか。「無視」の場合でもデータ登録時に大文字が登録できないわけではない
比較 列: 検索時のマッチ条件。完全=長さも等しくなければ一致しない, 数値=数値として比較, OctStr=オクテット文字列比較
多重 列: 同じ属性を別の値で複数回登録できるか
Attribute 説明 属性パターン 属性提供元
最上流クラス
必須 Case 比較 多重
uid OID: 0.9.2342.19200300.100.1.1
ユーザ名、つまりメールアドレスの @domain.tld より前の部分。
DirStr 無視 完全 不可 (core)
mail OID: 0.9.2342.19200300.100.1.3
正メールアドレス。ドメイン部も含めて stray@hoge.cxm のように登録。属性規格上は多重登録も可能だが、運用上おかしなことになるので複数登録は無しとする。
IA5 厳格 完全 (不可) (cosine)
userPassword OID: 2.5.4.35
Dovecot の POP3 認証と、Postfix の SMTP-AUTH に使うパスワード。
OctStr 厳格 OctStr 不可 (core)
mailMessageStore OID: 2.16.840.1.113730.3.1.19
メールボックスの所在。Postfix (virtual_mailbox_maps 機能を経由) でも Dovecot (auth_userdb) でも使用される。当例では、uid 属性と同一にする。当該ユーザのメールボックスパスは、Postfix, Dovecot の然るべき設定によって、最終的に /var/vmail/<domain>/<homeDirectory>/Maildir/ と解釈される。
IA5 厳格 完全 不可 mailRecipient
mailForwardingAddress OID: 2.16.840.1.113730.3.1.17
転送または BCC 先メールアドレス。この属性の値を転送先として扱うか BCC 先として扱うかは下記の mailDeliveryOption で決まる。転送の場合に限っては、この属性を別の値で複数回登録しておくことも可能で、そうすると、受信メールを複数のメールアドレスへ転送することができる。BCC の場合の複数登録は Postfix がサポートしておらず、メールヘッダが異常なものになり送信不能となる。注意して使えば多重転送も可能だが、Postfix のループ防止機構により以下の制限がある;
●転送先ユーザで更に Forward : 可能
●BCC先ユーザで更に Forward : 可能
●転送先ユーザで更に BCC : 不可能
●BCC先ユーザで更に BCC : 不可能
DirStr 無視 完全 mailRecipient
mailDeliveryOption OID: 2.16.840.1.113730.3.1.16
本来の属性設計とは少々違うが、当サイトでは mailForwardingAddress が転送先か BCC 先かの区別に使う。値は 3種類;
forward転送動作。正メールボックスには配送せず mailForwardingAddress にだけ配送する。
bccBCC動作。正メールボックスとともに mailForwardingAddress にも配送する。本来の属性設計にはこの使い方はない。
この属性が存在しないかそれ以外の値の時通常の配送mailForwardingAddress が登録してあったとしても、転送も BCC もしない。
DirStr 無視 完全 不可 mailRecipient
mailQuota OID: 2.16.840.1.113730.3.1.21
ユーザ固有のメールボックス容量制限値。当例では使用しないが、利用価値あり。
DirStr 無視 完全 不可 mailRecipient

ユーザの登録

いよいよ実際にバーチャルメールドメインユーザを登録する。ただし、PostfixDovecot の設定が完了するまでは、2~3 のテストユーザを登録するに留めておくのがいいだろう。

登録は Directory Server Gateway から行えばいいだろう。そのためには、DSGW の mailRecipient 対応化を済ませておかなければならない。他の方法としては、LDIF ファイルに書いておいてから Javaベースの 389 Management ConsoleImport Database する手もある。その際に使う LDIF の 1ユーザ分は、例えば下記のようになる。サンプルファイル: users.mail_hoge_cxm.ldif

dn: uid=stray,ou=People,dc=hoge,dc=cxm
objectClass: top
objectClass: mailrecipient
uid: stray
mail: stray@hoge.cxm
userPassword: straypwd
mailMessageStore: stray
登録の確認

ハッシュ格納されたパスワードも含めて登録内容を確認するには、コマンドラインのほうがいい。当ドキュメントでは、mozldap版の ldapsearch を使う (「mozldap版LDAPコマンドパスを PATH に追加」をまだやってなければやっておくこと)。

hoshu$ ldapsearch -D "cn=userretriever,dc=hoge,dc=cxm" -w PASSWORD \
  -b "ou=People,dc=hoge,dc=cxm" -s one 'objectClass=mailRecipient'

各ユーザのメールボックスについて

Postfix は、バーチャルメールユーザへの初めてのメールを配送する時に配送先ディレクトリが存在しないと、自動的に作成してくれる。また、Dovecot も、ディレクトリが存在しなければ、やはり適切なパーミッションで自動的に作ってくれる。そのため、各ユーザのメールボックスをわざわざ事前に作成しておく必要はない。メールユーザ "stray" を例に採って構造を示すと、下記のような構成になる。

/var/vmail/hoge.cxm/            [mailadmin:mailadmin 750]
             \_ stray/              [mailadmin:mailadmin 700]
                    \_ Maildir/     [mailadmin:mailadmin 700]
                            \_ new/ [mailadmin:mailadmin 700]
                               cur/ [mailadmin:mailadmin 700]
                               tmp/ [mailadmin:mailadmin 700]

ユーザ毎のメールボックスをどうしてもあらかじめ作っておきたい几帳面な人は、シェルスクリプト vmaildirmake を使っていただくといいだろう。基底ディレクトリや配送用 UNIXアカウントの名前は、スクリプトファイル冒頭の変数で適宜調整していただきたい。

エイリアスユーザの登録

何かの条件下で、バーチャルメールドメインの rootpostmaster つまり、root@hoge.cxmpostmaster@hoge.cxm へメールが届くケースがないともいえない。特に、メールトラブルなどの連絡先として postmaster を公表している場合だ。しかし、このメールサーバで複数のメールサブドメインを運営する場合、それぞれのバーチャルドメインの postmaster へメールが行くのは運用上煩雑だ。そこで、後述の Postfix 設定で、virtual_alias_maps 機能を利用して全てのバーチャルメールドメイン配下の特別なアカウントを実アカウントへ一旦エイリアスし、さらにマシンローカルの aliases ファイルで最終的なユーザなりメールアドレスなりへとエイリアスする。

そこで肝となるのが、そもそも Postfix は、アカウントデータベースに存在しないユーザへのメールは SMTPセッション段階で拒絶し、virtual_aliases を参照するまでに至らないという点だ。そのため、とにかく存在する ということを示すためだけに、それら特別なアカウントもダミー的に LDAP のユーザ階層に登録しておく必要がある。

ほとんどの場合、サンプルファイル aliasusers.mail_hoge_cxm.ldif に挙げたアカウント群で間に合うだろう。そのひとつ、postmaster の LDIF エントリはこんな塩梅だ;

dn: uid=postmaster,ou=People,dc=hoge,dc=cxm
objectClass: top
objectClass: mailrecipient
uid: postmaster
mail: postmaster@hoge.cxm
userPassword: ffffffffffffffffffffffffffffffff  <--パスワードはダミーで構わない
mailMessageStore: postmaster  <--使われないが、他のバーチャルユーザと同様にしておく

LDAP に登録する。今回はコマンドラインで投入する例を示す。/usr/lib(64)/mozldap/ にある mozldap版の ldapmodify を使うこと;

hoshu$ ldapmodify -a -D "cn=usermanager,dc=hoge,dc=cxm" -w PASSWORD \
  -f aliasusers.mail_hoge_cxm.ldif
Postfix と Dovecot のLDAPクライアント実装状況について

ネットワークパケットをスニフして分かったのだが、PostfixLDAPクライアント実装は非常に汚い。問い合わせの度に bind してくるのはまあいいとして、用事が終わっても unbind もせずにコネクションを放ったらかしにしてくれるのだ。しかも、複数の機能 (設定ディレクティブ) で LDAPを参照している場合 (本稿の実装例もそう)、ひとつの SMTPセッションで開始/放置される bind は 1本どころではない。bind 処理は LDAP サーバにとって軽い処理ではない。また、LDAP サーバアプリケーションによっては、bind セッションの数が飽和してしまう可能性もあるので、実装に際しては LDAPサーバのチューニングが必要になることがある。

一方の Dovecot は、オフィシャルマニュアルの質や LDAP参照定義の柔軟性では Postfix にかなわないものの、LDAPクライアントの実装は非常にシンプルで行儀正しい。DovecotPOP3 セッション毎ではなく デーモンの起動時bind を行い、LDAPとの接続に何か異常の生じない限りそれを再利用し続ける。unbind はデーモンの停止時に行われる。ただし、裏を返せば、LDAP 自体やその経路の異常には少々弱い面があり、bind セッションが不意におかしな切れ方をした場合には Dovecot デーモンを再起動しないと正常な問い合わせが成り立たないことがある。