インストールの方法 1. SMTPfeed のインストール 1.1 ./configure bind4 のインストール・ディレクトリを指定する場合は、 --with-bind4=/usr/local/bind4 のように指定します。 bind8 を利用する場合は、--with-bind8 スイッチを指定します。 bind8 のディレクトリの場所も指定したい場合は、 --with-bind8=/usr/local あるいは --with-bind8=/usr/local/bind8 のように指定します。 IPv6 を利用する場合は、--enable-ipv6 スイッチを指定します。 smtpfeed のインストール・ディレクトリは --libexecdir= で指定します。 インストール・ディレクトリのデフォルトは、/usr/libexec または /usr/lib (後者は /usr/libexec が存在しない場合) です。 ライブラリを static link する必要がある場合は、--with-static を 指定します。gcc の場合は、-static が、それ以外の場合は -Bstatic が LDFLAGS= に追加されます。それ以外のスイッチを指定する必要がある 場合は、次のステップで Makefile に直接書き込みます。 FD_SETSIZE の値をデフォルトより増やしてコンパイルしたい場合は、 --with-fds= にその値を指定します。デフォルト値については、select(2) などを参照して確認してください。またシステムが許容する最大値に ついては limit(1) 等で確認してください。 1.2 Makefile の編集(必要な場合のみ) Makefile を編集して、不足しているコマンドライン・スイッチ等を 指定します。 1.3 make all 1.4 make install 1.5 syslog.conf の調整 facility にあわせて local5.info /var/log/smtplog などと書いておきます(デフォルトは local5)。 facility は smtpfeed のコマンドライン・スイッチでも変更可能です。 ログファイルの作成と、kill -HUP {syslogdのPID} を忘れずに。 1.6 動作確認 簡単な動作確認は TEST.in の中のアドレスを適当に変更した後、 % smtpfeed -dA -lstderr < TEST.in を実行します。-dA は全てのデバッグ出力を得る指定、-lstderr は デバッグ出力を画面に送る指定です。 2. sendmail の変更とコンパイル 2.1 sendmail.8.11.x の入手と展開 2.2 3.3W.patch をあてる 存在しないファイルへの diff を含むので、古い patch コマンドだと うまくあたらないかもしれません。その場合は、新しい GNU patch を インストールしてください。 パッチを当てた後の conf.h において DYNAMIC_TOBUF を 1 に define しておきます(デフォルト)。 2.3 sh Build DB 関係や BIND 関係の調整も必要に応じて行ってください。 3. sendmail.cf の調整 A. 使用中の sendmail.cf を直接変更 B. m4 tool による設定 B. CF による設定 の3つの方法について説明します。 3.A 使用中の sendmail.cf を直接変更 この時点で /etc/sendmail.cf を直接変更せずに別のファイルに バックアップしておきます。 3.A.1 smtpf mailer の定義 smtp (あるいは esmtp, smtp8 など) mailer の定義を別の行にコピー して以下の変更をおこないます。 * mailer name を smtpf に * P=[IPC] を P=/usr/libexec/smtpfeed (インストールしたパス) に * F= に z の追加 (LMTP を指定)と m が含まれていることの確認 * A= を smtpfeed に(必要ならば smtpfeed に与えるオプションも) 例えば smtpfeed が認識する hostname が FQDN でないときは -c $j を補う。ループバックチェックを確実に行わせるため、 DNS の あらゆる MX レコードの右辺に現れる当該ホストを示す 名前は、-c あるいは -a で指示されていなければならない。 syslog にメッセージの queueID 情報も残るようにするには、 -i$i を指定する。ただし、受信者数が多いために複数のトラン ザクションに分割される場合は、2回目以降のトランザクションに queueID が引き継がれない(RSET コマンドでクリアされる)。 引き継がれるようにするには、$?{runqueue}-i$i$|-I$i$. のように指定する(sendmail 8.9.1+3.1W 以降を利用している場合 のみ)。これは、runqueue 処理の際に連続するトランザクションが 同一メッセージを処理するものでないことを考慮し、runqueue 処理でない場合に -I$i が指定されるようにするものである。 あるいは、sendmail が付加する Received: ヘッダ行に現れる id 情報を queueID として利用する場合は、-E オプションを指定する。 この場合、runqueue 処理におけるすべてのトランザクションに おいて、queueID が得られるであろうと期待できる。 * E= に指定する改行コードは \n でも \r\n でも良い。 (例) Msmtpf, P=/usr/sbin/smtpfeed, F=mDFMuXz, S=11/31, R=21, E=\n, L=990, T=DNS/RFC822/SMTP, A=smtpfeed 3.A.2 smtp (あるいは esmtp, smtp8 など) の呼び出しを smtpf に変更 その際、$@ の部分は固定文字列になるように修正しておかなければ、 ドメインの異なるアドレスが一度に smtpfeed に渡されないので注意 が必要です。 (例) R$* < @$* > $* $#esmtp $@ $2 $: $1 < @ $2 > $3 を ^^^^^^^^ TAB R$* < @$* > $* $#smtpf $@ LMTP $: $1 < @ $2 > $3 に ^^^^^^^^ TAB 3.A.3 $[ $] の使用の排除 特に必要な処置ではありませんが遅延の原因になるので、ネーム サーバを参照したメールアドレスの書き換えの必要がない場合は コメントアウトしておきます。 (例) R$* < @ $* $~P > $* $: $1 < @ $[ $2 $3 $] > $4 を ^^^^^^^^^^^ TAB #R$* < @ $* $~P > $* $: $1 < @ $[ $2 $3 $] > $4 に ^^^^^^^^^^ TAB 3.B m4 tool を利用 以下の定義を追加して sendmail.cf を作成します。 FEATURE(nocanonify)dnl MAILER_DEFINITIONS Msmtpf, P=/usr/sbin/smtpfeed, F=mDFMuXz, S=11/31, R=21, E=\n, L=990, T=DNS/RFC822/SMTP, A=smtpfeed MAILER(smtp)dnl define(`SMART_HOST', `smtpf:LMTP')dnl mailertable を利用している場合は、利用する mailer の指定で、 smtpf:LMTP などと書きます。 3.C CF を利用 以下の定義を追加して sendmail.cf を作成します。 P= の部分はインストールディレクトリに適宜読み替えてください。 LOCALHACKMAILER='# smtp feed mailer\ Msmtpf, P=/usr/libexec/smtpfeed, F=mDFMuXz, S=11, R=21,\ T=DNS/RFC822/SMTP, E=\n, L=990,\ A=smtpfeed' # hostname が FQDN でないときは A=smtpfeed -c $j に DIRECT_DELIVER_DOMAINS=none DEFAULT_RELAY='smtpf:LMTP' mailertable を利用している場合は、利用する mailer の指定で、 smtpf:LMTP などと書きます。 A, B, C とも、テストモードで以下のようになれば OK です。 > 3,0 user@domain rewrite: ruleset 3 input: user @ domain rewrite: ruleset 96 input: user < @ domain > rewrite: ruleset 96 returns: user < @ domain > rewrite: ruleset 3 returns: user < @ domain > rewrite: ruleset 0 input: user < @ domain > rewrite: ruleset 88 input: < smtpf : LMTP > . user < @ domain > rewrite: ruleset 88 returns: $# smtpf $@ LMTP $: user < @ domain > rewrite: ruleset 0 returns: $# smtpf $@ LMTP $: user < @ domain > 4. さらなる sendmail.cf の調整 4.1 トランザクション1回あたりの受信者数の調整 SMTP の仕様では、トランザクション1回あたりの受信者の最大数が 100 に 規定されています。DYNAMIC_TOBUF を定義すると固定長バッファのサイズに 起因する制限は緩和されますが、上記規定に従って 100 を越える受信者に ついては、別のトランザクションに分割されます。この制限があると、 sendmail から SMTPfeed に渡される受信者数の最大が 100 に抑えられて しまうため、SMTPfeed による並列度も最大 100 に抑えられてしまいます。 この制限はホスト内での合意に基づき緩和することができますから、 この制限を緩和して SMTPfeed にさらに多くの受信者を一度に渡すことに よって、さらに並列処理の効果を向上させることができます。 3.4W.patch では mailer 定義で r= 式が sendmail.cf で利用できるよう になっています。sendmail.cf において、 Msmtpf, P=/usr/sbin/smtpfeed, F=mDFMuXz, S=11/31, R=21, E=\n, L=990, T=DNS/RFC822/SMTP, r=1000, A=smtpfeed のように定義すると、sendmail の SMTPfeed に対する 1回のトランザク ション当たりの受信者の最大数を 1000 にまで緩和することができます。 デフォルトは 100 です。 メモリに余裕がある場合は、r= に指定する値は、メーリングリストの参 加者数を越える値にしておきます。 なお、sendmail.cf で ConnectionCacheSize が 1 以上であれば、複数に 分割されたトランザクションを同じ smtpfeed プロセスが処理を行います。 異なる smtpfeed プロセスを起動したい場合は ConnectionCacheSize を 0 にします。 smtpfeed によるメモリ占有量を減らそうとして r= に指定する値を小さ くすることで、一回のトランザクションで処理されるアドレスを少なくし ようとするときは、ConnectionCacheSize を 0 にしておくことを推奨し ます。3.2W.patch では smtpf mailer に mailer flag ; を追加すること で、特定のメーラのキャッシュのみを禁止することができます。 4.2 SMTPfeed 利用の抑制 受信者が1人だけであるような配信は、わざわざ SMTPfeed を起動せずに sendmail のみで処理をする方が効率的です。また、SMTPfeed は全ての 情報をメモリに保存するため、非常に大きなメッセージの配信には向いて いません。そこで、受信者数やメッセージサイズによって SMTPfeed を 起動するかどうかの選択ができると嬉しいわけです。ここでは、3.4W.patch に実装されている MULTI_MAILER 機能を利用します。 MULTI_MAILER 機能とは、sendmail.cf の配信メーラ選択部分において、 R$* < @$* > $* $#smtpf $@ LMTP $: $1 < @ $2 > $3 $#esmtp $@ $2. $: $1 < @ $2 > $3 (実際の設定では、1行目の最後の $3 と 2行目の最初の $# の間に TAB があってはならない。上記の例では 1行目の $* と $# の間のみに TAB。) のように複数のメーラを指定できるようにするものです。これにより、 1番目のメーラが TEMPFAIL で配信に失敗した場合には、2番目のメーラを 用いて配信の再試行をさせることができます。 さらに、冒頭に書いたように、最初から1番目のメーラを起動させたくない 場合の判定のために、*= equate (最小受信者数) や M= equate (扱う メッセージサイズの上限) を smtpf mailer に指定しておきます。 また、mailer flag ! (runqueue での使用を抑制) や mailer flag _ (TEMPFAIL でも次に進まない) なども指定しておくと良いでしょう。 Msmtpf, P=/usr/sbin/smtpfeed, F=mDFMuXz!_, S=11/31, R=21, E=\n, L=990, *=5, T=DNS/RFC822/SMTP, M=50000, A=smtpfeed このように設定しておくと、後続の mailer が存在し、受信者が5人に満た ない場合に、smtpfeed を起動することなく、すぐに後続の mailer に よる配信にスキップします(後続の mailer がなければ、*=5 が指定されて いても、配信処理をおこないます)。M= によるサイズの指定も同様で、 サイズ制限を越えるメッセージサイズで、後続の mailer が存在する 場合は、エラーにせず後続の mailer による配信にスキップします。 mailer flag ! が指定されていれば、メールの受信直後の配信には利用され ますが、一旦キューに保存されたメールの配送では、最初の処理以外には 利用されなくなります。 mailer flag _ が指定されていれば、当該 mailer が利用された場合、 その配信処理の結果の如何にかかわらず、後続の mailer は利用されなく なります(*=, M=, などと組み合わせて利用することで意味を持ちます)。 CF で MULTI_MAILER 機能を用いた定義を行う場合は以下のようになります。 P= の部分はインストールディレクトリに適宜読み替えてください。 LOCALHACKMAILER='# smtp feed mailer\ Msmtpf, P=/usr/libexec/smtpfeed, F=mDFMuXz!_, S=11, R=21,\ T=DNS/RFC822/SMTP, E=\n, L=990, M=50000, *=5,\ A=smtpfeed' DIRECT_DELIVER_MAILER=smtpf DIRECT_DELIVER_DOMAINS=all #DEFAULT_RELAY= DSPTLOCALHACK='R.$* $#smtpf$@LMTP$:$2$#smtp$@$1$X$:$2' ^TAB m4 tool で MULTI_MAILER 機能を用いた定義を行う場合は以下のようになり ます。 FEATURE(nocanonify)dnl MAILER_DEFINITIONS Msmtpf, P=/usr/sbin/smtpfeed, F=mDFMuXz!_, S=11/31, R=21, E=\n, L=990, T=DNS/RFC822/SMTP, M=50000, *=5, A=smtpfeed MAILER(smtp)dnl define(`SMART_HOST', `smtpf:LMTP')dnl LOCAL_CONFIG # These rules should be inserted to the top of S95 S95 R< smtpf : LMTP > $*<@$*>$* $#smtpf$@LMTP$:$1<@$2>$3$#smtp$@$2.$:$1<@$2>$3 R< smtpf : $* > $* $#smtpf$@LMTP$:$2$#smtp$@$1.$:$2 R< smtpf > $*<@$*>$* $#smtpf$@LMTP$:$1<@$2>$3$#smtp$@$2.$:$1<@$2>$3 ^^^^^^^^^^ TAB 4.3 LMTP DATA の完了時のタイムアウト sendmail は SMTPfeed の処理の終了を待ち、LMTP の DATA コマンド処理の 完了時に得られる配信結果レポートによって配信の成否情報を受け取ります。 SMTPfeed の処理がなかなか終らないときは、sendmail はタイムアウト処理 によって、配信処理が完了しなかったと見なし、再試行のために mqueue に メールを保存します。このため、SMTPfeed の処理がタイムアウトまでに完了 しないと、メールの2重配信が発生する可能性があります。このような問題を 避けるため、SMTPfeed が必ずタイムアウト期限が来るまでに完了するように 設定しておく必要があります。 SMTPfeed はデフォルトで 55 分以内に処理が完了しなかった場合は、残って いる配信処理を切り上げ、その時点で配信が完了している宛先をレポートし て終了します。この時間は、SMTPfeed の -t total= オプションによって変 更することができます。60分を指定する場合は -t total=60m と指定します。 正確には、-t total= で指定した時間が経過してから終了処理を開始するの で、最長の場合はさらに quit に対するタイムアウト時間がかかることにな ります。デフォルトでは、合計 57 分となります。 一方、sendmail 側では、sendmail.cf の O Timeout.datafinal= オプション で、タイムアウト時間を設定することができます。デフォルトは、1h (1時間) です。 5. sendmail と SMTPfeed による配送動作の確認 # newsendmail -C newsendmail.cf addresses < file maillog や smtplog も確認します。 6 sendmail と sendmail.cf の置き換えと再起動 うまくいくかな…? 7. 使用上の注意 SMTPfeed の BIND resolver は、ネームサーバからの応答に含まれる、 additional information を利用します。CERT Advisory CA-97.22: Topic: BIND - the Berkeley Internet Name Daemon で報告されている問題を 回避するため、SMTPfeed が問い合わせに利用する BIND server (named) には、 4.9.6 or 8.1.1 以降のバージョンを使用する必要があります。もちろん、 CERT Advisory CA-98.05 の報告もあるので、4.9.7 or 8.1.2 以降のバージョ ンを使用した方が良いことはいうまでもありません。 SMTPfeed は、同時に多くの SMTP コネクションを開こうとするため、SMTPfeed が稼働するホストは、SMTP の相手先から同時に多数の IDENT(RFC1413) 要求を 受けることになります。もし、identd が inetd から nowait で起動されるよう に設定されていると、一気に多数の identd が起動されるため、システムが一時 的に過負荷になります。このような過負荷を避けるために、identd を常駐型に するか、起動されないようにしておくと良いでしょう。 同時に要求するコネクションの数を減らしたい場合は、SMTPfeed の -n オプショ ンを使用してください。sendmail.cf の r= の値を減らすことはあまり効果的で はありません。