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

第15回FDS+Postfixでメールサーバ管理

前回までの設定

前回から少々時間がたってしまいましたので、今までの設定内容をここで一旦まとめておきます。前回までに行った設定は次の通りです。

  • FDSのインストールと初期設定
  • メールユーザ用ディレクトリエントリの追加
  • Postfix側のvirtual_mailbox_maps設定
  • テストメールの配送

つまり、バーチャルドメインユーザ宛のメールを25/tcpで受信すれば、メールボックスの保存パスがLDAPサーバから取得され、適切な場所にメールが保存される状態になっています。念のため、具体的なディレクトリエントリや設定ファイル等に関しても、ここで整理しておきます。

リスト1 FDSのディレクトリエントリ
# メールユーザ用トップツリー
dn: ou=Mail,dc=bluecoara,dc=net
ou: Mail
description: Postfix/Dovecot
objectClass: top
objectClass: organizationalunit

# バーチャルドメインユーザ用エントリ
dn: uid=HNAKAMITSU,ou=Mail,dc=bluecoara,dc=net
objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: inetorgperson
objectClass: mailRecipient
mail: hnakamitsu@bluecoara.net
uid: HNAKAMITSU
givenName: Hideo
sn: NAKAMITSU
cn: Hideo NAKAMITSU
userPassword: {SSHA}tTyYPQIq9ZDzoCDnAiLZaXvs2zA3Cc0B
mailForwardingAddress: forward@example.com
mailMessageStore: /home/mail/bluecoara.net/hnakamitsu 
リスト2 /etc/postfix/main.cf
# Postfixで管理するバーチャルドメイン
# 宛先がこれ以外のドメイン名であれば、MX検索より外部に配送する。
virtual_mailbox_domains = bluecoara.net, example.co.jp
# LDAPからホームディレクトリを取得する際のベースディレクトリ
# セキュリティ上の理由から設定した方が良いが、今回は属性の値をそのまま使うため/と設定 
virtual_mailbox_base = /
# メールアドレスとメールボックスを対応させるためのLDAP設定ファイル
virtual_mailbox_maps = ldap:/etc/postfix/vmailbox.cf
# メールファイルを保存する場合の最小UID
virtual_minimum_uid = 5000
# メールファイルの所有者、グループ(5000という固定設定)
virtual_uid_maps = static:5000
virtual_gid_maps = static:5000

リスト3 /etc/postfix/vmailbox.cf

# LDAPサーバのアドレス
server_host = localhost
# 検索ベース
search_base = dc=bluecoara,dc=net
# 検索フィルタ(%sがメールアドレスに置き換わる)
query_filter = (mail=%s)
# 検索後に取得する属性
result_attribute = mailMessageStore
# 属性取得後に文字列の後ろに/Maildir/という文字を付加することでメールを 
# ホームディレクトリ/Maildir/以下に保存するようにする
result_filter = %s/Maildir/

転送設定

Mail属性として登録されているhnakamitsu@bluecoara.net宛のメールを受信した場合、そのメールをmailForwardingAddress属性であるforward@example.com 宛に転送するようにします。そのためにはvirtual(5)のvirtual_alias_mapsパラメータを使用します。

内容はシンプルで、⁠mail=メールアドレス)に合致するエントリが見つかった場合には、そのメールをmail属性とmailForwardingAddress属性両方に転送する設定となります。

リスト4  main.cfに設定する内容
# メール転送用
virtual_alias_maps = ldap:/etc/postfix/forward.cf
リスト5 /etc/postfix/forward.cf
server_host = localhost
search_base = dc=bluecoara,dc=net
query_filter = (mail=%s)
result_attribute = mail, mailForwardingAddress

設定が終わったら、忘れずにPostfixをリロードしてください。ログを見ながらテストメールを送信すると、メールボックスへの配送と共に、外部へメールが転送されていることが分かると思います。

バーチャルドメイン設定

ここで、前回設定し損なったvirtual_mailbox_domainsもLDAPに対応させておきます。現在バーチャルドメインの一覧はmain.cfにハードコーディングされていますので、ドメインの一覧を

dn: ou=Mail,dc=bluecoara,dc=net

の中に保存しておくことにします。ドメイン名を格納する属性名ですが、これまでに使っているスキーマ中にmailAccessDomainというちょうど良さそうな属性が用意されていますので、これを利用することにします。ユーザのエントリと同様、mailRecipientというオブジェクトクラスを定義する必要があるため注意してください。

リスト6 /etc/postfix/main.cfのvirtual_mailbox_domainsパラメータを修正
修正前
virtual_mailbox_domains = bluecoara.net, example.co.jp

修正後
virtual_mailbox_domains = ldap:/etc/postfix/domains.cf
リスト7 /etc/postfix/domains.cf
server_host = localhost
search_base = dc=bluecoara,dc=net
# 該当するドメイン名が見つかった場合は、バーチャルドメインとして扱う 
query_filter = (mailAccessDomain=%s)
# なんでも良いので、適当な値を返すようにする
result_attribute = ou
# パフォーマンスを考慮し、子ツリー以下は検索しない
scope = one

これにあわせて、LDAPエントリにバーチャルドメインを定義します。

リスト8 LDAPエントリの一部を修正
% ldapmodify -x -D "cn=Directory Manager" -w dssecret << EOF 
dn: ou=Mail,dc=bluecoara,dc=net
changetype: modify
add: objectClass
objectClass: mailRecipient
-
add: mailAccessDomain
mailAccessDomain: bluecoara.net
mailAccessDomain: example.co.jp
EOF

以上の設定を行うことにより、Postfixが25/tcpでメールを受信した際、その宛先ドメインがdn: ou=Mail,dc=bluecoara,dc=netのmailAccessDomain属性に含まれていればバーチャルドメインとして扱い、それ以外であれば外部へリレーするようになります。

もし管理対象のメールサーバに複数のドメイン名がない場合や、バーチャルドメインの数が少ない場合には、ドメイン名をmain.cfに直接記述するようにしてください。LDAPサーバへの検索クエリが少なくなることで、パフォーマンスの向上につながります。

SMTP Authの設定

これまでの設定により、メールサーバは外部メールサーバからのメールを25/tcpで受信できるようになりましたが、Outlookなどのメールソフトから送信されてくるメールを正しく配送するためには送信用の設定が別に必要となります。

このための送信用ポートを587/tcpとし、不正中継対策のために送信の際にはユーザ名、パスワードを要求するようにします。

SendmailやPostfixなど、多くのMTAでSMTP Authの実際の認証をコントロールするのはcyrus-saslというライブラリで、このライブラリはいくつかのLDAP認証をサポートしています。

2003年の『Software Design』4~6月号ではsaslauthdという認証デーモンを紹介しましたが、最近のバージョンではldapdbというsaslauthdを必要としないLDAP認証手段が用意されています(最近のバージョンといっても、cyrus-saslの最新バージョンは2006年にリリースされて以来変更されていませんが……)。

saslauthdとldapdbの認証経路の違いは次の通りです。

saslauthdを使う場合の認証
saslauthdを使う場合の認証
ldapdbを使う場合の認証
ldapdbを使う場合の認証

このように、ldapdbを利用した方がシンプルなのですが、ldapdbを利用するためには、LDAPサーバ側にSASL認証、SASLプロキシ認証用の設定を行っておく必要があります。

SASLプロキシ認証では、たとえば

dn: uid=HNAKAMITSU,ou=Mail,dc=bluecoara,dc=net
userPassword: hnakamitsu

の認証を行う場合に、まずは

uid=proxyuser,ou=Mail,dc=bluecoara,dc=net

といった認証代行用のDNでディレクトリサーバへの接続を行い、このツリー中に設定されているsaslAuthzTo属性を参照し、最後に実ユーザの認証が行われます。しかし、残念ながらFDSでは、このSASLプロキシ認証がまだサポートされていません。将来的にはサポートされるかもしれませんが、2008年9月現在、Red Hat Directory Server Administrator's GuideのSASLの項には

SASL proxy authorization is not supported in Directory Server; therefore, the server will ignore any SASL authzid supplied by the client. 

とあります。したがって、FDS+SMTP Authという組み合わせの場合は残念ですが、従来のようにsaslauthdを使う必要があります……と言いたいところですが、それだと2003年の記事とあまり変わらず、おもしろくありませんので、今回は敢えて別の方法を取り入れてみます(笑⁠⁠。

機会があればいつかOpenLDAP+ldapdbという組み合わせも紹介するかもしれません。

giengerldapプラグインの活用

前述のように、FDSでldapdb方式が使用できないのはSASLプロキシ認証がサポートされていないためです。しかし、giengerldapというcyrus-sasl用プラグインを使えば、SASLプロキシ認証を使用せずに、なおかつSASL設定が行われていないLDAPサーバで認証を行うことができるようになります。

このプラグインはPascal Gienger氏によって作成、公開されており、saslauthdと違い、CRAM-MD5やDIGEST-MD5認証もサポートしています。是非本家ソースにも同じような仕組みを取り入れてほしいものです。

プラグインビルドのためには、cyrus-saslのソースファイルが必要になりますので、FTPサイトなどからCentOS用のcyrus-saslのSRPMを入手して、次のように下準備を行っておきます。

図1 cyrus-saslをビルドしておく
# rpm -i cyrus-sasl-2.1.22-4.src.rpm
# cd /usr/src/redhat/SPECS
# rpmbuild -bc cyrus-sasl.spec

以上により、/usr/src/redhat/BUILD/cyrus-sasl-2.1.22/build-shared以下に各種ライブラリなどが作成されますので、プラグインインストールの準備を行います。

図2 giengerldapプラグインの展開
% tar zxfv giengerldap_auxprop-1.2.1.tar.gz
% cd giengerldap-1.2.1

ソースファイルを展開したら、その中にあるcompileスクリプトを修正します。

リスト9 compileスクリプトの修正
CYRUSSASLPATH=/var/home/pascal/src/cyrus-sasl-2.1.22
       
CYRUSSASLPATH=/usr/src/redhat/BUILD/cyrus-sasl-2.1.22/build-shared 

次にcompileスクリプトを実行しますが、ヘッダファイルのパスが微妙に異なるためエラーになってしまいますので、CFLAGSを修正して正しいパスを指定します。CentOS以外で作業を行う場合には、エラー内容に従い、適切にパスの変更などを行ってください。

図3 giengerldapプラグインのコンパイルとインストール
% ./compile
(sasl.hなどのヘッダファイルが見つからないというエラーが表示されるので、手動でmake)
% make CFLAGS+="-I/usr/src/redhat/BUILD/cyrus-sasl-2.1.22/include -I/usr/src/redhat/BUILD/cyrus-sasl-2.1.22/plugins" 
# make install

以上の操作で、/usr/lib/sasl2以下にlibgiengerldap.*といったファイルが作成されます。必要であれば事前にRPMパッケージなどを作成してインストールするようにしましょう。

PostfixのSMTP Auth設定

まずは送信専用となる587/tcpを有効にします。そのために、master.cfのコメント行を外して次のようにsubmissionポートを有効にします。SSLは今回使用しないため、smtpd_enforce_tlsオプションは指定していませんが、SMTP Authを有効にするため、smtpd_sasl_auth_enable=yesを指定します。また、smtpd_client_restrictionsパラメータを設定することで、メールを送信する場合には宛先が内部であろうと外部であろうと、必ず認証を要求するようにしています。

リスト10 /etc/postfix/master.cfの一部
submission inet n       -       n       -       -       smtpd
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_client_restrictions=permit_sasl_authenticated,reject 

main.cfでは25/tcp、587/tcpにおけるアクセス制限を設定します。これ以外にも様々な設定が考えられるでしょうが、今回は簡単に済ませました。

リスト11 /etc/postfix/main.cfに設定する内容
# メールサーバが所属するネットワーク
mynetworks = 127.0.0.0/8, 10.0.100.0/24
smtpd_recipient_restrictions = 
  permit_mynetworks 
  permit_sasl_authenticated
  reject 

Cyrus-SASLの設定

Postfixは認証時にSASLライブラリを使用しますが、この時SASLライブラリは設定ファイルとなる/usr/lib/sasl2/smtpd.confを参照します。/usr/lib/sasl2というパスはcyrus-saslのコンパイル時にライブラリ中に埋め込まれます。確認するためには

% strings /usr/lib/libsasl2.so | less

などとして、SASL_CONF_PATHという文字列を追ってみると良いでしょう。また、smtpdというファイル名の一部はPostfixのようなアプリケーション側で定義することができます。具体的にはsmtpd_sasl_pathという設定がそれに該当しますが、通常このパラメータを変更する必要は無いでしょう。

では、giengerldap用の設定です。便宜上今回は、ディレクトリ検索用に、cn=Directory Managerというディレクトリ管理者のDNを用いていますが、実際にはセキュリティを高めるため、参照専用のDNなどを作成し、そのDNを指定するようにしてください。またファイルパーミッションを600などの適切な値に設定しておきます。

リスト12 /usr/lib/sasl2/smtpd.conf
# プラグインの定義
auxprop_plugin: giengerldap
# LDAPサーバの場所
gl_uri: ldap://localhost
# バインドDN、パスワード
gl_binddn: cn=Directory Manager
gl_bindpw: dssecret
# 検索ベース
gl_basedn: dc=bluecoara,dc=net
# 検索フィルタ。メールアドレスをSMTP Auth時のユーザ名とする
gl_search: (mail=%s)
# 認証方式の定義
mech_list: LOGIN PLAIN CRAM-MD5 DIGEST-MD5

次に、CRAM-MD5などのダイジェスト認証を行うためには、サーバ側に平文や中間値のパスワードが必要になりますので、ユーザエントリのuserPassword属性を

userPassword: hnakamitsu
userPassword: {CLEAR}hnakamitsu

のような平文状態に変更してください。システム全体で平文パスワードを保存したい場合には、管理コンソールよりConfigurationタブを選択し、左側メニューのDataツリーをクリック、右側に表示されるPasswordsメニューより、Password encryptionをCLEARになるよう設定してください。

以上でSMTPサーバの設定が完了しました!

まとめ

今回はLDAP認証のためにgiengerldapを紹介しましたが、オフィシャルプラグインでないと導入に不安を持つ方もいらっしゃるでしょうから、それ以外の認証方式を紹介しておきます。

表1 LDAPに関連するさまざまな認証方式
方式特徴必要な設定
saslauthd+ldapSASLライブラリはsaslauthdとプロセス間中心。saslauthdデーモンがLDAPサーバへの問い合わせを行う。仕組み上、CRAM-MD5などのダイジェスト認証は使用できない。saslauthdの設定と起動
saslauthd+pam+ldapSASLライブラリはsaslauthdとプロセス間中心。saslauthdデーモンはPAMライブラリと会話。PAMライブラリがLDAPサーバへの問い合わせを行う。仕組み上、CRAM-MD5などのダイジェスト認証は使用できない。saslauthdの設定と起動、OS内でのPAMの設定
ldapdbSASLライブラリが直接LDAPサーバへの問い合わせを行う。LDAPサーバ側に平文パスワードを登録することで、CRAM-MD5など使用可能。LDAPサーバ側でのSASL認証設定とSASLプロキシ設定、CRAM-MD5認証などを行うためにディレクトリ内には平文パスワードが必要
giengerldapSASLライブラリが直接LDAPサーバへの問い合わせを行う。LDAPサーバ側に平文パスワードを登録することで、CRAM-MD5など使用可能。CRAM-MD5認証などを行うためにディレクトリ内には平文パスワードが必要
authdaemondSASLライブラリはauthdaemondとプロセス間中心。authdaemondデーモンがLDAPサーバへの問い合わせを行う。仕組み上、CRAM-MD5などのダイジェスト認証は使用できない。courier-authlibの導入とauthdaemondの起動

次回はdovecotを用いてPOP3/IMAP4環境を構築します。

おすすめ記事

記事・ニュース一覧