そろそろLDAPにしてみないか?

第17回FDSとDovecot[設定編]

前回から続くFDSとDovecotを使ったPOP3/IMAP4サービスの構築。前回のDovecotインストールと基本的な設定に続いて、今回は実際にLDAPと連携するための設定について解説します。

パスワード検索と認証バインド

とりあえず前回の設定でPOP3/IMAP4サービスが使用できるようになったわけですが、DovecotからLDAPサーバを参照する場合には2種類の認証方式を選択することができ、それらはドキュメントの中でそれぞれ「パスワード検索⁠⁠、⁠認証バインド」として紹介されています。

先ほどの例では、dovecot-ldap.conf中にユーザ検索用のLDAPバインドDNやパスワードを定義していましたが、もうひとつの方式の場合、このような検索専用のDNを準備する必要がありません。これらの方式の違いはDovecotに限った話ではなく、それ以外の様々なソフトウェアにも当てはまることなので、良い機会なのでここで整理しておきましょう。

実際の挙動をLDAPサーバのログから追ってみます。以下はPOP3サーバにログイン、ログアウトした時のFDSのログです。わかりやすいよう各所にコメントを入れています。

リスト1 パスワード検索時のログ
# dovecotを起動すると、早速検索用のDNでバインドが行われ、以後の検索のため待機する
[14/Oct/2008:11:59:16 +0900] conn=26 fd=64 slot=64 connection from 127.0.0.1 to 127.0.0.1
[14/Oct/2008:11:59:16 +0900] conn=26 op=0 BIND dn="cn=Directory Manager" method=128 version=2
[14/Oct/2008:11:59:16 +0900] conn=26 op=0 RESULT err=0 tag=97 nentries=0 etime=0 dn="cn=directory manager"
# POP3セッションでユーザ名、パスワードが入力されたため、エントリが存在するか検索し、パスワードを照合
[14/Oct/2008:11:59:19 +0900] conn=26 op=1 SRCH base="ou=Mail,dc=bluecoara,dc=net" scope=2 filter="(mail=hnakamitsu@bluecoara.net)" attrs="userPassword"
[14/Oct/2008:11:59:19 +0900] conn=26 op=1 RESULT err=0 tag=101 nentries=1 etime=0
# メールボックスの存在するホームディレクトリ属性を取得
[14/Oct/2008:11:59:19 +0900] conn=26 op=2 SRCH base="ou=Mail,dc=bluecoara,dc=net" scope=2 filter="(mail=hnakamitsu@bluecoara.net)" attrs="mailMessageStore"
[14/Oct/2008:11:59:19 +0900] conn=26 op=2 RESULT err=0 tag=101 nentries=1 etime=0
# dovecotを終了すると検索用DNがアンバインドされる
[14/Oct/2008:11:59:21 +0900] conn=26 op=3 UNBIND
[14/Oct/2008:11:59:21 +0900] conn=26 op=3 fd=64 closed - U1
リスト2 認証バインド時のログ
# POP3セッションでユーザ名とパスワードが入力されたら、ユーザの有無を確認
[14/Oct/2008:11:58:53 +0900] conn=21 op=1 SRCH base="ou=Mail,dc=bluecoara,dc=net" scope=2 filter="(mail=hnakamitsu@bluecoara.net)" attrs=ALL
[14/Oct/2008:11:58:53 +0900] conn=21 op=1 RESULT err=0 tag=101 nentries=1 etime=0
# POP3セッション時のユーザ名、パスワードを使ってディレクトリサーバにバインドできるか確認
[14/Oct/2008:11:58:53 +0900] conn=21 op=2 BIND dn="uid=HNAKAMITSU,ou=Mail,dc=bluecoara,dc=net" method=128 version=2
[14/Oct/2008:11:58:53 +0900] conn=21 op=2 RESULT err=0 tag=97 nentries=0 etime=0 dn="uid=hnakamitsu,ou=mail,dc=bluecoara,dc=net"
[14/Oct/2008:11:58:53 +0900] conn=21 op=3 BIND dn="" method=128 version=2
[14/Oct/2008:11:58:53 +0900] conn=21 op=3 RESULT err=0 tag=97 nentries=0 etime=0 dn=""
# メールボックスの存在するホームディレクトリ属性を取得
[14/Oct/2008:11:58:53 +0900] conn=21 op=4 SRCH base="ou=Mail,dc=bluecoara,dc=net" scope=2 filter="(mail=hnakamitsu@bluecoara.net)" attrs="mailMessageStore"
[14/Oct/2008:11:58:53 +0900] conn=21 op=4 RESULT err=0 tag=101 nentries=1 etime=0
[14/Oct/2008:11:58:56 +0900] conn=21 op=6 UNBIND
[14/Oct/2008:11:58:56 +0900] conn=21 op=6 fd=64 closed - U1

チャレンジ・レスポンス方式認証とLDAP

LDAPを用いる場合に2つの認証方式があることをお話ししましたが、これはLDAPサーバの負荷だけではなくPOP3/IMAP4認証方式にも大きく影響します。

たとえばサーバ側でAPOPを実装する場合、その原理上POP3デーモンは認証の前にあらかじめユーザの平文パスワードを認識しておく必要があります。話が少し脱線してしまいますが、DIGEST-MD5と異なりAPOPは非常にシンプルなので、この機会に解説しておきます。

※ 実際にはAPOPには2007年に弱点も見つかっていますので、今となってはそれほど使用される機会があるとは思いませんが、チャレンジ・レスポンス方式を説明する上でAPOPは絶好の材料なのです。
参考:APOP(エーポップ)方式におけるセキュリティ上の弱点(脆弱性)の注意喚起について

さて、次のtelnetセッションではAPOP認証を行っています。

図1 APOP認証を行うようす
% telnet localhost 110 
Escape character is '^]'. 
+OK Dovecot ready. <d43.e.48f98c19.Lqw3XswPopRACVhKEheing==@cos5a>
APOP hnakamitsu@bluecoara.net a12145991e03d06a94c54f94e2e60536   ←─サーバに送る文字列 
+OK Logged in. 

ここで、POP3サーバに対して

APOP hnakamitsu@bluecoara.net a12145991e03d06a94c54f94e2e60536 

という文字列を送信しています。フォーマットは見てわかるとおり、

APOP ユーザ名 ハッシュ値

です。3番目のハッシュ値は接続の度にサーバから発行されるユニークなチャレンジ、つまり

<d43.e.48f98c19.Lqw3XswPopRACVhKEheing==@cos5a>

を元にした値であるため、サーバに送信するハッシュ値も必然的に接続の度に異なることになります。これによってネットワーク上の盗聴が防止できていたわけです。では具体的に、このハッシュ値はどのようにして計算されるかというと、シェル上から次のようにして算出することができます。

% printf '<d43.e.48f98c19.Lqw3XswPopRACVhKEheing==@cos5a> hnakamitsu' | md5sum

ごらんのように、APOP認証で送信されるハッシュ値は

サーバからのチャレンジと平文パスワードを連結した文字列のMD5ハッシュ値

となります。メールクライアントがこのハッシュ値をサーバに送信し、サーバ側で結果が正しいかどうかを判断するためには、サーバ側でも

クライアントに送ったチャレンジと平文パスワードを連結した文字列のMD5ハッシュ値

を得る必要があり、この計算のためにサーバ側で平文、または復号可能なパスワードが必要になるのです。

しかし前述の認証バインド方式では実際の認証をLDAPサーバに委任するため、POP3デーモンが事前に平文パスワードを得ることができません。CRAM-MD5やDIGEST-MD5でも同様で、チャレンジ・レスポンス認証のためにはサーバ側で平文パスワードや中間値が事前に必要ですので、認証バインド方式ではこれらに対応することができないのです。一方、パスワード検索方式の場合は、Dovecot自身が認証をコントロールしますので、閲覧用のDNでユーザを検索することにより、平文パスワードを取得することができますね。

このように考えていくと、

  • ユーザにはAPOP/CRAM-MD5/DIGEST-MD5などのチャレンジ・レスポンス認証を使用させたい
  • セキュリティ上、dovecot-ldap.conf中に閲覧用のDNとパスワードを記述したくない
  • セキュリティ上、LDAPサーバに平文パスワードを登録したくない

のような矛盾が発生してしまい、よく議論の対象となります。

技術的にはSASLを使用し、DIGEST-MD5やCRAM-MD5認証をそのままLDAPサーバ側に委任することで、設定ファイルにはパスワードを記述することなくダイジェスト認証を使用できるでしょうが、それでもLDAPーサーバには平文パスワードが必要ですし、そもそもDovecotはそのような作りになっていません。

したがって考え方としては、

  • 設定を簡単にすませたいのであれば認証バインド
  • 少しでもLDAPサーバのパフォーマンスを向上させたい場合やチャレンジ・レスポンス認証を使いたい場合はパスワード検索

という形で覚えておくと良いのではないでしょうか。もう少し内容を詳しく知りたい方はLDAP - Dovecot Wikiが参考になります。

APOP/CRAM-MD5/DIGEST-MD5を試す

脱線ついでに、よくFAQとなりがちなチャレンジ・レスポンス方式ですが、Dovecotでは以下のような形で簡単に実現することができます。繰り返しになりますが、LDAP認証方式はパスワード検索に設定しておき、LDAPサーバには平文パスワードを格納しておく必要があります。

リスト3 /etc/dovecot.conf
auth default {
  mechanisms = plain apop cram-md5 digest-md5
  ...
}

ただし、読者の皆さんの多くがすでにご存じのように、これらの認証方式を用いることで、ネットワーク上の盗聴により平文パスワードが漏洩する可能性はゼロに近くになりますが、メール自体が暗号化されるわけではありませんし、メーラによって対応状況が変わってきます。そのため近年では平文認証+SSL/TLSという組み合わせでパスワード盗聴に備えるのが一般的となっています。SSL/TLS設定による欠点があるとすれば、

  • 通信全体が暗号化されるため、サーバ、クライアント側の負荷につながる
  • 証明書の管理コスト増大

などが考えられますが、サーバの能力も日々向上していることですし、ぜひSSL/TLSも検討してみてください。

まとめ

最初のFDS紹介からずいぶん時間が経ってしまいましたが、これで基本的なメールサーバがやっとできあがりました。Dovecotにはさまざま機能が備わっているため、LDAP以外に着目してもいろいろと勉強になることがあると思います。

メールサーバの大枠が完成したら、次は各ユーザ用のポータルサイトを作成し、ApacheのLDAP認証モジュールを使ってアクセスさせる、Perl/PHPのLDAP関数を使って、利用者のパスワードや転送アドレスなどをWeb経由で変更させる、spamフィルタのルールをLDAPサーバに保存し、各ソフトウェアから参照させる、など工夫次第でおもしろい使い方がたくさん出てきそうです!

それではまた次回。

おすすめ記事

記事・ニュース一覧