最新 追記

おこたの国


2007-05-18

_ [COMP] spam 対策 — qmail-smtpd 改造編

前回の続き。連休中に spamd を OpenBSD 4.1 のものに換装するつもりだったんだけど、知り合いの別荘に行ったりして遊び惚けたので頓挫。簡単にできるってことで、もっぱら qmail-smtpd に手を入れる事に終始してた。つごう、3回ほど変更をいれた結果、今では日に数通しか通過してこなくなった。

前回にも載せた、通過してくる spam の数*1、今回はグラフにしてみた。

[spam通過数グラフ]

元は 500 から 600 ほど通過してきてたことを考えると、この一ヶ月で数百分の一にできたともいえる。

[spam通過数グラフ(全)]

badheloarg

mfcheck の真似をして、badheloarg というのをでっちあげた。spam の HELO, EHLO の引数は実にいいかげん。特に、自分の FQDN ではなく、こっちのホスト名やらアドレスを入れてくるのが大半である。これらのいい加減な HELO をほざく相手を reject する。

mfcheck と同じく、HELO の引数として弾くものを /var/qmail/control/badheloarg というファイルに入れておくだけ。ここに、localhost.localdomain だとか自前のサイトのホスト名や MX に使ってる名前をいれておく。

さらに、ピリオドがひとつもないものも一律弾く。rfc2821 的に正しい FQDN や [アドレス] な形式であれば、必ずピリオドが入ってるはずだからね。IPv6 なアドレスはどうよ? てな部分は残るんだけど、qmail 自体が IPv6 非対応だからよしとする。

4/28 にリリース。グラフ見てわかるとおり、効果は絶大。ほぼこれだけで半減してる。

rcptusers

qmail は、RCPT TO に指定されたアドレスのローカルパートが有効なものであるかを SMTPセッション中にチェックできない。「そんなユーザーはいないよ」エラーは、一旦受け取った後、エラーメールとして送信するしかない。これが、qmail の一番の弱点である。

もちろん、これに関しては山ほどパッチが作られている。有効なアドレスをファイルに書いておく小規模なものから、外部の ldap を見に行く大規模なものまでよりどりみどり。が、毎度のことながら、気に入るものがなかったので自前で実装した。

これまた mfcheck 同様に、有効なローカルパートのみを rcptusers に書いておくというパターンの仕組みである。user-default と書いておけば「user-なんちゃら」の拡張アドレスはすべて受け入れる。

5/4 に、テストを終えた rcptusers 版をリリース。最初 rcptusers には noroi-default を書いていたのだが、翌日拡張アドレスをすべて書き連ねたものに置き換えた。かなり効果がある。あたりまえだ。今までは存在しないアドレスもすべて喰っていたのだ。

さらに、セキュリティホールmemofree-memoconnect24h の各メーリングリスト用アドレスを変更した。これらの ML のウェブアーカイブは、個々の記事のメールアドレス部分が隠蔽されてなかった時期がかつてあり、その頃収集されてしまったアドレス宛の spam が今でも山のように来るからだ。

そんなこんなで、5/4 以降なだらかに減っているのは、ちょこまか直しを入れていたから。

greet pause

いまさらだけど実施。これが5/11。

qmail-smptd のログを眺め続けた結果、tcpserver が接続を受けてから qmail-smtpd を起動するまで時間がかかることがあるのに気づく。そんな場合に、送信をあきらめてしまう接続が結構あるのだ。知識として greet pause で spam を 8割抑えられることはわかってるつもりだったんだけど、ここにきてようやく実感したわけだ。

tcpserver が qmail-smtpd を起動するまで時間がかかる「ことがある」ってのは、ident を引いてるから。これのタイムアウトが 26秒。RST が返ったり ident が引けちゃったりもするので、遅延がある場合とない場合ができてしまう。そこで、tcpserver に ident 引かせるのを止め、qmail-smtpd で一律 26秒待たせることにした。いやはや弾ける弾ける。まぁ、greet pause してなくても、他の対策に引っかかるものばかりなんだろうけどね。

その後

ちなみにここまでで、marunouchi.tokyo.ocn.ne.jp はほぼ撲滅できた。あ、いや、5/9 に一通通り抜けてきてるな。まぁ、やり方の違う業者なんだろうね。甘い ISP には spam 業者が群がってるだろうし。

badheloarg を実施している内部的な関数 helocheck() には手を入れ続けている。引数がアドレスでなければ名前を引き、nxdomain なら reject するところまでは既に取り込んでいる。が、ここまで減ってるとあまり効果は見えてこないんだな。

その他にも、接続元が逆引きできないなら、引数は FQDN じゃなくアドレスであるべきだし、アドレスは bracket で括られてないとおかしいし、A RR は接続元と一致するものが含まれてないとおかしいし…てな部分はチェックだけしてログに残して様子を見ている。これらの理由で reject する根拠があまりないのと、connect24h ML や harden-mac ML が使っている FreeML のように、spammer じゃないのにちゃんとした FQDN を送ってこれない間抜けなところがあるので、reject できないのだ。まぁ、本気でおかしなヤツらは、たいてい後段で別のチェックに引っかかって reject されてるから、いいんだけど。

*1 実は、これには自分以外のアドレスへの spam の数は含まれてない。bounce してくるのを見るに、たぶん今でも日に数通あると思うんだけど、spam かどうか判定する方法がないので、含めようがないのだ。


2002|10|
2003|10|12|
2004|01|06|07|08|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|11|12|
2006|01|02|03|04|05|06|07|08|09|10|11|
2007|01|02|03|04|05|06|07|08|09|10|11|12|
2008|01|02|03|05|07|08|09|10|11|12|
2009|02|06|08|09|
2010|02|08|
2011|08|
2012|07|
2013|01|06|09|10|
2019|07|10|
2020|07|