研究室のメールサーバがあふれました

今週頭ぐらいからメールサーバが頻繁にトラブルを起こします。
新しいメールを受信できなかったり、逆に送信できなかったり。
直接の原因はHDDがいっぱいになることでした。
火曜に一度復旧したので油断していたのですが、今日また同じような障害が発生してしまいました。
仕方ないので場当たり的な処理ではなく、根本的な原因を探ることに。
いろいろ調べた結果、結局根本的な原因はとあるOBの転送設定。
以下公開できる範囲で原因と対策のレポート

何となく時系列順に書いてるので技術読み物としてお楽しみください。
なお、今まさにメールサーバのHDDがあふれていててっとり早く対処がしたい人は次のエントリをご参照ください。
技術面だけ要約してあります。

最初の障害

火曜日の午後から一切のメールが届かなくなる。
単にメールが来ていないだけかと思っていたところ、どうもメールサーバのHDDが一杯だった模様。
正確には /var/mailが大きすぎて/varのパーティションの使用率が100%になっていた。
深夜で自分は気付かなかったのだが、スタッフの先生が対処してくれた。
具体的には、容量に余裕のあった/homeのパーティションに/var/mailの内容を移動し、/var/mailからシンボリックリンクを張っていた。この対策により, /var/mailがこの時点の倍ぐらいに膨れても大丈夫になる。

第2の障害(兆候編)

今回の障害は自分が知る限りはじめてのケースだったので、翌日、簡単に原因究明。
/var/mailの中にある各ユーザのメールのサイズを調査。
ある1人が5Gぐらい使い込んでいることに気づく。
面識のあるOBだったので直接連絡をとり確認。(以下P氏。もちろん本名ではない)
自分「メールボックスが5Gぐらいになってるけど心当たりありますか?」
P氏「ないなあ。でもすぐには確認とれないから、急ぐんだったら古いメールは消してよいよ」
一応確認も取れ、この時点では容量に差し迫った危機はなかったため、とりあえず放置。
なんかあったらまた見ればいいや、ぐらいの気分だった。
だが、思えばここでもう少し考えておくべきだったのである。
そうすれば今こんな苦労もしなくてすんだのに・・・。

第2の障害(発生編)

今日の昼過ぎ(風邪気味で鼻詰まりがひどく寝不足のため最近は重役出勤)に研究室に来ると、いきなり秘書さんに「メールが送れないし届かないんだけど」と泣きつかれる。
すぐ原因に思い至りサーバを確認。
/homeがDiskFullになったのではないかと思ったが、今回も/varの使用率が100%になっていた。
今度は/var/mailではなく、/var/spool、特にその中のincomingキューが/varの容量を圧迫していた。
ちなみに/var/mail(実体は/homeのパーティションにある)もサイズは増えていたが、/homeにはまだ余裕があった。
ここでようやく、根本原因をつぶさないとだめだと気付く。

原因と対策

思いついた原因は以下の3つ

  1. P氏のアカウントが攻撃を受けている
    愛憎だか私怨だか愉快犯だか知らないがメールボムが届いてる
  2. P氏のアカウントを含む無限ループができている
    転送設定のミスでどっかのアドレスと相互に転送し合っているとか。
  3. P氏のアカウントがspamのFrom行として詐称されている
    所謂backscatter。宛先不明のエラーメールが大量に来てるとか。

 
そんな仮説を抱きつつ、8GB近いメールキューを mailqコマンドで眺めてみると、3つのメールアドレスの組み合わせが大量に目についた。
1つはP氏のメールアドレス。もう1つはMAILER-DAEMON。そして最後は初めて見るアドレスだったが、ユーザ名がP氏を連想させた。
この時点で2つ目の可能性が濃厚。P氏に確認のメールを入れつつ、彼のアカウントを停止。とりあえず被害の拡大を食い止める。
 
続いてメールサーバの復旧を目指す。
とりあえずあふれているメールキューをどうにかしなければいけない。
先生と相談しつつ、原因となっているメール群の削除を試みる。
具体的な手順は以下の通り。

  1. mailqコマンドでキューのIDを確認
  2. grepとかsedとかawkで問題となるメールのIDを抽出
  3. postsuperでキューを削除

 
使ったコマンドは以下のとおり

#mailq |tee mailq.log
#grep MAILER-DAEMON$ mailq.log | grep Dec | awk '{print $1}' | sed 's/\*//g' | postsuper -d -
#grep P氏のメールアドレス$ mailq.log | grep Dec | awk '{print $1}' | sed 's/\*//g' | postsuper -d -

 
1行目
まずmailqでキューID他の情報を出力(teeを使っているのは出力と同時に目視で原因究明をしていたから)
 
2行目
(原因がわかったので)P氏発のメールキューを一斉削除。
mailqの出力は

-Queue ID- --Size-- ----Arrival Time---- -Sender/Recipient-------
XXXXXXXXXX 112 Thu Dec 11 hh:mm:ss foo@example.org
bar@example.net

みたいになるので、grep DecでIDがある行を抽出し、awkでID(第1要素)を出力。
また、なぜかたまに 00000000* とIDの末尾に*がつく出力があり、こいつらがエラーになったのでsedで*を除去。
そして postsuper -d (キュー削除コマンド)に渡してキューを削除。
 
3行目
MAILER-DAEMONについても同様。
 
そして現在目下作業中。。。
もしかしたら続くかも。