SMTP AUTHの設定

Postfix は、SMTP AUTH のための認証機構を外部プログラム (あるいはライブラリ) である SASL に頼っている。SASLSimple Authentication and Security Layer の略で、ざっくり言えば、認証手続き (例:PLAINやDIGEST-MD5) と認証データ参照メカニズム(例:LDAPやSQL) との間を抽象化して、簡単に使える認証フレームワークをアプリケーションに提供する仕組みだ。RFC4422 (RFC2222 を置き換えた) で標準化されている。

Postfix から使える SASL の実装としては、カーネギーメロン大学の Project Cyrus による実装で事実上のスタンダードである Cyrus SASL と、Dovecot に付属する SASL 機能がある。手元の Postfix がそれらをサポートしているかどうかは、下記のコマンドで分かる;

root# postconf -a

CentOS 5.4 標準パッケージの Postfix 2.3.3 では両方ともサポートされていた。優劣をつけるのは難しいので、当稿では Cyrus SASLDovecot SASL の双方について解説する。もちろん、認証のためのユーザ情報源には、ここまで使ってきたのと同じ 389 DS 上のデータベースが利用できる。

役に立つドキュメント: Postfix.org "Postfix SASL Howto"

Cyrus SASL を利用する場合

389 Directory Server に格納したアカウントデータを活用するには、Cyrus SASL パッケージに付属する saslauthd デーモンを利用する。このデーモンは、起動すると UNIXソケットを開く。Postfix はこのソケットを通じてパスワードの正否を問い合わせる。RedHat系 Cyrus SASL パッケージでのデフォルトのソケットファイルパス/var/run/saslauthd/mux となっている。

Cyrus SASL 及び saslauthd は、各種の認証手続きや認証データ参照機能をプラグインモジュールとしてロードするカタチを採っている。どんなものが利用できるかをまず調べておこう。サポートしている認証手続きモジュールをリストアップするには、

root# pluginviewer -s

認証データ参照メカニズムは、

root# saslauthd -v

で得られる。本稿に倣って設定をするには、`plain' 認証手続きプラグインと、`ldap' 認証データ参照プラグインがあれば充分だ。検証環境の Cyrus SASL2.1.22

Postfix.org の "Howtos and FAQs" からリンクの張られている "Postfix SMTP AUTH (and TLS) HOWTO" は参考になった。

Cyrus SASLの設定

/usr/lib(64)/sasl2/smtpd.conf ファイル

Postfix は、SMTP AUTH を有効にすると (デフォルトでは) `smtpd' というアプリケーション名を名乗って Cyrus SASL に問い合わせを行う。そうすると Cyrus SASLsmtpd.conf という名前のファイルを読んで基本動作を決定しようとする。そのファイルを探す場所はコンパイル時のオプションによっても異なるようだが、検証環境の Cyrus SASL では /usr/lib64/sasl2/ だった。32bit OS上なら /usr/lib/sasl2/ だろう。他に /usr/lib(64)/sasl/ にも smtpd.conf がインストールされている場合があるが、そちらをいくらいじっても効果はないので注意。ファイルパーミッションは root:root 640 または 644。

pwcheck_method: saslauthd
mech_list: plain

mech_list パラメータを書いておかないと、Cyrus SASL は利用可能なあらゆる認証手続き (DIGEST-MD5, CRAM-MD5 など) を有効にしてしまう。しかも実際のところ saslauthd 経由では PLAINLOGIN しか機能しない。よって、mech_list は必ず指定すべきだ。古びたメールクライアントしか使わない LOGIN も、どうしても必要だと分かっているのでなければ安易にリストに加えるべきでない。Project Cyrus は "Cyrus SASL for System Administrators" の中で、「LOGIN メカニズムは、今後とも解説を書く気はないし、サポート対象外。古いメールクライアントの面倒を見なければならない SMTP サーバのために Cyrus SASL ディストリビューションに含まれているにすぎない」と言っている。

saslauthd の代わりに、`ldapdb' というSASLプラグインを利用する手もあるのだが、ldapdb がきちんと機能するのは LDAPエントリの userPassword 値が平文で格納されている時だけ、という酷い制限がある。それに対して saslauthd なら、PLAIN もちろん、CRYPT, MD5, SMD5, SHA, SSHA もサポートされている。

/etc/saslauthd.conf ファイル

このファイルによって、saslauthd から LDAP サーバへの問い合わせ方法を定義する。ファイルパーミッションは root:root 640 または 644。参考になるドキュメントは少なく、Cyrus SASL のソースに付属するテキストドキュメント LDAP_SASLAUTHD がやっとだ。例を挙げ、その後ポイントだけ補足する。

サンプルファイル: saslauthd.conf

ldap_servers: ldap://localhost/
ldap_version: 3
ldap_auth_method: custom
#ldap_default_realm: hoge.cxm
ldap_bind_dn: cn=userretriever,dc=hoge,dc=cxm
ldap_password: password
ldap_scope: one
ldap_deref: never
ldap_search_base: ou=People,dc=hoge,dc=cxm
ldap_filter: (&(objectclass=mailRecipient)(mail=%U@%d))
ldap_servers:
ポートも指定する必要があるなら ldap://host:1389/ のように指定。スペース区切りで複数のサーバを並べておくことも可能。
ldap_auth_method:
LDAPサーバへ接続する際の認証方法。custom が最も速い。定義しない時のデフォルトは bind (通常のLDAP bind を行うモード) だが、その際の LDAPサーバのログを観察したところ、ldap_bind_dn に指定した DN でのバインドに加えて、クライアントが `auth plain' で入力したユーザでも再度バインドが行われるという無駄な挙動が見られる。
ldap_default_realm:
クライアントの申告してきたユーザ名が `user' のようにドメインを欠いていた時に補完する @domain.tld。これを設定しておくとドメインなしのユーザ名だけでも SMTP認証ができる。しかし、SASL への問い合わせ以前に Postfix 側で補完するようにしてある場合は要らないため、例ではコメントアウトしてある。Postfix 側の smtpd_sasl_local_domain を参照されたし。
ldap_bind_dn:, ldap_password:
当例では常に LDAP参照専用管理者エントリでバインドするので、その DN とパスワードを指定。
ldap_scope:
sub, one, base のいずれか。
ldap_deref:
search, find, always, never のいずれか。
ldap_filter:
LDAP検索フィルタ。例では、LDAP ユーザエントリをオブジェクトクラスと mail 属性との AND で検索している。組み込み変数が使用でき、%U は入力ユーザ名の `user' 部のみ、%d は `@domain.tld' 部のみ (入力ユーザ名がドメイン部を欠いていた時はデフォルトレルム) に置き換えられる。変数の説明はソース付属の LDAP_SASLAUTHD にある。
/etc/sysconfig/saslauthd ファイル

RedHat系のパッケージでは、saslauthd デーモン起動時のパラメータをこのファイルで環境変数として指定する。

SOCKETDIR=/var/run/saslauthd
MECH=ldap
FLAGS="-c -s 1024 -t 3600"

/etc/init.d/saslauthd 起動スクリプトによって、SOCKETDIR-m オプションの引数、MECH-a の引数として sasuauthd に渡される。その他のコマンドラインオプションを指定したい場合は、例のように FLAGS にそのまま書く。例では、認証キャッシュを有効にし (-c)、キャッシュサイズを 1024、キャッシュの有効期限を 3600 秒つまり 1時間に設定している。この他のオプションは saslauthdman で見られる。

設定が終わったら、saslauthd を起動し、問題がなければ自動起動に登録;

root# service saslauthd restart
root# chkconfig saslauthd on 

Postfix の設定

前の章で作成した main.cf に、下記のパラメータを書き加える。

smtpd_sasl_auth_enable = yes
#smtpd_sasl_type = cyrus
#smtpd_sasl_path = smtpd
smtpd_sasl_local_domain = hoge.cxm
broken_sasl_auth_clients = yes
smtpd_sasl_security_options = noanonymous
smtpd_recipient_restrictions = check_client_access cidr:/etc/postfix/authclients,
 permit_sasl_authenticated,
 reject_unauth_destination
smtpd_sasl_auth_enable
SMTP AUTH を有効にする。
smtpd_sasl_type
認証に使用する SASL の種別。CentOS 5.4 標準の Postfix では cyrus がデフォルト。参考のため載せただけなのでコメントアウトしてある。
smtpd_sasl_path
タイプが cyrus の場合は、アプリケーション名を指定する。これもデフォルトであり、参考のために書いあるだけ。PAM のサービス名のようなもので、Cyrus SASL ライブラリはこれを受け取ると /usr/lib64/sasl2/smtpd.conf を参照して動作方式を決める。
smtpd_sasl_local_domain
クライアントが ESMTP セッションでドメインなし (`user') で認証を求めてきた場合に補完するドメイン名。これを設定しておくと、SMTP AUTH 時のユーザ名が `user@hoge.cxm' でも `user' だけでも認証できる。SASL側の saslauthd.confldap_default_realm を設定するのと似ているが、Postfix 側で先に補完するようにしておけば SASL へのクエリは必ずドメイン付きになるため、SASL の認証キャッシュを最大限に活かすことができる。Cyrus SASL では、ldap_default_realm で補完できたとしても、そもそものアプリケーションからのクエリのキーが `user' だった時と `user@hoge.cxm' だった時とは別物として扱われるからだ。
broken_sasl_auth_clients
SMTPサーバは、クライアントからの EHLO に対する回答の 1つとして、サポートしているログインメカニズムのリストを `250-AUTH type type ...' という文で返す。ところが世の中には `AUTH' とタイプリストとの間に `=' がないと解釈できないブロークンなメールクライアントが存在する。broken_sasl_auth_clients はその対策で、yes にしておくとログインメカニズムリスト文をイコールなしとイコールありの計 2回送出する。Postfix のマニュアルによると、迷惑クライアントは、Outlook Express 4~6、 Outlook ~2003、Exchenge 5.0 だそうだ。「正しい実装のメールクライアントに悪影響はない」とも書かれているので、有効にしておいたほうがいいだろう。
smtpd_sasl_security_options
SASL 認証に関する制限事項を設定する。少なくとも noanonymous (アノニマスログインの拒否) だけは書いておくべき。
smtpd_recipient_restrictions
RCPT TO コマンドを受け取った時点で検査/発動する、規制を定義する。値はカンマまたはスペース区切りのリストで、先に書いたものから順に評価され、条件にマッチした時点で評価が終わる。SMTP AUTH を機能させるためには、permit_sasl_authenticated を入れないと意味がない。また、Postfix は、reject, defer, defer_if_permit, reject_unauth_destination のいずれかが入っていないとメールを一切受け取ってくれない。reject_unauth_destination は、おおざっぱに言うと、RCPT TO のドメインが relay_domains で許可されているリレー先だった時と、同ドメインがこのメールサーバの最終配送先だった時 (つまり mydestination, virtual_mailbox_domains, inet_interfaces etc..に一致する時) にはリレーを許し、それ以外はお断りする。

最後の smtpd_recipient_restrictions で、リストの最初に `check_client_access TABLE_NAME ' を書いている。これは、応用例を示すために以下のような要件を課してみたからだ。

巷では、ローカルセグメントからは無条件でメールリレーを許すよう、smtpd_recipient_restrictions リストの最初には permit_mynetworks が書いてある解説をよく目にする。mynetworks パラメータはたいてい、サーバセグメントを含む下記のような定義だ;

mynetworks = 192.168.0.0/24, 127.0.0.0/8

このままで smtpd_recipient_restrictions リストに permit_mynetworks を書いたとすると、192.168.0.0/24 のセグメントにいるクライアントは全て、認証なしに外部へメールが送れるようになってしまう。mynetwork 自体を 127.0.0.0/8 だけに限定することも考えてみたが、mynetworks 値は、リレー制御でなく接続自体を受け入れるかどうかの制御のために、

smtpd_client_restrictions = permit_mynetworks, reject_unauth_destination

というふうにも使用されているため、絞り込むと問題が生じる。

そこで、自由なメールリレーを許可するクライアントアドレスだけを格納した別のルックアップテーブルを参照させることにした。それが /etc/postfix/authclients だ。内容は、

127.0.0.0/8    permit

ファイルを作ったら bdb ファイルに変換して、Postfix をリロード。

root# postmap /etc/postfix/authclients
root# service postfix reload

Dovecot SASL を利用する場合

Dovecot は、POP3/IMAP 認証用に設定された passdb の機能を、SASLプロトコルに準拠したインターフェイスとして他のアプリケーションにも提供することができる。DovecotPOP3IMAP サーバとしては使用したくない場合には、主設定ファイルprotocols ディレクティブを `protocols = none' に設定しておくことによって、DovecotSASL としてだけ機能させることが可能だ。

Dovecot SASL の設定

前章で作成した /etc/dovecot.confauth defult{} セクション内に下記のような socket listen{} 定義を加える。

auth default {
  mechanisms = plain
<-- 中略 --> 
  socket listen {
    client {
      path = /var/spool/postfix/private/auth
      mode = 0660
      user = postfix
      group = postfix
    }
  }
}

path は、作成する SASL UNIXソケットファイルのパス。Postfix サービスが chroot() した時でもアクセスできるよう、Postfix のスプールディレクトリ配下に作らせるのがいいようだ。それに続くディレクティブはソケットファイルのパーミッション。なお、client{} 定義は複数定義することができる。つまり、同時に複数のアプリケーションに SASL 認証ソケットを提供することも可能なわけだ。

Postfix の設定

main.cf に加える設定は Cyrus SASL の時とほぼ同じで、異なるのはハイライトした部分だけ。`smtpd_sasl_type=dovecot' の時に定義する smtpd_sasl_path は、Dovecot SASL ソケットファイルのパス。下の例では Postfix スプールディレクトリ基底からの相対位置となる。その他のディレクティブについては Cyrus SASL の時を参照していただきたい。

smtpd_sasl_auth_enable = yes
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
smtpd_sasl_local_domain = hoge.cxm
broken_sasl_auth_clients = yes
smtpd_sasl_security_options = noanonymous
smtpd_recipient_restrictions = check_client_access cidr:/etc/postfix/authclients,
 permit_sasl_authenticated,
 reject_unauth_destination

テスト

ローカル上や別のマシン上から、バーチャルメールアカウント (例えば penguin@hoge.cxm) でメール送信を試行してみる。テストコマンドは Qmail のページの「動作テストのためのコマンド」でいろいろと紹介している。デバグに一番役に立つのはやはり、telnet でポート 25 に接続するやり方だ。