Postfix Rate Controls


上のレベルへ | 基本設定 | UCE 制御 | 速度制御 | リソース 制御 | アドレス操作

イントロダクション

ハイパフォーマンスなメール配送システムを作るのと、他のシステムを 倒さないハイパフォーマンスなメール配送システムを作るのは違うことです。 大群(thundering herd) シンドロームに病んでいるメーラが あります: 文字通りメールで他のシステムを氾濫させます。 Postfix は高速なメーラであると同時に、よき隣人であろうとします。

内向きに関しては、Postfix SMTP サーバ は悪意があったり混乱したクライアントに対して適切に防御します。 インフラストラクチャに対する激しい Denial of Service 攻撃に対する 保護はしませんが、これにはプラグを抜く以外の対処法はないでしょう。

特に指示がなければ、ここで記述される全てのパラメータは main.cf ファイルに書きます。動いている Postfix システムの パラメータを変更したら、忘れずに postfix reload コマンドを 実行してください。

プロセス制限

default_process_limit パラメータ (デフォルト: 100) は内向きおよび外行きの配送速度を直接制御します。このパラメータは Postfix サービス (smtp クライアント、smtp サーバ、local 配送等) を実装する、並列配送数を制御します。小さなシステムやダイアルアップ ネットワークで接続しているシステムでは、10 程度の default_process_limit がより適切でしょう。 マシンが主要なメールハブであれば、より大きな値を使ってください。

master.cf ファイルを編集する事で、特定の Postfix デーモンに対してこの設定を上書きする事ができます。例えば、 同時に 100 の SMTP メッセージを受け取りたくなければ、次のように 指定することができます:

 
# ==========================================================================
# service type  private unpriv  chroot  wakeup  maxproc command + args
#               (yes)   (yes)   (yes)   (never) (100)
# ==========================================================================
. . .
smtp      inet  n       -       -       -       5       smtpd
. . .

同時配送

そして、大量のディスクとメモリを載せた巨大なメールハブで、 最大 1000 の SMTP クライアントプロセスを同時に走らせるように Postfix を設定しました。おめでとう。しかし、本当に同時に 1000 の接続を同時に同じリモートシステムにしたいでしょうか? おそらく違うでしょう。

Postfix キューマネージャが救いの手をさしのべます。このプログラムは TCP slow start 流量制限戦略と同様の物を実装しています: あるサイトへの配送時に、まず小量のメッセージを送り、それから すべてがうまくいく間、速度を増加させます; 渋滞の直前で速度を 緩めます。

initial_destination_concurrency パラメータ (デフォルト: 2) は、並列配送数を適応する前に同じ配送先に最初に送るメッセージの 数を制御します。もちろんこの設定は プロセス制限や特定のメール配送チャネルに 対する並列配送数制限を越えない限りにおいて有効です。

default_destination_concurrency_limit パラメータ (デフォルト: 20) は同じ配送先に同時に送ることができるメッセージの 数を制御します。この設定は特定の配送チャネル (local, smtp, uucp 等)に対して上書きすることができます。main.cf ファイルは 次の設定を推奨しています:

local_destination_concurrency_limit = 2
default_destination_concurrency_limit = 20
local_destination_concurrency_limit パラメータは 同じローカル受信者に対して同時に配送するメッセージの数を制御します。 推奨される制限が低いのは、同じメールボックスへの配送は順次 おこなわなければいけなく、大量の並列は不便だからです。 同じ受信者への同時配送を制限する他の重要な理由もあります: 受信者が重いシェルコマンドを .forward ファイルで動かしていたり、 受信者がメーリングリストマネージャであった場合は、同時に多すぎる インスタンスを動かしたくないでしょう。

一つの配送先への SMTP 配送を潰さずにシステムに目立った負荷をかけるには、 並列数制限は 20 で十分だと思われます。大きすぎる値に変更する際は 十分注意してください。

受信者制限

default_destination_recipient_limit パラメータ (デフォルト: 50) Postfix 配送エージェント (smtp, uucp, etc.) がEメールメッセージのコピーを送る際の受信者の数を制限します。 一つのEメールメッセージに $default_destination_recipient_limit 以上の同じ配送先の受信者があると、受信者リストは小さく分けられ、 複数のメッセージのコピーが送られます。

特定の Postfix 配送エージェント (smtp, uucp, 等) に対して この設定を上書きすることができます。例えば:

uucp_destination_recipient_limit = 100
UUCP 配送ごとの受信者の数を 100 に制限します。

受信者数制限を大きくする際には十分注意しなければいけません; メモリを使い果たしたり受信者数のハード制限に達すると接続を 強制終了する SMTP サーバがあり、メールが届かなくなります。

smtpd_recipient_limit パラメータ (デフォルト: 1000) は SMTP サーバが配送毎に受け取る受信者の数を制御します。 これは適切な SMTP クライアントが送るよりも大きな値です。 この制限は悪意があったり混乱したクライアントからローカル メールシステムを保護するためだけに存在します。

常に遅延させる配送

defer_transports パラメータには、Postfix が明示的に配送を 依頼されるまで、メールを常に遅延させる配送方法を指定します。

一時的にしかオンラインにならなかったり、(例えば PPP ダイアルアップ スクリプトから) sendmail -q コマンドが実行されるまで 全ての配送を遅延したい小さなサイトでは、次のように使います:

defer_transports = smtp

ISP では defer_transports 機能をほとんどの時間 off-line な顧客に使うこともできます。顧客は ETRN コマンドを SMTP ポートで実行する事で、配送を促すことができます。次の例は そのような顧客を設定する方法を示します:

/etc/postfix/main.cf:

defer_transports = hold

ここにはいくつでも transport を指定する事ができます。この例では 一つだけです。

/etc/postfix/transport:

customer.com   hold:[gateway.customer.com]
.customer.com   hold:[gateway.customer.com]

[] は MX 検索を避けるために必要で、これはローカルマシンを指すかも しれません。2番目のエントリは顧客のサブドメインにメールを リレーしたい時のみに必要です。

/etc/postfix/master.cf:

hold   unix   -   -   n   -   -   smtp

これは通常の SMTP に対する master.cf エントリと同じで、 最初のフィールドだけが hold に変わっています。

接続できないホストの配送遅延

Postfix 配送エージェント (smtp, local, uucp, など) がメッセージを配送できない時に、メッセージ自身や受け取る組織に 原因を求めるかも知れません。

期待通りに、このプロセス全体はいくつかの小さなパラメータによって 支配されています。

queue_run_delay (デフォルト: 1000 秒)
キュー マネージャが遅延メールのキューをスキャンする頻度。

maximal_queue_lifetime (デフォルト: 5 日)
メッセージが 配送不能として送り返されるまでにキューに留まる期間。最初の配送試行で 失敗したらすぐにメールを送り返すのであれば 0 を指定します。

minimal_backoff_time (デフォルト: 1000 秒)
メッセージが 検索されない最小時間および「死亡」配送先に手を出さない最小時間。

maximal_backoff_time (デフォルト: 4000 秒)
配送に 失敗してからメッセージを見ない最大時間。

qmgr_message_recipient_limit (デフォルト: 20000)
メモリ 内キューマネージャデータ構造のサイズ。特に、このパラメータは 短期間、メモリ内「死亡」リストのサイズを制限します。リストに合わない 配送先は追加されません。

悪質クライアントの低速化

まずはじめに、どんな防御も激しい Denial of Service 攻撃に対しては 保護しません。不可能な期待を起こすことは避けたいだけです。 しかし混乱したり悪意を持ったクライアントプログラムに対処するために できる簡単なことがいくつかあります。

いくつかの防御はより一般的な戦略の一部です: 例えば、どの程度の 長さのテキストが細かく分割されるかであるとか、複数行メールヘッダで どの程度の量のテキストを配送するかなどです。詳細は リソース制御のドキュメントを参照してください。

Postfix SMTP サーバ はクライアントの要求が 認識できなかったり実装されていない場合や、クライアントの要求が UCE 制限や他の理由に違反している場合に セッション毎のエラーカウンタを増加させます。エラーカウンタは メッセージの配送に成功するとリセットされます。

セッション毎のエラーカウンタが増加すると、SMTP サーバは振る舞いを 変えます。クライアントを遅くすることでダメージを制限するという 考え方です。この振る舞いは次のパラメータにより制御されます:

smtpd_error_sleep_time (デフォルト: 1 秒)
セッション 毎のエラーカウントが小さければ、SMTP サーバはクライアントに問題を 報告する時に一時止まるだけです。これは、神経質なクライアントが 高速な接続-エラー-切断ループに入ることを防ぐためです。

smtpd_soft_error_limit (デフォルト: 10)
セッション 毎のエラーカウントがこの値を越えると、SMTP サーバはクライアントの 要求に応答する前に error_count 秒スリープします。

smtpd_hard_error_limit (デフォルト: 20)
セッション 毎のエラーカウントがこの値を越えると、SMTP サーバは接続を切ります。

不幸なことに、Postfix SMTP サーバは SMTP サーバプロセスの総数を制限 する(プロセス制限参照)以外に、 同じクライアントからの接続の数を制限する方法を未だに知りません。 さらに悪い状況: SMTP サーバプロセス制限を実装していないメーラもあります。 もちろんこれは弁解ではありません。私はよい解決法を探し続けています。


上のレベルへ | 基本設定 | UCE 制御 | 速度制御 | リソース 制御 | アドレス操作