Postfix の設定

LDAP連携に関係するファイル一覧

/etc/
   \_ aliases                   ローカルシステムのメールエイリアスファイル
      postfix/
          \_ main.cf            [root:root 644] 主設定ファイル
             ldapvirtual        [root:postfix 640] バーチャルメールユーザに関するLDAP参照定義ファイル
             ldapvirtualaliases [root:postfix 640] フォワードに関するLDAP参照定義ファイル
             ldapbcc            [root:postfix 640] オートBCCに関するLDAP参照定義ファイル
             virtualaliases     [root:root 644] postmaster など特別なバーチャルユーザを実ユーザへ振るための定義

これ以外にも関係するファイルが幾つかあるが、それらについては既に 「OSの環境整備」 の項で述べている。LDAP連携とは直接関係のない要調整システムファイルについては後で面倒をみる

main.cf - 主設定ファイル

Postfix の主設定ファイル。以下に LDAP連携に関係するパラメータに的を絞って説明する。より詳しい説明や他のパラメータについては、Postfix.org ホームページの Postfix Configuration Parameters を参照。混乱を避けるため、SMTP AUTH のためのパラメータは後述とする。

パラメータ名 当実装での設定値 説明
基本的なパラメータ
myhostname penguin.hoge.1 メールサーバとしてのフルホスト名。バーチャルメールドメインと区別するため必ずバーチャルメールドメインとは別のドメインにする。その重要性は「実装概要」でも述べた。特にこの値は、別パラメータの多くで参照される重要なもの。
mydomain hoge.1 同、ドメイン部のみ。
myorigin $myhostname ローカルで発生したメール及びローカルに配送するメールに @domain.tld が欠けていた時にデフォルトで付加するドメイン部。
syslog_facility mail LDAP連携とは直接関係はない。syslog にログを投げる際のファシリティ。Dovecot 1.0.7 やそれ以降ではファシリティが変更できるようになったため、Postfix 側はデフォルトのままでいい (「syslogの調整」も参照のこと)。
mydestination $myhostname, localhost.$mydomain, localhost ローカル配送すべきと認識する @domain.tld。ここにバーチャルメールドメインを絶対に含めてはいけない。
smtp_helo_name mail.hoge.cxm SMTPセッションで `helo' 及び `ehlo' への返答の際に名乗る名前。運用ポリシーやネットワークトポロジによっては実マシン名のほうが妥当な場合もある。
諸制限
forward_path /var/vmail/dot_forward_disabled .forward ファイルのパス。当ページの LDAP連携ではフォワードメカニズムも LDAPを使って実装するので、デフォルトの $home/.forward 等は有害。左記のように単一のファイルなお且つあり得ないファイル名にして実質無効化しておくのがよい。
remote_header_rewrite_domain   リモートクライアント (マシンローカルでない) からのメールで、メッセージヘッダに書かれたアドレスに @domain.tld が欠けていた時に補完する @ 以降。クライアントを正すべきであって、補完しないのが妥当だが、必要ならば hoge.cxm のほうを指定すべきだろう。デフォルトもヌルつまり補完は無効。
バーチャルメールドメイン
virtual_transport virtual virtual配送エージェントの定義 (デフォルト)。
virtual_mailbox_domains hoge.cxm virtual_mailbox機能で扱うメールドメイン。複数の場合はカンマかスペース区切りで連ねる。
virtual_mailbox_base /var/vmail 配送先ファイルシステムパスの基底。Postfix の安全機構のひとつで、ここに指定した以外のファイルシステムツリーにメールファイルをばらまくのを防ぐ。
virtual_mailbox_maps ldap:/etc/postfix/ldapvirtual バーチャルメール機能の根幹となるパラメータ。各バーチャルメールユーザと配送先メールボックスパスとの対応マップを定義する。左記は「LDAPテーブル形式のマップ定義を /etc/postfix... ファイルから読め」の意。
virtual_minimum_uid 500 virtual配送エージェントが受付を許可するユーザの UID の下限。一種のセキュリティ機構。
virtual_mailbox_limit 51200000 各アカウントのメールボックスサイズ制限。バイト単位。無制限なら 0 に。
virtual_uid_maps static:1025 配送実行時に使用する UNIX UID。常に mailadmin 権限で行うので mailadmin の UID を固定 (static:) で指定。
virtual_gid_maps static:1025 同、GID。
バーチャルエイリアス (フォワードと、特別なアカウントの実ユーザへのマッピング)
virtual_alias_maps ldap:/etc/postfix/ldapvirtualaliases,
hash:/etc/postfix/virtualaliases
ldapvirtualaliases ファイルでフォワードのLDAP参照定義、もう一方で postmaster など特別なバーチャルアカウントの実ユーザへのマッピングを定義する。パラメータに `virtual_' という名前が付いているが、参照は virtual_mailbox_domains のドメインに限定されるわけでなく、受信/送信にかかわらず全てのメールのエンベロープ To: に対して牽かれることに注意。
オートBCC機能
recipient_bcc_maps ldap:/etc/postfix/ldapbcc オートBCCの LDAP参照定義。virtual_mailbox_domains のドメインに限定されるわけでなく、受信/送信にかかわらず全てのメールのエンベロープ To: に対して牽かれることに注意。
エイリアス
alias_maps hash:/etc/aliases 実ユーザのメール転送定義。当実装では、前述の virtual_alias_mapsvirtualaliases ファイルで実ユーザへマッピングした特別なバーチャルアカウントも、ここで二次的に処理され、最終的な宛先アドレスへ振り向けられる。
alias_database hash:/etc/aliases newaliases または `sendmail -bi' コマンドで更新されるべきファイル。(デフォルト)
デフォルトメールボックスパス
home_mailbox Maildir/ デフォルトの配送先パス (各ユーザのホームからの相対)。最後のスラッシュが Maildir 形式であることを表す。このパラメータは local 配送エージェントだけのもので、バーチャルメール配送には利用されない。
配送並列度
local_desitination_concurrency_limit 2 並列処理できる 1ユーザあたりのローカル配送の数。
defualt_destination_concurrency_limit 20 ひとつのドメインに対して並列処理できる配送の数。smtp, virtual, lmtp, pipe配送エージェント共通の値。
virtual_destination_concurrency_limit 50 同上、ただし virtual配送エージェント固有の値。LDAP連携と直接の関わりはないが、その実装の仕組み上、配送には主に virtual が使われることになるので、メール流量によっては並列度を上げておいたほうがよい。デフォルトでは上記 default_destination... と同値。

検索テーブルファイル

ここからのものは、Postfixルックアップテーブル と呼ばれる類だ。当実装においては ldapテーブル と バークレイDB (bdb) の 2種類を使い分ける。

ldapテーブルのほうは、正確には LDAPテーブルの参照を定義する設定ファイル だ。かつて、LDAP参照定義は main.cf の中に直接書くしかなかったが、Postfix 2.1 以降では main.cf 内で参照先を ldap:/PATH/TO/FILE (例えば virtual_mailbox_maps ディレクティブで) のように指定することによって、定義内容をこのように別ファイルに置けるようになった。おかげで、bind 用パスワードを含むこれら重要なファイルをファイルパーミションで守ることができる。

ldapテーブルにおいては、アカウントデータ (つまり LDAP上のデータ) の変更はすぐさま Postfix に反映される。それに対して、Postfix の標準テーブルである bdb の場合、編集するのは 原稿 であり、データを反映させるには postmappostalias コマンドでバイナリファイルに変換してやる必要があり、更に `postfix reload' 等のコマンドで Postfix に再読込みさせなくてはならない。

ldapvirtual - バーチャルメールユーザのLDAP参照定義ファイル

virtual_mailbox_maps 機能が参照する。設定サンプル: ldapvirtual

server_host = localhost
server_port = 389
version = 3
bind = yes
bind_dn = cn=userretriever,dc=hoge,dc=cxm
bind_pw = password
domain = hoge.cxm
search_base = ou=People,dc=hoge,dc=cxm
scope = one
dereference = 0
query_filter = (&(objectClass=mailRecipient)(mail=%s))
result_attribute = mailMessageStore
expansion_limit = 1
result_format = %D/%s/Maildir/

オフィシャルドキュメントは `man 5 ldap_table' や Postfix.org の LDAP_TABLE(5) で読める。

server_host
LDAPサーバを別のマシンで動かしている場合はそれなりに。
version
LDAP サーバとの通信に使用する LDAPプロトコルバージョン。Postfix 2.3 のデフォルトは LDAPv2 だが、389 DS LDAPv3 をサポートしているので、時代遅れな v2 を使う理由はない。
bind, bind_dn, bind_pw
デフォルトでは、Postfix は問い合わせをアノニマスで行う。しかし、当実装の場合には常に問い合わせ専用 LDAPアカウント userretrieverbind して問い合わせを行う。LDAPサーバに多少の負荷を伴うが、セキュリティ上、このほうが好ましい。bind_dn には LDAPデータベースに用意しておいたユーザ情報読み取り専用ユーザエントリDNbind_pw にはそのパスワードを入れておく。
domain
これを定義しておくと、入力値のドメイン部全体がこのリストのいずれかに完全一致しなければ、はなから LDAP検索を実行しない。また、入力値が `user' だけだったり `@domain.tld' だけだっ時にも問い合わせは行われない。おかけで無効な入力に対して無駄な LDAP参照を発生させずにすむ。複数のバーチャルドメインやサブドメインを管理している場合にはカンマかスペースで区切って `hoge.cxm, so.hoge.cxm' のように書くことで対応でき、`hash:/file/name ' のようにルックアップテーブルを使用することも可能。
search_base
アカウントエントリを検索する Directory ツリー。なお、当ページでは使用していないが、組み込み変数 %x を使ってドメイン/サブドメイン毎に参照ツリーを変えることも可能だ。
scope
ldapsearch-s オプションにあたるもの。検索の負荷を軽減するとともに意図しないヒットを防止するため、特に理由のない限り「その階層だけ」を意味する one にする。ou=People の下にさらに ou を作っていてそれら全階層からユーザを検索させたい場合は sub に。
query_filter
このファイル最大のポイント。もの凄い柔軟性があってどうにでもなるため Postfix-LDAP連携の具体的で有用な記事が少なく、このページを書く要因となったのがこれだ。値は LDAPクエリフィルタ規格 に基づくフォーマットで書く。例は、「オブジェクトクラスがmailRecipient」且つ「mail属性が入力文字列全体と等しい」エントリを検索せよ、というフィルタだ。組み込み変数 %s で表せる「入力文字列全体」とは、Postfixvirtual_mailbox_maps 機能に対して渡してくるキーのことで、具体的にはメールアドレス (xxx@domain.tld) になる。この他の組み込み変数には %u, %d などもあり、%u@domain.tld より前つまり通常ならアカウント名、%d@ より後ろとなる。もっと複雑なクエリを組むなら %1 から %9 までのポジション変数も用意されている。ポジション変数はドメインパートだけを対象にして後方からマッチし、例えば入力が penguin@work.mail.hoge.cxm だったとしたら、%1=cmx, %2=hoge, %3=mail, %4=work という代入が行われる。余計な Directory ツリーを探し回らせず検索を効率化するために、フィルタはできるだけ限定的にするべき。(objectClass=mailRecipient)AND 条件の筆頭にしてあるのはそのためだ。
result_attribute
取得する属性。カンマかスペース区切りで並べれば複数の属性を指定することもできるが、virtual_mailbox_maps においては mailMessageStore だけ。複数並べるとどうなるかは下記 expansion_limit の解説を参照。
expansion_limit
LDAP から取得される値の数を制限する。デフォルトでは 0 つまり規制なし。PostfixLDAPルックアップでは、複数の値が得られた場合、その各々が下記 result_format の処理を受けた後、それらがカンマで連結されて最終的なひとつの文字列が形成される。例えば、わざと `result_attribute = mailMessageStore mail' を設定しておいて stray というユーザへメールを配送させると、メールは /var/vmail/hoge.cxm/stray/Maildir/,stray@hoge.cxm/Maildir/ というトンデモないパスに配送される。またあるいは、LDAP上の stray エントリに余分な mailMessageStore 属性を `stray2' という値で追加登録しておくと、/var/vmail/hoge.cxm/stray/Maildir/,stray2/Maildir/ にメールが配送されてしまう。そこで、`expansion_limit = 1' を設定しておけば、2つ以上の値が LDAP から得られた時にはルックアップエラーとなり、その結果、送信を行おうとしたメールクライアントに送信失敗コードが返ることになる。
result_format
Postfix に実際に戻り値を返す前に値を整形する。このディレクティブでも幾つかの組み込み変数が使用でき、 %sresult_attribute で得られた値。%D は、LDAP から得られた値のではなく入力値のドメイン部。そもそもヒットするエントリがなかった時には、`/Maildir/' も何も返らず、「そういうユーザはいない」という判断となる。バーチャルメールボックスへの配送は local 配送エージェントでなく virtual 配送エージェントによって行われるため、main.cfhome_mailbox で指定したサフィックスは付加されないということに注意。

このファイルには読み取り専用ユーザのパスワードが書かれているので、一般の UNIXユーザに読めないようパーミッションは必ず root:postfix の 640 にしておかなければならない。

ldapvirtualaliases - フォワードに関するLDAP参照定義ファイル

virtual_alias_maps 機能が参照する。設定サンプル: ldapvirtualaliases

server_host = localhost
server_port = 389
version = 3
bind = yes
bind_dn = cn=userretriever,dc==hoge,dc=cxm
bind_pw = password
domain = hoge.cxm
search_base = ou=People,dc=hoge,dc=cxm
scope = one
dereference = 0
query_filter = (&(objectClass=mailRecipient)(mail=%s)(mailDeliveryOption=forward))
result_attribute = mailForwardingAddress

ほとんどのディレクティブは前述の ldapvirtual ファイルと同様。特記すべきディレクティブについてだけ述べる。

domain
この参照定義の対象とする入力ドメイン (メールアドレスの @ より後ろ) を限定する。注意すべきは、virtual_alias_maps 機能が、送信/受信にかかわらず全てのメールのエンベロープ To: に対して照会されるという点だ。例えば、当サーバで管理するドメインのユーザから mike@yahoo.com へのメール送信要求を受け付けたとすると、mike@yahoo.com に対してもこのマップの参照が試みられる。それを制限するのが domain ディレクティブだ。まずひとつに、無駄な LDAP検索を抑制し、サーバリソースが節約できる。そしてもうひとつ、仮に、ドメインを制限をせずに query_filter(uid=%u) にしてあったとすると、LDAP検索時に入力のドメインパートは無視されるので、我が hoge.cxm にも mike が存在した場合、そのメールは mike@yahoo.com に送信されず、cn=mike,ou=People,dc=hoge,dc=cxmmailForwardingAddress 属性に登録してあるアドレスへ転送されてしまうのだ。複数のバーチャルドメインを対象にするにはカンマかスペースで区切って並べておく。
query_filter
「オブジェクトクラスがmailRecipient」でなお且つ
mail属性値が入力文字列とイコール」でなお且つ
mailDeliveryOption属性値がforwardである」エントリを探せ、の意。

!! フォワードの場合には mailForwardingAddress は複数登録可能なので、`expantionlimit=1' は設定してはいけない。

このファイルには読み取り専用ユーザのパスワードが書かれているので、一般の UNIXユーザに読めないよう、パーミッションは必ず root:postfix の 640 にしておく。

ldapbcc - BCC先のLDAP参照定義ファイル

recipient_bcc_maps 機能が参照する。サンプルファイル: ldapbcc

server_host = localhost
server_port = 389
version = 3
bind = yes
bind_dn = cn=userretriever,dc=hoge,dc=cxm
bind_pw = password
domain = hoge.cxm
search_base = ou=People,dc=hoge,dc=cxm
scope = one
dereference = 0
query_filter = (&(objectClass=mailRecipient)(mail=%s)(mailDeliveryOption=bcc))
expansion_limit = 1
result_attribute = mailForwardingAddress 

ほとんどの要素は ldapvirtualaliases 及び ldapvirtual と同様。

domain
重要なのでもう一度述べる。このディレクティブは、参照定義の対象とする入力ドメイン (メールアドレスの @ より後ろ) を限定する。注意すべきは、recipient_bcc_maps 機能が、送信/受信にかかわらず全てのメールのエンベロープ To: に対して照会されるという点だ。例えば、当サーバで管理するドメインのユーザから mike@yahoo.com へのメール送信を受け付けたとすると、mike@yahoo.com に対してもこのマップの参照が試みられる。それを制限するのが domain ディレクティブだ。まずひとつに、無駄な LDAP検索を抑制し、サーバリソースが節約できる。そしてもうひとつ、仮に、ドメインを制限をせずに query_filter(uid=%u) にしてあったとすると、LDAP検索時に入力のドメインパートは無視されるので、我が hoge.cxm にも mike が存在した場合、そのメールは mike@yahoo.com に送信されずに、cn=mike,ou=People,dc=hoge,dc=cxmmailForwardingAddress 属性に登録してあるアドレスへ転送されてしまうのだ。複数のバーチャルドメインを対象にするにはカンマかスペースで区切って並べておく。
query_filter
「オブジェクトクラスがmailRecipient」でなお且つ
mail属性値が入力文字列とイコール」でなお且つ
mailDeliveryOption属性値がbccである」エントリを探せ、の意。
expansion_limit
詳しい説明は ldapvirtual を参照していただくことにするが、ldapbcc では実装上の意味合いが少し異なる。属性の解説で述べたように、Postfixrecipient_bcc_maps 機能は複数のBCC先への転送をサポートしてないため、もしも mailDeliveryOption属性値が `bcc' でなお且つ mailForwardingAddress が複数登録してあるユーザがいると、かなり気持ち悪いエラーが起きる。そこで、こうして属性数規制を掛けておけば、複数の mailForwardingAddress 値が返ってきた時点できちんとエラーにすることができる。このエラーにヒットすると、主宛先へはメールが配送されるが、いずれの mailForwardingAddress にもメールは送信されない。ただし、その際、Postfix デーモンからのエラーメールが出されず、BCCエラーの発生を知るにはシステムのメールログを見るしかないのが欠点だ。

このファイルには読み取り専用ユーザのパスワードが書かれているので、誰彼なしに読めてしまうことを防ぐために、パーミッションは必ず root:postfix の 640 にしておく。

virtualaliases - 特別なバーチャルアカウントからローカルユーザへのマッピングテーブル

virtual_alias_maps 機能が参照するアドレスリライティングテーブル。サンプルファイル: virtualaliases

mailer-daemon@hoge.cxm  postmaster@localhost
postmaster@hoge.cxm     postmaster@localhost
root@hoge.cxm           root@localhost

こうしてバーチャルメールドメインの postmasterroot などをローカルユーザへとマッピングすることによって、次項の /etc/aliases ファイルでそれらローカルユーザの一括マッピングができる。バーチャルドメインがひとつだけでない場合は、すべてのバーチャルドメインの postmasterroot なども明示的に書いておく。

作成後、bdbファイルに変換する。書き換えるたびに行う必要がある。

root# postmap /etc/postfix/virtualaliases

aliases - ローカルユーザからローカルまたは外部へのマッピングテーブル

alias_maps 機能が参照する。ローカルユーザとしての rootpostmaster へのメールが hoshu へ回されるように設定する。

mailer-daemon:  postmaster <--デフォルトでこうなっているはず
postmaster:     root       <--デフォルトでこうなっているはず
 <中略>
root:           hoshu      <--ファイル末尾に付け加える

右辺には、myaddress@provider.co.jp のような外部アドレスや、なんとなれば hoshu@hoge.cxm のようにバーチャルメールドメインのメールアドレスを書くこともできる (ただしループには注意)。上書き保存後、bdb ファイルへと変換する。書き換えるたびに行う必要がある。

root# postalias /etc/alises

※ 変換は newaliases コマンドでも行えるが、RedHat系では alternatives (デフォルトプログラム変更フレームワーク) による複雑なシンボリックリンクを辿って最終的には結局 postalias と同義のコールが行われる仕組みになっているので、postalias を直接使ったほうが確実といえる。

Maildirへの対応

システムの標準メールボックス形式を Maildir 方式にするため、以下のファイルの当該箇所を修正する。LDAP連携とは全く関係ない基本中の基本だが、こんなところで座礁してもらいたくないので書き添えておく。

/etc/profile

#MAIL="/var/spool/mail/$USER" <--コメントアウト
MAIL="~/Maildir"
MAILDIR=$MAIL
 <中略>
export PATH USER LOGNAME MAIL MAILDIR HOSTNAME HISTSIZE INPUTRC <--変数追加

/etc/login.defs

今どきほとんど使われることのないファイルだが、念のためこちらも直しておく。

MAIL_DIR    Maildir

Mutt ローカルメールリーダーの整備

テキスト版メールリーダー MuttMaildir環境向けに設定しておくと、これから何度もすることになるであろう確認作業で非常に役に立つ。Qmail のページの「Muttのインストール」を参照して設定を行っておこう。

Postfix の標準化とサービスの起動

root# alternatives --config mta
Tere are 2 programs which provide 'mta'.
 Selection   Command
----------------------------------------------
*+ 1         /usr/sbin/sendmail.sendmail
   2         /usr/sbin/sendmail.postfix
Enter to keep the current selection[+], or type selection number: 2
 
root# service sendmail stop
root# service postfix start

送受信テスト

ローカルマシン上から、バーチャルメールドメインアカウントの例えば penguin@hoge.cxm へメールを送信してみる。テスト送信コマンドのいろいろは Qmail のページの「動作テストのためのコマンド」で紹介している。

送信したら、root 権限で mutt を使って読んでみるといいだろう;

root# mutt -f /var/vmail/hoge.cxm/penguin/Maildir/

ただし、POP3 を含めた運用が始まってからこのようにして mutt で覗き見すると、次回、本来のユーザがメールクライアントでメールを読み込んだ時に全てのメールが再リトリーブされる可能性があるので、濫用は避けること。