Postfix はキューに入れる前に同時に1行のメッセージヘッダまたは メッセージ本体の内容を調べる、ビルトインフィルタ機能をサポートして います。フィルタは通常、header_checks(5) マニュアルページに書かれている POSIX または PCRE 正規表現で 実装されます。
ビルトインフィルタは特定のEメールワームやウィルスの発生を止める ことが元々の目的であり、これはうまく機能しました。またフィルタは バウンスされたジャンクメール、ワームやウィルスからのバウンスメール、 ウィルス検知システムからの通知をブロックするのにも役立ってきました。 この2番目の応用についての情報は BACKSCATTER_README ドキュメントに 挙げられています。
ビルトインフィルタは特定のワームやウィルスの発生を止めることに 最適化されているため、一般的なジャンクEメールやウィルス検知に 「適さない」ような制限があります。そのためには、 FILTER_README や SMTPD_PROXY_README ドキュメントに 書かれているような、いずれかの外部コンテンツ検査方法を使うべきです。
以下の図は Postfix ビルトインコンテンツ検査がどのように働くかという 概略を示しています:
Postmaster
通知|
vネットワークまたは
ローカルユーザ-> ビルトイン
フィルタ-> Postfix
キュー-> 配送
エージェント-> ネットワークまたは
ローカルメールボックス^
||
v配送できないメール
転送されたメール
この絵は Postfix が新しいメールを受け取る際にフィルタが働くことを 明らかにしています。これは Postfix がネットワークからのメールを、 送信者のアドレス (なりすましの場合がよくあります) に配送できない メールを返すことなく拒否できます。しかし、この機能はかなりの高負荷に なります: メールの検査に時間がかかりすぎると、リモートクライアントは タイムアウトしてしまい、クライアントは同じメッセージを繰り返し送る ことになるかもしれません。
このドキュメントがカバーしている話題:
Postfix ヘッダ/本体チェックは incoming キュー にメールを入れる前の cleanup(8) サーバによって 実装されています。以下の図は cleanup(8) サーバ周辺を拡大し、このサーバが多くの異なるソースからのメールを 扱っていることを示しています。図を読みやすくするため、postmaster 通知の ソースは示されていません。postmaster 通知は多くの Postfix デーモン プロセスが生成する可能性があるためです。
bounce(8)
(配送できない)smtpd(8)
(ネットワーク)\ |
vqmqpd(8)
(ネットワーク)-\
-/cleanup(8) -> incoming
キューpickup(8)
(ローカル)/ ^
|local(8)
(転送)
効率上の理由で、Postfix の外部から入ってくるメールのみがヘッダ/本体 チェックで検査されます。すでにフィルタリングされたメールを再び フィルタリングするのは非効率ですし、postmaster 通知をブロックするのは 望ましくないことでしょう。以下の表はヘッダ/本体チェックを受ける、 もしくは受けないメールをまとめています。
メッセージの種類 ソース ヘッダ/本体チェック? 配送できないメール bounce(8) No ネットワークメール smtpd(8) 設定可能 ネットワークメール qmqpd(8) 設定可能 ローカル投函 pickup(8) 設定可能 ローカル転送 local(8) No Postmaster 通知 many No
どのメールがフィルタリングされる必要があるかを、Postfix はどのように 決めるのでしょうか? cleanup(8) サーバは 非常に多くの異なるソースからメールを受け取るため、このプログラムが 決めるのはよい方法ではありません。代わりに、ヘッダ/本体チェックは ソースによって要求されます。 smtpd(8) や qmqpd(8)、pickup(8) で受け取るメールのヘッダ/本体チェックを無効にする方法の例が以下の "外部ユーザからのメールのみをヘッダ/本体チェック するように設定する" や "あるドメイン宛の メールのみをヘッダ/本体チェックするように設定する" にあります。
ヘッダ/本体チェックはメッセージヘッダやメッセージ本体の内容を デコードしません。例えば、メッセージ本体が BASE64 エンコード (RFC 2045) されて いると、あなたの正規表現は BASE64 エンコードされた形にマッチしなければ いけません。同様に、非 ASCII 文字でエンコードされたメッセージヘッダ (RFC 2047) は エンコードされた形にマッチする必要があります。
ヘッダ/本体チェックはメッセージヘッダや本体行の組み合わせで フィルタリングすることはできません。ヘッダ/本体チェックは同時に1つの メッセージヘッダ、または同時に1つのメッセージ本体行を調べ、その決定を 次のメッセージヘッダや本体行に持ち越すことはできません。
ヘッダ/本体チェックはメッセージの受信者によって変えることは できません。
一つのメッセージが複数の受信者を持つことがありますが、 メッセージの全ての受信者は同じ扱いを受けます。複数受信者を持つ メールの一部の受信者を遅延させることを含む回避方法が提案されて いますが、SMTP パフォーマンスが落ちる結果となり、また非 SMTP メールでは働きません。
メールのソースの一部はヘッダや内容を受信者情報の前に送ります。 フィルタリングが必要かどうかを決める前にメッセージ全体をバッファに 入れることは効率が悪く、またフィルタリングやバッファリングが必要と わかる前にメールをフィルタリングし動作の全てをバッファに入れるのは よい方法ではありません。
警告しているのに、数百もしくは数千の正規表現を使って、ビルトイン フィルタ機能を一般的なジャンクメールやウィルスのブロックに使おうとする 人たちがいます。これは壊滅的にパフォーマンスが落ちてしまいます。 症状は以下の通りです:
cleanup(8) プロセスが正規表現を 処理するために利用可能な CPU タイムを全て使い果たしてしまうか、 利用可能なメモリを全て使い果たしてシステムがスワップし始めます。 これは入ってくるメール全ての配送を遅くします。
Postfix はEメールメッセージを受け取るためにさらに多くの時間を 必要とし、同時 SMTP セッション数が SMTP サーバプロセスの制限に達するまで 増加します。
cleanup(8) が終わるのを全ての SMTP サーバプロセスが待つ間、新しい SMTP クライアントは SMTP サーバ プロセスが利用可能になるまで待たなければなりません。このため、 それが始まる前にメール配送はタイムアウトしてしまいます。
この種のパフォーマンス問題の解決は簡単です: 一般的なジャンクEメールや ウィルスのブロックにヘッダ/本体チェックを使ってはいけません。またキューに 入る前にメールをフィルタリングしてはいけません。パフォーマンスを考慮すべき 場合は、FILTER_README ドキュメントに 書かれている、メールがキューに入った後に走る外部コンテンツフィルタを 使ってください。
以下は Jim Seymour の http://jimsun.linxnet.com/downloads/pflogsumm-faq.txt にある Pflogsumm FAQ から引用しました。Pflogsumm は拒否されたメールからの ログを含む、Postfix のログを解析するプログラムです。ログに Postfix body_checks パターンで拒否された 文が含まれていると、そのログも同じ body_checks パターンで拒否されて しまうかもしれません。header_checks パターンの場合、メール状態レポート部にある文には適用されないため、 この問題は存在しません。
Postfix が本体チェックをするように設定すると、Postfix はチェックを おこない、 Pflogsumm が報告し、Postfix は Pflogsumm レポートの中の同じ 文字列を受け取ります。この解法はいくつかあります。
Wolfgang Zeikat はこれを提供してくれました:
#!/usr/bin/perl use MIME::Lite; ### Create a new message: $msg = MIME::Lite->new( From => 'your@send.er', To => 'your@recipie.nt', # Cc => 'some@other.com, some@more.com', Subject => 'pflogsumm', Date => `date`, Type => 'text/plain', Encoding => 'base64', Path => '/tmp/pflogg', ); $msg->send;ここで "/tmp/pflogg" は Pflogsumm の出力です。これは Pflogsumm's の 出力を base64 MIME 添付ファイルに入れます。
Wietse からの注意: 信頼できないユーザがアクセス可能なマシン上でこれを 動かす場合、Pflogsumm レポートを誰でも書き込み可能ではないディレクトリに 置く方が安全です。
postfix-users メーリングリストのスレッドへのフォローアップで、Ralf Hildebrandt が次のように指摘しています:
"mpack が同じことをやります。"
確かにそうです。どちらのツールを使うかは好みの問題です。
他の解として、日常のメール状態レポートを除外する body_checks ルールを追加すると いうのもありますが、これは推奨できません。このようなルールは全てのメールを 遅くし、Postfix の管理を複雑にします。
以下の情報は Postfix 2.1 に当てはまります。以前の Postfix のバージョンは receive_override_options 機能をサポートしません。
最も簡単な方法としては、「1つの」Postfix インスタンスで複数の SMTP サーバ IP アドレスを持つよう master.cf に設定します:
2つの SMTP サーバ IP アドレスを内部ユーザからのメール専用で用意し、 ヘッダ/ 本体フィルタリングを無効にしておきます。またローカルメール収集 サービスでヘッダ/本体フィルタリングを無効にしておきます。
/etc/postfix.master.cf: # ================================================================== # service type private unpriv chroot wakeup maxproc command # (yes) (yes) (yes) (never) (100) # ================================================================== 1.2.3.4:smtp inet n - n - - smtpd -o receive_override_options=no_header_body_checks 127.0.0.1:smtp inet n - n - - smtpd -o receive_override_options=no_header_body_checks pickup fifo n - n 60 1 pickup -o receive_override_options=no_header_body_checks
1つの SMTP サーバアドレスを外部ユーザからのメールに用意し、 ヘッダ/本体フィルタリングを main.cf で有効にしておきます。
/etc/postfix.master.cf: # ================================================================= # service type private unpriv chroot wakeup maxproc command # (yes) (yes) (yes) (never) (100) # ================================================================= 1.2.3.5:smtp inet n - n - - smtpd
以下の情報は Postfix 2.1 に当てはまります。以前の Postfix のバージョンは receive_override_options 機能をサポートしません。
MX サービスプロバイダで、あるドメインに対してヘッダ/本体チェックを 適用したくないのであれば、「1つの」Postfix インスタンスで複数の SMTP サーバ IP アドレスを持つよう master.cf に設定することができます。それぞれの アドレスは異なるサービスを提供します:
/etc/postfix.master.cf: # ================================================================= # service type private unpriv chroot wakeup maxproc command # (yes) (yes) (yes) (never) (100) # ================================================================= # SMTP service for domains with header/body checks turned on. 1.2.3.4:smtp inet n - n - - smtpd # SMTP service for domains with header/body checks turned off. 1.2.3.5:smtp inet n - n - - smtpd -o receive_override_options=no_header_body_checks
セットアップしたら、それぞれのドメインを適切な SMTP インスタンスに 振るように DNS の MX レコードを設定します。