オフィシャルサイト: The Postfix Home Page

Postfix Tips

筆者が実際に試した Postfix の小技集。けっこう大技もあったりするが...

Table of Contents

ひとつのOS上で複数の Postfix を動かす

PostfixSendmail に比べるとアドレスリライティング機能が弱い。例えば、或る宛先ドメインへメールを出す時にだけ From: ドメインを特定のものに書き換えるというようなことができない。Postfix デーモンを複数立ち上げて別のポートか別の IPドレスで待機させる方法を知っておくと、アドレス書き換えの他にもいろいろな難局を乗り越えることができるだろう。

Advosys Consulting - Adding a second Postfix instance が非常に役立った。

本稿では、副インスタンスをループバックアドレスのポート 1025 で待機させる場合を例として構築法を示す。例えば、特定のドメイン宛の送信メールだけを主インスタンスからリレーで受けて From: ドメインを書き換えて外部へ送信する、送信専用MTA としての実装などに適している。副インスタンスは "postfix-deux" と名付けることにしよう。この名前はいろいろな設定項目で使うことになる。検証は RedHat Enterprise Linux 4.5 と CentOS 5.1 上で行った。

リッスンする別ポートまたは別アドレスの検討

Linux では、単一のネットワークインターフェイスカードにエイリアスというカタチで追加の IPアドレスを振ることができる。eth0:1, eth0:2 ... というやつだ。副Postfix がマシンの外からの SMTP コネクションを受け付けなければならない場合はそうするといいだろう。しかし、内部リレーで使う、つまり主インスタンスからの SMTP コネクションを受けるだけで事足りるのなら、ポートを変えるだけで充分だ。しかも、副Postfix はループバックアドレスしかリッスンしないようにしておけば、セキュリティリスクをひとつ減らすことができる。

前者の方法を採るのなら、次の行程に進む前にエイリアスインターフェイスを用意しておいていただきたい。

副Postfix用ディレクトリの作成

まずここで、主Postfix を停止させておく。

root# service postfix stop

Postfix の設定ディレクトリ /etc/postfix/ を、配下も含めて丸ごと /etc/postfix-deux/ に複製する。

root# cp -a /etc/postfix /etc/postfix-deux

スプールディレクトリはあとで作成する。

起動スクリプトの整備

共有ファンクションファイル

RedHat系デフォルトの rcスクリプトでは、ふたつの Postfix インスタンスの面倒をみるのは不可能だ。一番の問題は pid ナンバーの割り出しルーティンで、副インスタンスの停止ができなかったり、`service postfix status' で主副両方のプロセスが表示されるという現象が避けられない。

そこでまず、様々な rcスクリプトで共有されるユーザ定義ファンクション集である /etc/init.d/functions を改造しなければならない。とはいえ、このファイル自体をいじると他のデーモンに重篤な影響を与えてしまう。それを避けるため、主副Postfix の rcスクリプトだけが追加で読み込むシェルスクリプト断片 /etc/init.d/functions-postfix というものを作る。functions-postfixfunctions の一部のユーザ定義ファンクションを再定義するもので、pidfileofproc(), pidofproc(), status() の 3つのルーティンを置き換える働きを持っている。

functions-postfix

このファイルを /etc/init.d/ へコピーする。パーミッションは、他のファイルと同じ root:root755 にしてもいいが、644 に絞り込んでも構わない。

主Postfix 起動スクリプト

こちらはほんの微々たる調整だ。前項で新設した functions-postfix を追加インクルードさせるだけでいい。/etc/init.d/postfix の下記の箇所を修正する;

# Source function library.
. /etc/rc.d/init.d/functions
. /etc/rc.d/init.d/functions-postfix  <--ここにこの行を挿入する

副Postfix 起動スクリプト

こちらは大手術で、diff を採ってみたがほとんどの行がリプレースになってしまうのでやめたほどだ。主要な変更点を挙げておくと;

postfix-deux.rc

言わんでも分かると思うが、このファイルを /etc/init.d/postfix-deux としてコピーし、パーミッションを root:root 755 にする。

おっと! まだ絶対に起動させてはイケナい

Postfix設定ファイル

主Postfix の main.cf

メインの Postfix インスタンスに別の Postfix 設定ディレクトリの存在を教えてやるために、下記のディレクティブを 主Postfixの main.cf に書き加える。ファイルの末尾近く、`# INSTALL-TIME CONFIGURATION INFORMATION' の前がいいだろう。

alternate_config_directories = /etc/postfix-deux

副Postfix の main.cf

副インスタンスとして動かす上で含めなくてはならない設定ディレクティブは以下。各ディレクティブの前に解説を添えておいた。

# スプールディレクトリ. 必ず主インスタンスとは別にする.
queue_directory = /var/spool/postfix-deux
 
# これはループバックだけをリッスンさせる場合. エイリアスネットワークインターフェイスを聞かせる場合はそのIPを.
inet_interfaces = loopback-only
 
# Postfix の SMTPクライアントプロセスが次ホップ (メールリレーなど) と通信する際に使用するIP。ループバックだけをリッスン
# させる場合をはじめ、入ってくるインターフェイスと出て行くインターフェイスが異なる時には書いておいたほうがいい.
smtp_bind_address = 192.168.1.3
 
# ログを主インスタンスとは異なるファシリティで syslog に渡せばログファイルを振り分けられる.
syslog_facility = local5
 
# ループバックだけをリッスンさせる場合、リレー元は主インスタンスしかあり得ないので `host' にしておくのが安全.
mynetworks_style = host
 
# 1種類のプロセス (例えば `virtual' や `smtp' など) の最大同時起動数。主Postfix よりは少ないはずなので、
# 安全とメモリ節約のため減らしておいたほうがよい.  Postfix 2.2 のデフォルトは 100.
default_process_limit = 50

副Postfix の master.cf

Postfix において master.cf というファイルは、様々な用途の子プロセスの定義・設定を行うファイルだ。リッスンするポートを変更するには下記の部分を修正する。この例は、副インスタンスにループバックアドレスだけをリッスンさせる場合だ。

#smtp           inet    n  -  n    -    -    smtpd  <--コメントアウト
localhost:1025  inet    n  -  n    -    -    smtpd  <--新規行

副Postfix のスプールディレクトリ作成

起動の準備が整ったので、やっと副Postfix 用のスプールディレクトリが作れる。ここまで引き延ばしたのは、スプールの作成には postfix コマンド自体を使う必要があるからだ。

root# mkdir /var/spool/postfix-deux
root# postfix -c /etc/postfix-deux check

上記のように postfix を直接 check 命令を付けて呼ぶと、不足しているディレクトリが自動的に作成されるとともに、ファイルやディレクトリのパーミッションが適切に修正される。

起動

基本的な準備は以上で完了。「起動スクリプトの整備」で用意した rcスクリプトを使って起動しよう。

root# service postfix start
root# service postfix status
root# service postfix-deux start
root# service postfix-deux status

無事起動するようだったら、副デーモンも所定の runレベルにスタートアップ登録しよう;

root# chkconfig --add postfix-deux

副Postfix用コマンドラッパー

Postfix には、設定の確認やメールキューの状況確認/操作などを行うための各種ユーティリティが付属している。それらのほとんどは、環境変数 MAIL_CONFIG に設定ディレクトリパス名をセットするか -c オプションでパスを与えてやれば副Postfix のために動いてくれる。しかし、いちいち `env MAIL_CONFIG=/etc/postfix-deux mailq' だの `mailq -c /etc/postfix-deux' だのとコマンドするのは面倒臭い。そこで、あらかじめこれらのオプション付きでコマンドを書いた、ラッパーシェルスクリプトを用意しておくといい。

筆者の用意した postfix-deux-wrap.tar.gz には以下のラッパーがセットにしてある;

mailq-deux postcat-deux postconf-deux postmap-deux
postqueue-deux postsuper-deux qshape-deux  

ラッパースクリプトはオリジナルバイナリと同じパスに置きたいが /usr/bin/ だったり /usr/sbin/ だったりしてコピーも説明も面倒なので、Makafile を同梱しておいた。postfix-deux-wrap.tar.gz をダウンロードしたら、以下の要領で一気にインストールできる;

user$ tar xzvf postfix-deux-wrap.tar.gz
user$ cd postfix-deux-wrap
user$ make help    <--ヘルプを見るべし
user$ su
root# make install

これで、例えば副インスタンスのメールキューに何通のメールが溜まっているか見たければ;

root# mailq-deux

と打つだけでOK。postsuper など引数の必要なコマンドのラッパーは、ちゃんと全ての引数を受け取るように作ってある。以後、副インスタンス用の設定 bdb テーブルを更新する時には postmap でなく postmap-deux のほうを使うのを忘れずに。