今日は一日メールサーバーがパンク状態になっていた。
JRA-NETのメールサーバーをご利用の皆様には接続しにくい状況が続き、大変ご迷惑をお掛けしましたことをお詫び申し上げます。
今日のパンクの原因は大量のスパムだった。
ここ最近は数が減ってきていて安心していたが、何故か今日は嵐のごとく大量のスパムが届いている。
サーバーにSSHで入ってログファイルをtailすると画面上は残像しか見えない...
届いているスパムは実在するメールアドレス宛ではなく「kkvvbmdraqtdhcr@jra….」といった機械的にアカウント名部分を生成して送りつけてきているモノが90%以上なので、実際にメールボックスへ届くメールは非常に少ない。
しかし、SMTPサーバーはせっせとDBにメールアドレスが正しいか問い合わせて、結果を接続元に返している。
大量のアクセスが集中するのでDBへのコネクションが限界を超えてビジーが発生し、結果としてSMTPサーバーは動作が停滞。停滞しているのに次から次へとアクセスが入ってくるので待ちが待ちを呼ぶ形になりパンクしてしまっていた。
改めてエラーの状況を詳細に見てみると行儀の悪いスパムと行儀のいいスパムが居る事が解った。
行儀のいい奴はエラーを返すとサッサと接続を切って居なくなる。
しかし、行儀の悪い奴はエラーを返してもお構いなしにメールを送りつけようとしてくる。
具体的には RCPT TO で6件程の宛先を通知してくるが、全てエラーを返しているのに DATA を送ってくる。
応答コードなんかお構いなしで我が道を行くって感じ。
もう少しインテリジェンスに作って欲しい。
あと、RCPT TOに対してエラーを返すとフリーズする奴もいる。
250 OK が返ってこないと何をしていいのか解らないらしい (^_^;
結局タイムアウトで接続を切っているが、それまでフリーズしてやがるからタチが悪い。
エラー処理はちゃんと入れておいて欲しいもんだ。
で、こんな奴らが大量に来るのを捌かなければいけない。
結局やった事はDBコネクションのパフォーマンス改善。
まずはPostgreSQL側の同時接続数を可能な限り増やしてやる。
ただ、サーバーはそれなりに古いのでメモリーはそんなに多くない。(と言うかマザーボードが対応しきれない)
と言う事でシェアードメモリーがそんなに確保できないので、たいして同時接続数は増やせなかった。
困った...
続いて考えたのはPostfix側が適宜接続を切ってくれないかなという事。
Postfixのsmtpdはプロセスがデフォルトで100個まで立ち上がる。
こいつらがコネクションプールを使ってPostgreSQLと繋がったままで居ようとするので溢れてきてしまう。
ただ、大量にメールが届く状況でコネクションのOPENとCLOSEを繰り返すのはオーバーヘッドが大きいだろうから現実的では無さそうだし、いちいち接続を切るような設定が出来そうにもなかった。
とりあえず急場しのぎでプロセスの最大数を減らしてみたが効果は薄かった。
あれこれ対応策を探しているうちにPostfixにPROXYMAPなる機能が有る事が分かった。
PROXYMAPを使うとプロセス一個一個がDBに接続するのではなくPROXYMAPが一括してDBに接続してクエリーを実行し、それぞれのプロセスに結果を返してくれるのでDBへの同時接続数を劇的に減らしてくれるらしい。
と言う事で設定をしてみた。
元々
virtual_mailbox_maps = pgsql:/etc/postfix/pgsql-virtual_maps.cf
となっている所を
virtual_mailbox_maps = proxy:pgsql:/etc/postfix/pgsql-virtual_maps.cf
とするだけでOK。
PROXYMAPを使って動かしてみると、プロセス数のMAXはデフォルトの100個になっていてもPostgreSQLへの接続は10個くらいが動いているだけ。
それでも問題なく捌いてくれている。
相変わらずログをtailするともの凄い勢いで流れていて文字は判読できないけど...
と言う事で、これで解決かなと思っている。
(2時間程流しているけどビジーは出てない)