カテゴリー: qmail

qmailの大量キューを送信元や送信先でフィルターして削除する方法

qmail!?って思われるかもしれないですが、勉強会とかいくと結構現役なサーバって多いみたいです。

以前、qmailの大量キューをすべて削除するという記事でqmailのキューをすべて削除する方法を書きましたが、実際の運用では削除すべき大量のメールキューの中に、削除してはいけないキューがあったりします。
今回はqmailの大量キューを送信元や送信先でフィルターして削除する方法を検証しました。

ツール類の準備

下記2つのキュー操作ツールを利用します。
両方サーバーに入れます。
両方、perlのスクリプトなので任意の場所において実行権限を付与したりパスを通したりして下さい。

・qmHandle
http://qmhandle.sourceforge.net/

tar zxvf qmhandle-1.3.2.tar.gz

・queue-fast
http://www.kawa.net/works/qmail/queue-fast.html

wget http://www.kawa.net/works/qmail/src/queue-fast.20050210.tar.gz
tar zxvf queue-fast.20050210.tar.gz
chmod 755 queue-fast.pl

送信先メールアドレスでフィルターして削除

queue-fastのみで対応可能です。

キューの確認

perl queue-fast.pl

user@domain.name宛のキューを確認

perl queue-fast.pl user@domain.name

user@domain.name宛のキューを削除
キューの削除の際はqmailを落としてください。(キューの整合性が取れなくなる可能性がある為)

perl queue-fast.pl -d user@domain.name

送信元メールアドレスでフィルターして削除

queue-fastとqmHandleを組み合わせて使います。
※厳密には送信元だけではなく送信先に含まれているものも削除されます

user@domain.nameというアドレスが関連したキューをすべて削除したい場合。
まず、queue-fastでuser@domain.nameに関連したキューのIDを一覧します。

perl queue-fast.pl | grep user@domain.name | cut -d" " -f1 | cut -d"/" -f2

qmHandle の引数にキューIDを渡してあげるとそのキューIDのキューを削除してくれます。

perl qmHandle -d22222

便利に使う為、適当なスクリプトを作成

qmailQueueDelete.sh

!/bin/sh
if [ $# -ne 1 ]; then
echo "\n"
echo "qmailQueueDelete.sh \n"
echo "usage : ./qmailQueueDelete.sh test@example.com \n"
exit 1
fi
QID=`perl queue-fast.pl | grep $1 | cut -d" " -f1 | cut -d"/" -f2`
for var in ${QID}
do
if [ ! -z "$var" ] ; then
perl qmHandle -d${var}
fi
done

qmailを停止してから、

./qmailQueueDelete.sh user@domain.name

で削除が実行されます。

qmailの大量キューをすべて削除する

qmailのキューを削除する方法。

原因はスパム、ループ、メール送信テスト、とかでキューがあほほどたまってしまう事があります。
そんな時のキュー削除方法。

一般的なキュー削除方法

一般的には以下の方法でキューを削除します

・qmHandle
http://qmhandle.sourceforge.net/

・queue-fast
http://www.kawa.net/works/qmail/queue-fast.html

上記のツールは特定のToやFromのキューを削除するなどができて大変便利です、が、
実は単にすべてのキューを削除したい場合は以下のコマンドでOKです。

qmailを停止してから
# rm -f /var/qmail/queue/*/*/*

大量にキューがある時

あるサーバーにキューが120万件たまっていました。
キュー全削除の為に上記コマンドを実行しようとしたらこのエラーです。

# rm -f /var/qmail/queue/*/*/*
/bin/rm: 引数リストが長すぎます
もしくは
-bash: /bin/rm: Argument list too long

こういう時はxargsというコマンドを行うとよい。

echo /var/qmail/queue/*/*/* | xargs rm

ただ、上記でも多すぎるとエラーになる時があって以下のシェルスクリプトを作ってみました。
さすがにこんだけ細かくしてやれば削除できるだろうと・・・。(120万件はうまくいきました)

queue_del.sh
https://gist.github.com/4653448

すごい力技。。
forくらい使わないとって感じだけど検証も面倒なのでこれでOK。

qmailでbackscatter対策を行う

qmail環境でのbackscatter対策について。

以下のページを参考しました。
Stray Penguin – Linux Memo (qmail) – http://www.asahi-net.or.jp/~aa4t-nngk/qmail.html

qmailではローカル配送時に「存在しないメールアドレス」だった場合に
「正常にメールが配信できなかった」旨を送信元へ連絡します。

[code]
(例)
①メールサーバーAはhoge.comというドメインのメールアドレスを管理している

②abcde1234@hoge.com など、存在しないメールアドレス宛にメールが送信されてきた

③メールサーバーAは「そんなメールアドレスないよ」と送信元へ通知(バウンスメール)
[/code]

メールアドレスを打ち間違えて送信した場合などにバウンスメールが返ってくると間違いに気づく事ができるなどメリットはたくさんあるのですが、スパム配信者など悪意ある送信者の場合、メールアドレスがあるかないかに関わらず手当り次第にメールを送ってくる事があります。

このようなスパム配信者の送信元メールアドレス(リターンパス)は基本的には偽装されており、実際には「存在しないメールアドレス」が設定されている事がほとんどです。メールサーバーAはバウンスメールの送信がタイムアウトになるまで接続を試みる状態となってしまい、結果、キューにメールが溜り続け、メールサーバーはサービスを提供できない状態となってしまいます。

最近ではスパム業者はわざと存在しないメールアドレスへ送信し、送信元やリターンパスを真に送信したいアドレスと設定する事で、バウンスメール送信させる事を目的としている挙動も見られました。このような攻撃をされた場合、最悪の場合はRBL(ブラックリストサーバー)などに登録される恐れもあります。

このように、メールの仕様を逆手にとった攻撃が「backscatter攻撃」で、非常にむかつく攻撃です。
この問題に対応するために行った様々な対策です。

[対策1 バウンスメールを返さない設定にする]

簡単な対策としては、バウンスメールをまったく返さないという設定とする事が考えられます。qmailでは.qmail-defaultというファイルで存在しないメールアドレス宛のメールの挙動を決定しています。存在しないメールアドレス宛のメールを破棄する場合は.qmail-defaultを以下のように編集します。以下の例はvpopmailにて管理してるバーチャルドメインでの.qmail-defaultの例です。

[code]
vi .qmail-default

| /var/vpopmail/bin/vdelivermail ” bounce-no-mailbox

| /var/vpopmail/bin/vdelivermail ” delete
[/code]

このように設定する事でバウンスメールでキューがたまってにっちもさっちもいかなくなる事はなくなりました。ただこの設定を行うと、宛先アドレスを入力ミスしただけの場合でもバウンスメールは帰ってこない為、メールが届いていないのに届いていると誤解されてしまう恐れもあるので、設定の際は注意して下さい。

[対策2 badmailfromで差出人のメールアドレスでsmtpの時点で拒否する]

上記の対策だけでメール破棄が行われてるわけですが、qmail的にはすべて受け取っている事と同じです。そのため

・スパム業者は「なんでもメールおくれるなーこのサーバー。どんどんやったれ」と思われてどんどん数が増えてくる
・配送を行うプロセスを踏むのでSMTP配送の負荷がかかり、ひどいときにはSMTPに遅延が発生しはじめた

という問題が出てきました。
そこでqmailへの配送前の時点で破棄するようなルールを設定しました。特にqmailの再起動をする必要もなく、以下のファイルを作成しメールの受信を拒否する発信元アドレスを記述するだけで設定できます。
[code]
/var/qmail/control/badmailfrom
[/code]
以下のような書き方を行うと特定ホスト(hogehoge.com)からのメールを拒否します
[code]
@hogehoge.com
[/code]

[対策3 差出人/送信先のメールアドレスを正規表現で設定しsmtpの時点で拒否する]

上記の対策2では送信元メールアドレスやホストが一定である必要があり、さまざまなメールアドレスからの送信されてきた場合はお手上げでした。また、[ランダム文字列@yahoo.co.jp]など、有名メールサービスのメールアドレスを詐称された場合、ドメイン単位での拒否を行う事はサービス上できないという問題も発生しました。

そこでqmailに新たな機能を追加する為にqregex というパッチを導入しました。このパッチでは以下の機能がqmailに追加されます。

qregex配布元 The Arda Network – http://www.arda.homeunix.net/index.html

[code]
・badmailfrom の送信元を正規表現で記述できる
・badmailto と呼ばれるbadmailfromの逆の動作(送信先で拒否)を行う機能が追加
・badmailto でも正規表現は記述可能
[/code]

送信元メールアドレスに比べて送信先のメールアドレスは基本的に特定のドメインに集中する為、大きな成果をあげる事ができそうです。

導入方法

以下のサイトからパッチを取得してqmailにパッチをあてます
[code]
cd /path/to/qmail-1.03/
wget http://www.arda.homeunix.net/store/old_software/qregex-20040601.patch
patch < qregex-20040601.patch
[/code]
この際、すでにsmtpd-authなどのパッチを充てていた場合はMakefileqmail-smtpd.cなどで競合が起きてパッチが正常終了しません。正常終了しなかった部分は*.rejというファイルが出力されますのでそちらを見ながら手動でソースを編集する必要があります。

修正が終わったらインストールを実行。すでにqmailが起動している場合は落としておいて下さい。
[code]
make clean
make
make setup
make check
[/code]
インストール後、qmailを起動したら以下のファイルへメールの受信を拒否する送信先アドレスを記述するだけで設定できます。
[code]
/var/qmail/control/badmailto
[/code]
[code]
[a-z]+[0-9]+@hogehoge.com
[/code]
例えば上記のように記述すると英字+数字@hogehoge.com という送信先のメールはすべてsmtp接続時点で拒否する事ができるようになります。またこのパッチを充てたことで[対策2]でお伝えしたbadmailfromも正規表現によるフィルタが可能となります。

最後に

qmailはシンプルでバグも見られずとてもよいMTAなのですがITの進歩と共に追加されてきた機能などを追加するときはどうしてもパッチのつぎはぎになってしまうのが難点ですね。

今回、qregexというパッチを使用しましたが、vpopmail環境の場合はchkuserパッチというものも存在し、こちらはsmtp時点でメールアドレスが存在するか確認できるパッチのようですのでまた検証してみたいと思います。

chkuser 2.0 – http://opensource.interazioni.it/qmail/chkuser.html

Postfixではデフォルトの機能でbackscatter対策が可能なようです

Postfix 後方散乱 Howto
http://www.postfix-jp.info/trans-2.1/jhtml/BACKSCATTER_README.html

© SEEDS Co.,Ltd.