http://www.gabacho-net.jp/anti-spam/log-sorting-script.html
S25Rスパム対策方式によって正当なメールサーバが誤って拒絶されているのを発見するのに有用なシェルスクリプトを紹介します。メールサーバがウェブサーバを兼ねているなら、このスクリプトをcgi-binディレクトリ配下のディレクトリにパスワード付きで置くことにより、ウェブブラウザで拒絶記録を容易に監視できます。コマンドとして実行することもできます
ということなので、早速スクリプト「s25r.cig」を
http://mail.smb.net/cgi-bin/s25r.cig
に置いて、アクセスすると・・・
[Thu Aug 23 08:26:18 2012] [error] [client 210.255.122.209] /usr/local/www/apache22/cgi-bin/s25r.cig: gawk: not found [Thu Aug 23 08:26:18 2012] [error] [client 210.255.122.209] /usr/local/www/apache22/cgi-bin/s25r.cig: gawk: not found [Thu Aug 23 08:26:18 2012] [error] [client 210.255.122.209] /usr/local/www/apache22/cgi-bin/s25r.cig: gawk: not found [Thu Aug 23 08:26:18 2012] [error] [client 210.255.122.209] /usr/local/www/apache22/cgi-bin/s25r.cig: gawk: not found [Thu Aug 23 08:26:18 2012] [error] [client 210.255.122.209] cat: /var/log/maillog.1: /usr/local/www/apache22/cgi-bin/s25r.cig: gawk: not found [Thu Aug 23 08:26:18 2012] [error] [client 210.255.122.209] Permission denied [Thu Aug 23 08:26:18 2012] [error] [client 210.255.122.209] cat: /var/log/maillog: Permission denied [Thu Aug 23 08:26:18 2012] [error] [client 210.255.122.209] /usr/local/www/apache22/cgi-bin/s25r.cig: gawk: not found [Thu Aug 23 08:26:18 2012] [error] [client 210.255.122.209] /usr/local/www/apache22/cgi-bin/s25r.cig: gawk: not found
というエラー(´・ω・`)なので、
hotshot# portinstall japanese/gawk hotshot# rehash
した。
HTTPデーモンの権限でメールログファイルが読めるようにアクセス権を設定してください。多くのシステムでは、以下のコマンドで設定できます。
chgrp nobody /var/log/maillog* chmod g+r /var/log/maillog*
したけど、なぜか無効なので
hotshot# chmod 644 /var/log/maillog*
した。
[Thu Aug 23 08:49:30 2012] [error] [client 210.255.122.209] /usr/local/www/apache22/cgi-bin/s25r.cig: gawk: not found [Thu Aug 23 08:49:30 2012] [error] [client 210.255.122.209] /usr/local/www/apache22/cgi-bin/s25r.cig: gawk: not found [Thu Aug 23 08:49:30 2012] [error] [client 210.255.122.209] /usr/local/www/apache22/cgi-bin/s25r.cig: gawk: not found [Thu Aug 23 08:49:30 2012] [error] [client 210.255.122.209] /usr/local/www/apache22/cgi-bin/s25r.cig: gawk: not found [Thu Aug 23 08:49:30 2012] [error] [client 210.255.122.209] /usr/local/www/apache22/cgi-bin/s25r.cig: gawk: not found [Thu Aug 23 08:49:30 2012] [error] [client 210.255.122.209] egrep: writing output: Broken pipe [Thu Aug 23 08:49:30 2012] [error] [client 210.255.122.209] egrep: writing output: Broken pipe [Thu Aug 23 08:49:30 2012] [error] [client 210.255.122.209] egrep: writing output: Broken pipe [Thu Aug 23 08:49:30 2012] [error] [client 210.255.122.209] egrep: writing output: Broken pipe [Thu Aug 23 08:49:30 2012] [error] [client 210.255.122.209] egrep: writing output: Broken pipe [Thu Aug 23 08:49:30 2012] [error] [client 210.255.122.209] egrep: writing output: Broken pipe [Thu Aug 23 08:49:30 2012] [error] [client 210.255.122.209] egrep: writing output: Broken pipe [Thu Aug 23 08:49:30 2012] [error] [client 210.255.122.209] egrep: writing output: Broken pipe [Thu Aug 23 08:49:30 2012] [error] [client 210.255.122.209] egrep: writing output: Broken pipe [Thu Aug 23 08:49:30 2012] [error] [client 210.255.122.209] egrep: writing output: Broken pipe [Thu Aug 23 08:49:30 2012] [error] [client 210.255.122.209] egrep: writing output: Broken pipe [Thu Aug 23 08:49:30 2012] [error] [client 210.255.122.209] egrep: writing output: Broken pipe
目次
あらまし
まとめ
付録A. Postfixでの設定方法
付録B. 拒絶記録抽出用スクリプト
オープンリレー(第三者中継)を行うメールサーバが少なくなり、最近では多くのスパマーが、ADSLやケーブルネットワークなどのエンドユーザー用高速回線につながってボットに感染したたくさんのエンドユーザーコンピュータからスパムを直接ばらまいている。オープンリレーブラックリストはもはや役に立っていない。有効なスパム対策は、メール中継サーバからのSMTPアクセスを受け入れる一方で、エンドユーザー用回線からのSMTPアクセスを拒絶することである。それらは、IPアドレスの逆引き名の特徴に基づいて識別できる。私はこの方式を使って、Postfix以外に何らの付加ソフトウェアも使うことなく、スパムとウィルスメールを合わせた不正メールの約99%を阻止することに成功している。
スパマーは、苦情の返信を避けるために、偽の送信者アドレスをかたることが多い。そこで、メッセージの送信者ドメインが実在しなければ拒否するという対策をとっているメールシステムがある。しかしスパマーは、罪のない他人の実在ドメインを悪用するという方法でこの防御を破っている。もちろん、罪のないドメインにスパムの差し戻しが殺到する。大迷惑である。
特定の語(たとえば「make money」)を含むメッセージを拒否するという対策がある。しかしスパマーは、語を変形させたり(「m-a-k-e m-o-n-e-y」のように)、無効なHTMLタグを語の中に挿入したり、本文全体をBASE64に符号化したりすることによって、この防御を破っている。
スパマーは、多量のスパムをばらまくために、インターネット上のメールサーバによるオープンリレーを悪用した。そこで、メールサーバでオープンリレーを禁止する対策が普及した。また、いくつかの組織がオープンリレーブラックリスト(ORBL)を提供して、そのデータベースに登録されたメール中継サーバからの受信を拒否するよう勧めている。しかし、ADSLやケーブルネットワークなどのエンドユーザー用高速回線が普及してからは、スパマーは、ボットに感染させたたくさんのエンドユーザーコンピュータを操ることによって、オープンリレーに頼ることなく多量のスパムを受信者のドメインへ直接ばらまいている。
このようなエンドユーザー用回線からスパムを受けて、そのIPアドレスをORBLサイトに入力すると、「それはオープンリレーサーバではない」という答えが返る。悪質なスパム送信コンピュータはSMTPアクセスを発するだけで受けようとはしないので、オープンリレーを行わないのは当然である。セキュリティの知識も悪意もないメールシステム管理者を摘発するORBLは、真の悪人には寛容と見える。やれやれ…。
SMTPアクセスをかけてくるクライアントのIPアドレスを検査するという方法もある。しかし、一つのIPアドレスをブラックリストに登録しても、スパマーはすぐに別のIPアドレスからスパムを送り込んでくる。かくしてブラックリストは際限なく肥大化する。
IPアドレスブロック(「223.45.67.*」のような)、または逆引きで得られたドメイン名(「*.example.com」のような)をブラックリストに登録することもできる。しかし、正当なメールが巻き添えを食らって阻止されてしまうかもしれない。
結局、メールシステム管理者は、メール爆弾を受けた時以外にはこの方法を使いたいとは思わないだろう。私のアイデアまであと一歩なのだが…。
私が考案したSelective SMTP Rejection (S25R)スパム対策方式のコンセプトは、メールサーバがメール中継サーバからのSMTPアクセスは受け入れるがエンドユーザーコンピュータからの直接のSMTPアクセスは拒絶するという単純なものである。
正当なメールのほとんどは、ISP(インターネットサービスプロバイダ)や組織のメール中継サーバを経由して送られてくる。一方、昨今のスパムのほとんどは、ADSLやケーブルネットワークなどのエンドユーザー用回線につながってボットに感染したエンドユーザーコンピュータから直接送られてくる。メール中継サーバを経由して送られてくるスパムは、比較的少なく抑えられる。サーバの処理能力がボトルネックになるからである。
また、昨今のウィルスには、自前のSMTPエンジンを持って、エンドユーザーコンピュータから自分の分身を宛先ドメインへ直接ばらまくものが多い。メール中継サーバを経由して送られるウィルスは、もしメール中継サーバがウィルス対策ゲートウェイを持てばそこで阻止される。
これらのことから、メール中継サーバからのメールだけを受け取るというポリシーによって、スパムやウィルスメールの受信を減らすことができる。
SMTPアクセスをかけてきたクライアントがメール中継サーバかエンドユーザーコンピュータかを判別することは非常に難しいと思えるかもしれない。しかし私は、意外なほど簡単な方法を思い付いた。次節に述べるように、IPアドレスの逆引きで得られるFQDN(Fully Qualified Domain Name:完全修飾ドメイン名)の特徴を見るのである。それは、Postfixを使って容易に実現できる。
この判別は、外からのメールの入り口であるMX(Mail eXchanger)の役割を担うメールサーバが行うのがよい。すなわち、MXは、メッセージを検査する前に受け取ってしまうのでなく、スパムの疑いのあるメッセージを拒絶するのがよい。スパマーのコンピュータは、メッセージ内容を伝送する前に、失敗の意味の応答コードを突き返される。したがって、インターネット上の無駄なトラフィックが減る。また、ドメイン名を偽の送信者アドレスに悪用された被害者に殺到する不正な差し戻しも少なくなる。一方で、拒絶の際に「後で再試行せよ」の意味の応答コードを返すことにより、誤って阻止される正当なメール中継サーバを見つけてそれを救済することができる。もしこのスパム対策方式がインターネットに普及したら、スパマーは、スパムの配信が片っ端から失敗することを思い知るだろう。
SMTPアクセスをかけてきたクライアントのFQDNの特徴に基づいて、クライアントがメール中継サーバか、エンドユーザー回線につながったコンピュータかを推定することができる。この方法でクライアントを制限するための規則は、一般規則、ブラックリスト、およびホワイトリスト(許可リスト)から成る。一般規則は、大多数のエンドユーザー用回線を引っかける。ブラックリストは、一般規則に引っかからないエンドユーザー用回線を引っかける。また、悪質なメール送信サーバも引っかける。ホワイトリストは、一般規則またはブラックリストによる誤った拒絶から正当なメール中継サーバを救済する。これは完璧な方法ではありえないが、きわめて有効な方法である。
うまく管理されているメール中継サーバのほとんどは、逆引きで得られるFQDNを持つ。IPアドレスが逆引きFQDNを持たなければ、ダイヤルアップ、ADSL、ケーブルネットワークなどのエンドユーザー用回線であることが多い。メール中継サーバよりもエンドユーザー用回線の方がはるかに多いからである。したがって、逆引きFQDNのないIPアドレスからのSMTPアクセスは、少しの例外を除いて拒絶すればよい。
エンドユーザー用回線のIPアドレスにも、逆引きFQDNを持つものがかなり多い。しかし、その逆引きFQDNには、メール中継サーバの名前とは違った特徴がある。エンドユーザー用回線の逆引きFQDNは、多くのIPアドレスへの名前の割り当ての便宜のために、比較的多くの数字を含むことが多い。一方、メール中継サーバの名前は、ネットワーク管理者は誰でも覚えやすい名前を好むから、通常、数字をあまり含まない。そこで、正規表現を使うことによって、エンドユーザー用回線の逆引きFQDNとメール中継サーバの逆引きFQDNを区別することができる。エンドユーザー用回線と推定されたIPアドレスからのSMTPアクセスは、少しの例外を除いて拒絶すればよい。
私が作り上げた拒絶用の一般規則を以下に説明する。これは、逆引きFQDNのないクライアントを拒絶する規則に加えて、クライアントのFQDNを検査するわずか6個の正規表現から成る。この規則は、メール中継サーバのFQDNを引っかけることが少ないように工夫されている。
逆引き失敗の意味は、IPアドレスからFQDNを検索できないことだけでなく、逆引きFQDNの順引きの結果が元のIPアドレスに一致しない場合も含んでいる。
逆引きが失敗するホストの大多数はエンドユーザーコンピュータである。インターネットにはエンドユーザーコンピュータの方がメールサーバよりはるかに多いので、当然である。
例: 220-139-165-188.dynamic.hinet.net evrtwa1-ar3-4-65-157-048.evrtwa1.dsl-verizon.net a12a190.neo.rr.comPostfixの正規表現: /^[^.]*[0-9][^0-9.]+[0-9].*\./
エンドユーザー用回線のFQDNの中には、この規則に引っかかるものが最も多い。私はこの規則に引っかかるメール中継サーバをいくつか見つけているが、さほど多くない。 正規表現の末尾にある「\.」は、ドットにマッチする。これは、あらゆるIPv6アドレスを引っかけないために必要である。
例: YahooBB220030220074.bbtec.net pcp04083532pcs.levtwn01.pa.comcast.net Postfixの正規表現: /^[^.]*[0-9]{5}/
私は末端ホスト名に最大で4個連続する数字を含むメール中継サーバを見つけたことがあったので、5個以上連続する数字を引っかけることにした。その後、末端ホスト名に5個以上連続する数字を含むメール中継サーバを見つけているが、それらはごく少ない。
例: 398pkj.cm.chello.no host.101.169.23.62.rev.coltfrance.com Postfixの正規表現: /^([^.]+\.)?[0-9][^.]*\.[^.]+\..+\.[a-z]/
「smtp.246.ne.jp」(実在する)のようなFQDNを引っかけないように、上位3階層を検査から除外することにした。
正規表現の末尾にある「\.[a-z]」は、トップレベルドメイン名の先頭にマッチする。これは、あらゆるIPv4アドレスのドット付き十進表記を引っかけないために必要である。
例: wbar9.chi1-4-11-085-222.dsl-verizon.net m226.net81-66-158.noos.fr Postfixの正規表現: /^[^.]*[0-9]\.[^.]*[0-9]-[0-9]/
「mail1.1-2-3.co.jp」(ドメイン名は実在、末端ホスト名は架空)というFQDNはこのルールに引っかかる。しかし、上位3階層を検査から除外することにはしなかった。そうすると見逃されるエンドユーザー用回線があるからである。
例: m500.union01.nj.comcast.net d5.GtokyoFL27.vectant.ne.jp Postfixの正規表現: /^[^.]*[0-9]\.[^.]*[0-9]\.[^.]+\..+\./
「mail1.number1.co.jp」(ドメイン名は実在、末端ホスト名は架空)のようなFQDNが引っかからないように、上位3階層を検査から除外することにした。「mail1.gate1.example.co.jp」というFQDNはこのルールに引っかかってしまうが、そのようなFQDNを持つメール中継サーバはまれである。
例: dhcp0339.vpm.resnet.group.upenn.edu dialupM107.ptld.uswest.net PPPbf708.tokyo-ip.dti.ne.jp dsl411.rbh-brktel.pppoe.execulink.com adsl-1415.camtel.net xdsl-5790.lubin.dialog.net.pl Postfixの正規表現: /^(dhcp|dialup|ppp|[achrsvx]?dsl)[^.]*[0-9]/
この規則だけに引っかかるFQDNはわずかに存在する。このような末端ホスト名を持つメール中継サーバはまずない。
付記 2007年9月に正規表現の「adsl」の部分を「[achrsvx]?dsl」に変更した。
メールサーバがこれらの規則によってSMTPアクセスを拒絶する時は、「後で再試行せよ」を意味する応答コード「450」を返すべきである。そうすれば、これらの規則のいずれかに引っかかる正当なメール中継サーバを、後で述べるホワイトリスト(許可リスト)を作ることによって救済することができる。
付録A.は、これらの規則を後述のブラックリストおよびホワイトリストと共に設定するためのPostfix用設定ファイルを示している。
ブラックリストは、前述の一般規則をすり抜けるエンドユーザー用回線を拒絶するために用いる。また、悪質なメール送信サーバを拒絶するためにも用いる。
一般規則をすり抜けるFQDNの特徴には次のものがある。
私は「ACBBD419.ipt.aol.com」というFQDNを発見したことがある。人の目で見れば、この末端ホスト名は十六進番号を示していると推測できるが、このFQDNは一般規則をすり抜ける。8桁の十六進番号の約96%は一般規則のルール1または2のいずれかに引っかかるが、約4%はいずれもすり抜ける。
IPアドレスの十六進表記を含むホスト名を一網打尽にするためには、「/^[^.]*[0-9a-f]{8}/」という正規表現を一般規則に追加することを考慮してもよい。ただし、もしそうするなら、「rapidfeed1」が引っかからないのになぜ「speedfeed1」が引っかかるのかと不思議がってはいけない。
私は「user-0cetcbr.cable.mindspring.com」および「user-vc8fldi.biz.mindspring.com」というFQDNを発見したことがある。ランダムに見える英字は、おそらく番号を示している。これらの例は一般規則をすり抜ける。
数字を含まないFQDNを持つホストからスパムを受けたことがある(そのFQDNは「host.example.co.uk」と同じ構文であった)。そのホストはSMTPアクセスを受け付けなかったので、スパム送信専用と思われた。私は、そのドメインの配下のホスト名をいくつか調べて、そのドメインはユーザーの好きなホスト名を割り当てていると推測した。このようなサービスを利用するスパマーは、一般規則をすり抜けることができる。
ISPのドメインをブラックリストに登録する時には、そのドメイン内のメール中継サーバを拒絶しないように注意する必要がある。たとえば「ACBBD419.ipt.aol.com」というFQDNから作る拒絶用の正規表現は、サブドメイン名を含めた「/\.ipt\.aol\.com$/」がよいだろう。「user-0cetcbr.cable.mindspring.com」および「user-vc8fldi.biz.mindspring.com」の場合は、共通の部分文字列を含めた「/^user.+\.mindspring\.com$/」がよいだろう。
特定のホストを拒絶したい場合は、正規表現を「/^host\.example\.com$/」のように記述すればよい。もしそのドメイン全体が疑わしいと判断したならば、「/\.example\.com$/」のように記述してもよい。
ホワイトリスト(許可リスト)は、一般規則またはブラックリストに引っかかる正当なメール中継サーバを救済するために必須である。ホワイトリストは一般規則およびブラックリストの前に指定しなければならない。
正当なメール中継サーバに対する拒絶の記録は、メールログから発見される。こちらのメールサーバが、一般規則またはブラックリストで拒絶する時に応答コード「450」を返せば、正当なメール中継サーバは送信を数日間にわたって再試行する。もし拒絶の記録が1分以上の間隔で同じクライアントIPアドレス、HELOアドレス、送信者アドレス、および受信者アドレスを示していたら、正当なメール中継サーバからのアクセスかもしれない。クライアントは正当なメール中継サーバであると判断した時は、ホワイトリストに許可条件を登録することによってそのメッセージを受信することができる。スパム送信コンピュータとウィルスのほとんどは、再試行しないか、あるいは数秒間隔でしばらくの間再試行する。正当なメール中継サーバと同様に再試行するには、多くのコンピュータリソースを消費するからである。
参考までに、Postfixは、クライアント制限によって拒絶しなければならないことがわかっていても、クライアントにHELOコマンド、MAIL FROMコマンド、およびRCPT TOコマンドを送信させてから蹴飛ばすのがデフォルトの動作になっている。この動作のおかげで、拒絶されたメッセージの送信者アドレスと受信者アドレスとHELOアドレスがログからわかる。
正当なメール中継サーバからのアクセスが拒絶されるケースは次のとおりである。
逆引きFQDNを持たないメール中継サーバがいくらかある。
逆引きFQDNからの順引きで複数のIPアドレスが得られることがまれにある。このような場合、Postfixは、順引きされた最初のIPアドレスが元のIPアドレスに一致しない限り、逆引き失敗と判断してしまう。
一般規則に引っかかるホスト名が少しある。実例として、私が「hotmail.com」ドメインのユーザーへ送ったメッセージの差し戻しが「mc1-s3.bay6.hotmail.com」という名前のホストから送られてきた。
小規模の組織、個人インターネットサイト、およびメールマガジン配信業者が安いエンドユーザー用回線を利用してメールサーバを運用することがある。メールサーバは独自のドメイン名を持っていても、回線の逆引きFQDNはISPによって管理されており、それが一般規則に引っかかる。
逆引きFQDNを持つIPアドレスは「/^223-123-45-67\.example\.net$/」のような正規表現によって、また、逆引きFQDNを持たないIPアドレスは「/^223\.123\.45\.67$/」のような正規表現によって許可することができる。
エンドユーザー用回線を利用しているメールサーバは、固定IPアドレスを持つ限りは、上述の方法で安全に許可することができる。しかし、浮動IPアドレスとダイナミックDNSを使うメールサーバを救済することにはリスクが伴う。なにしろ、ある時にそのメールサーバに割り当てられたIPアドレスが、別の時にはボット感染したコンピュータに割り当てられるかもしれないではないか。そのようなメールサーバは、ISPのメール中継サーバを経由してメールを送り出すか、さもなければ固定IPアドレスサービスに切り替えてほしい。
クライアント制限によってほとんどのスパムが引っかかるが、それをすり抜けるスパムも少しある。それを引っかけるために、ほかのメールフィルタが役立つことがある。
HELOコマンドはクライアントホストのFQDNを名乗らなければならないのに、スパム送信プログラムやウィルスの中には、HELOコマンドで宛先ホストのIPアドレスまたは受信者のドメイン名を通知するものがある。正当なメール中継サーバは、ウィルスに冒されない限り、決してそんな動作はしない。他ネットワークのクライアントが、あなたのメールサーバのIPアドレスまたはあなたのドメイン名をHELOコマンドで通知したら、躊躇なく「致命的エラー」の応答コードを返して蹴飛ばしてよい。
このような不正な動作をするSMTPエンジンを作る奴は、SMTPの決まりを知らないのだろう。不正メールを判別する手がかりを自ら提供するとは馬鹿だね。
参考までに、PostfixでHELOコマンドの検査に基づいて拒絶するには、キーワード「REJECT」を指定する必要がある。応答コード「450」を返すことによってクライアントにメール送信を再試行させることはできない。
送信者ドメインの実在をDNSで検査することは、従来から行われている方法である。昨今のスパムの多くは実在のドメインを悪用しているので、このフィルタが役立つことは少ないが、設定しておく価値はなおもある。
参考までに、Postfixは、送信者ドメインの検査に基づいて拒絶する時には、デフォルトで応答コード「450」を返す。ドメイン名が実在してもDNS検索が一時的に失敗することがあるので、このデフォルトを変えてはならない。
メールヘッダおよびメッセージ本文を検査してスパムにありがちな語を見つけるというのも、従来から行われている方法である。これはたまに役立つことがある。しかし、スパマーはすでに、内容の検査をすり抜けるためのたくさんの方法を編み出しているので、内容の検査のフィルタをメンテナンスする労力は引き合わない。
参考までに、Postfixでメールヘッダおよび本文の検査に基づいて拒絶するには、キーワード「REJECT」を指定する必要がある。応答コード「450」を返してクライアントにメール送信を再試行させることはできない。
2004年4月の1ヶ月間に私のメールサーバへ来た、スパムとウィルスメールを合わせた不正メールの阻止率の統計を示す。阻止率は、アクセス元のIPアドレス567個に対する割合で示している。
クライアント制限の一般規則のルール2から6による阻止率の増分は、それぞれの規則に引っかかったアクセスすべてではなく、それよりも前の規則をすり抜けてからその規則に引っかかったものの割合を示している。ブラックリストによる阻止率の増分は、ブラックリストで引っかかったアクセスすべてではなく、一般規則で引っかけることができなかったものの割合を示している。HELOコマンドの検査による阻止率の増分は、クライアント制限をすり抜けてからこの検査で引っかかったアクセスの割合である。
クライアント制限および併用したほかの対策によって阻止できなかったメッセージは5件(0.9%)であった。そのうち4件は宛先誤りであった。受信してしまったのは1件で、それは、正当な企業のメール中継サーバから送られてきたスパムであった。メール中継サーバがボットに感染していたと思われる。
一方、この期間中に正当なメッセージに対する拒絶を何度か発見して、ホワイトリスト項目を5個追加することによってそれらすべての受信に成功した。
2004年4月末時点で、私のブラックリストの項目数は17個、ホワイトリストの項目数は9個であった。
表1. 私のメールサーバでの不正メール阻止率の統計(2004年4月)
拒絶条件 | 適合率 | 阻止率増分 | 阻止率累計 |
[ルール0]逆引き失敗 | 38.4% | 38.4% | 38.4% |
[ルール1]逆引きFQDNの最下位(左端)の名前が、数字以外の文字列で分断された二つ以上の数字列を含む | 44.5% | 44.5% | 82.9% |
[ルール2]逆引きFQDNの最下位の名前が、5個以上連続する数字を含む | 10.2% | 7.6% | 90.5% |
[ルール3]逆引きFQDNの上位3階層を除き、最下位または下位から2番目の名前が数字で始まる | 12.3% | 6.5% | 97.0% |
[ルール4]逆引きFQDNの最下位の名前が数字で終わり、かつ下位から2番目の名前が、1個のハイフンで分断された二つ以上の数字列を含む | 3.4% | 0.9% | 97.9% |
[ルール5]逆引きFQDNが5階層以上で、下位2階層の名前がともに数字で終わる | 8.5% | 0.3% | 98.2% |
[ルール6]逆引きFQDNの最下位の名前が「dhcp」、「dialup」、「ppp」、またはDSL系の名前で始まり、かつ数字を含む | 7.6% | 0% | 98.2% |
ブラックリストに登録されている | 2.6% | 0.5% | 98.7% |
HELOコマンドが宛先サーバのIPアドレスまたは受信者のドメイン名を通知している | 9.3% | 0.4% | 99.1% |
送信者ドメインの検索失敗 | 不明 | 0% | 99.1% |
内容の検査 | 不明 | 0% | 99.1% |
私は、個人用メールサーバを使って、自分のリスク負担でS25Rスパム対策方式を開発した。組織やISPなどの大規模サイトがこの方式を導入する時には、運用においてリスクをコントロールすることが重要な課題になる。
メールシステム管理者がスパムに対していかに強く怒りに燃えていても、私のようにスパムの阻止率を100%に近付けることに血道を上げたりはしない方がよい。一人のユーザーが、あるホストからスパムを受けたと申告したとしても、同じホストから正当なメールも来るかもしれない。ブラックリストにホストを登録する前に、スパム被害の実態とクライアントホストの挙動を慎重に調べるべきである。
それよりも、受けなければならないメールを受信者が受けられないというリスクを避けることの方が重要である。正当なホストが再試行するのをほったらかすことは許されない。私は、メールログから拒絶の記録を抽出するスクリプト(付録B.参照)を使って拒絶の記録を監視しながらホワイトリストを作っている。また、私は、規則的な再試行を見つけやすくする改良型のスクリプトも作った。大規模サイトではこれが有効であろう。
少しのスパムが誤って許可されてしまうリスクを許容できるなら、ホワイトリストのメンテナンスを自動化することもできる。S25R方式のある導入者は、ホワイトリスト登録の自動化システムを開発した。また、S25R方式をグレイリスティング(再試行するホストを許可する方法)またはタールピッティング(応答遅延)と組み合わせることによって正当なホストを許可する方式が佐藤潔氏によって提供されている。詳しくはリンクのページ http://www.gabacho-net.jp/anti-spam/links.html を参照していただきたい。
もしS25Rスパム対策方式がインターネット全体で支持されるなら、メール中継サーバとエンドユーザー用回線とを区別するための規則を合意することによって、この方式はより確実なものになるだろう。メール中継サーバを引っかけることを避けるために、エンドユーザー用回線の末端ホスト名が数字で始まるか、5個以上連続する数字を含むか、または数字以外の文字列で分断された2個の数字列を含むという規則を私は提案する。
また私は、すべてのドメインで次の規則を守ることを提案する。 エンドユーザー用回線のIPアドレスは、エンドユーザー用回線の名前の規則に適合する逆引きFQDNを持つか、さもなければ逆引きFQDNを持たない。
スパマーがS25Rスパム対策方式をすり抜けるには、以下の方法がある。しかし、いずれの方法を使っても、スパマーが大量のスパムを低コストでばらまき続けることは非常に困難だと思われる。すなわち、このスパム対策方式は強固であると考えられる。
ISPのメール中継サーバを経由するスパムは、このスパム対策方式に引っかからない。正当なメールがそのメール中継サーバを通りうる限り、受信者のドメインのメールシステム管理者はそれをブラックリストに登録しないからである。しかし、この方法ではスパマーはさほど多量のスパムをばらまくことはできない。もしスパマーがメール中継サーバを過負荷にすれば、ISPからペナルティを食らうかもしれない。また、ISPは、あまりに多くの宛先が指定されたメッセージや、一つのクライアントからのあまりに頻繁な送信要求を、メール中継サーバに拒否させるかもしれない。だからスパマーはおとなしく少量のスパムを送信するしかない。それで大量スパム配信ビジネスはペイするかな?
スパム送信コンピュータが応答コード「450」に対して、正当なメール中継サーバと同じように送信を再試行すれば、受信者のドメインのメールシステム管理者は、スパム送信コンピュータを正当なメール中継サーバと見誤り、それをホワイトリストに登録するかもしれない。しかし、メッセージがスパムだったとわかったら、ホワイトリストから抹消するだろう。かくしてスパマーは、同じホストからそのドメインへ二度とスパムを送ることができなくなる。つまり、再試行のためのメールキューにコンピュータリソースを消費しながらも、スパムの送達率を上げることはむずかしい。それで大量スパム配信ビジネスはペイするかな?
スパマーを庇護しようとするISPが、正当なメール中継サーバであるかのようなFQDNをスパマーに提供するかもしれない。しかし、そのようなISPのドメイン名は、やがて多くのドメインでブラックリストに登録されるであろう。だから、そのようなISPは生き延びることができない。おあいにくさま。
もしスパマーがDNSを管理できるなら、自分自身のドメイン名を持つことによって、正当なメール中継サーバであるかのようなFQDNを利用することができる。しかし、結果は、スパマーを庇護するISPを利用する場合と同じである。防御側がドメイン名をブラックリストに登録するのには金がかからないが、攻撃側がドメイン名を変更するには金がかかる。スパマーにはお気の毒なことである。
まとめ
スパマーへの怒りを主張することは、スパムを減らすためには何の役にも立たない。スパマーは、儲かるからスパムをやめない。スパムをやめさせたいならむしろ、拒絶の応答コードを黙々と返し続けることである。それも、防御に金がかからず、攻撃に金がかかる方法で。
S25Rスパム対策方式は、少しの副作用のリスクをコントロールする覚悟さえあれば、すぐに無料で導入できる。しかもこの方式は、スパムやウィルスメールを約99%阻止できる。この方式の効果は私の個人用メールサーバで実証済みである。この方式が普及すれば、スパムの受信はなくならないまでも激減するであろう。
私は、このアイデアについて何らの独占権も主張しない。そして、もしあなたが私のアイデアに基づいて新たな方法を考案したなら、独占権を主張せずにそれをインターネットの世界に提供してくれるよう希望する。
読者諸氏のコメントと協力を期待する。
付録A. Postfixでの設定方法
Postfixでクライアントを制限するための設定方法を紹介する。
ホワイトリスト項目の実例は、ホワイトリスト情報のページ http://www.gabacho-net.jp/white-list.html からいくつかピックアップしている。
ブラックリスト項目の実例は、私が自分のメールサーバに登録したもののうち、何度も役立っているものをいくつかピックアップしている。
ブラックリストと一般規則に記載されているFQDNの実例は、実際に私のメールサーバへスパムかウィルスを送ろうとしたことのあるクライアントのものである。しかし、そのドメインが悪質だという意味ではなく、そのIPアドレスが悪質な、あるいは不注意なユーザーに使われたことがあるという意味にすぎない。
/etc/postfix/main.cfファイルに追加する行
smtpd_client_restrictions = permit_mynetworks, check_client_access regexp:/etc/postfix/white_list, check_client_access regexp:/etc/postfix/rejections smtpd_helo_required = yes smtpd_helo_restrictions = permit_mynetworks, reject_invalid_hostname, check_helo_access regexp:/etc/postfix/helo_restrictions smtpd_sender_restrictions = permit_mynetworks, reject_non_fqdn_sender, reject_unknown_sender_domain
付記 以前はクライアント制限設定ファイルを一つにしていたが、ホワイトリストファイルと拒否条件ファイルに分離した。これにより、ファイルの保守が容易になる。また、逆引きが失敗した時の拒否メッセージを任意に指定できるようになる。「cannot find your hostname」という不親切な拒否メッセージを返すreject_unknown_client指定は不要になった。
/etc/postfix/white_listファイルの中身
# S25R client permission specifications for Postfix # Contributed by ASAMI Hideo (Japan), Jun 2004; Jul 2007 # Refer to: http://www.gabacho-net.jp/en/anti-spam/ # # To use this file, add following lines into the /etc/postfix/main.cf file: # # smtpd_client_restrictions = # permit_mynetworks, # check_client_access regexp:/etc/postfix/white_list # check_client_access regexp:/etc/postfix/rejections # # where "white_list" is the name of this file. # # *** WHITE LIST *** # # When you find a legitimate mail relay server which is rejected by the # rejection specification written in the /etc/postfix/rejections file, write # down here a permission specification taking a leaf from the following # examples. # #/^223-123-45-67\.example\.net$/ OK #/^223\.123\.45\.67$/ OK # # Practical examples: # # mail-gx0-f21.google.com, etc. /\.google\.com$/ OK # # mc1-s3.bay6.hotmail.com, etc. /\.hotmail\.com$/ OK # # h04-a1.data-hotel.net, etc. /\.data-hotel\.net$/ OK # # web10902.mail.bbt.yahoo.co.jp /\.yahoo\.co\.jp$/ OK # # web35509.mail.mud.yahoo.com /\.yahoo\.com$/ OK # # n2.59-106-41-68.mixi.jp, etc. /\.mixi\.jp$/ OK # # mta12.m2.home.ne.jp, etc. /\.m2\.home\.ne\.jp$/ OK # # mmrts006p01c.softbank.ne.jp, etc. /\.softbank\.ne\.jp$/ OK # # imt1omta04-s0.ezweb.ne.jp, etc. /\.ezweb\.ne\.jp$/ OK # # bay-w1-inf5.verisign.net, benicia-w2-inf30.verisign.net /\.verisign\.net$/ OK
/etc/postfix/rejectionsファイルの中身
# S25R client rejection specifications for Postfix # Contributed by ASAMI Hideo (Japan), Jun 2004; Jul 2007 # Refer to: http://www.gabacho-net.jp/en/anti-spam/ # # To use this file, add following lines into the /etc/postfix/main.cf file: # # smtpd_client_restrictions = # permit_mynetworks, # check_client_access regexp:/etc/postfix/white_list # check_client_access regexp:/etc/postfix/rejections # # where "rejections" is the name of this file. # # *** BLACK LIST *** # # When you find a UCE sender's FQDN which is not rejected by the generic # protection rules specified below, insert here a denial specification taking # a leaf from the following practical examples. You should specify a subdomain # name or a substring together with the domain name if possible so that you can # avoid rejecting legitimate mail relay servers in the same domain. # # pr86.internetdsl.tpnet.pl # fq217.neoplus.adsl.tpnet.pl # pa148.braniewo.sdi.tpnet.pl /\.(internetdsl|adsl|sdi)\.tpnet\.pl$/ 450 domain check, be patient # # user-0cetcbr.cable.mindspring.com # user-vc8fldi.biz.mindspring.com /^user.+\.mindspring\.com$/ 450 domain check, be patient # # c9531ecc.virtua.com.br (hexadecimal used) # c9066a60.static.spo.virtua.com.br (hexadecimal used) /^[0-9a-f]{8}\.(.+\.)?virtua\.com\.br$/ 450 domain check, be patient # # catv-5984bdee.catv.broadband.hu (hexadecimal used) /\.catv\.broadband\.hu$/ 450 domain check, be patient # # Edc3e.e.pppool.de # BAA1408.baa.pppool.de /[0-9a-f]{4}\.[a-z]+\.pppool\.de$/ 450 domain check, be patient # # pD9EB80CB.dip0.t-ipconnect.de (hexadecimal used) /\.dip[0-9]+\.t-ipconnect\.de$/ 450 domain check, be patient # # pD9E799A1.dip.t-dialin.net (hexadecimal used) /\.dip\.t-dialin\.net$/ 450 domain check, be patient # # ool-43511bdc.dyn.optonline.net (hexadecimal used) /\.dyn\.optonline\.net$/ 450 domain check, be patient # # rt-dkz-1699.adsl.wanadoo.nl # c3eea5738.cable.wanadoo.nl (hexadecimal used) /\.(adsl|cable)\.wanadoo\.nl$/ 450 domain check, be patient # # ACBBD419.ipt.aol.com (hexadecimal used) /\.ipt\.aol\.com$/ 450 domain check, be patient # # *** GENERIC PROTECTION *** # # [rule 0] /^unknown$/ 450 reverse lookup failure, be patient # # [rule 1] # ex.: evrtwa1-ar3-4-65-157-048.evrtwa1.dsl-verizon.net # ex.: a12a190.neo.rr.com /^[^.]*[0-9][^0-9.]+[0-9].*\./ 450 S25R check, be patient # # [rule 2] # ex.: pcp04083532pcs.levtwn01.pa.comcast.net /^[^.]*[0-9]{5}/ 450 S25R check, be patient # # [rule 3] # ex.: 398pkj.cm.chello.no # ex.: host.101.169.23.62.rev.coltfrance.com /^([^.]+\.)?[0-9][^.]*\.[^.]+\..+\.[a-z]/ 450 S25R check, be patient # # [rule 4] # ex.: wbar9.chi1-4-11-085-222.dsl-verizon.net /^[^.]*[0-9]\.[^.]*[0-9]-[0-9]/ 450 S25R check, be patient # # [rule 5] # ex.: d5.GtokyoFL27.vectant.ne.jp /^[^.]*[0-9]\.[^.]*[0-9]\.[^.]+\..+\./ 450 S25R check, be patient # # [rule 6] # ex.: dhcp0339.vpm.resnet.group.upenn.edu # ex.: dialupM107.ptld.uswest.net # ex.: PPPbf708.tokyo-ip.dti.ne.jp # ex.: dsl411.rbh-brktel.pppoe.execulink.com # ex.: adsl-1415.camtel.net # ex.: xdsl-5790.lubin.dialog.net.pl /^(dhcp|dialup|ppp|[achrsvx]?dsl)[^.]*[0-9]/ 450 S25R check, be patient
付記 以前の拒否メッセージは、ブラックリストには「domain UCE-blacklisted」、一般規則には「may not be mail exchanger」であった。これらは、「be patient」(お待ちください)という語句を含むメッセージに変更した。遅延警告メッセージを受けた善良な送信者を不安にさせることを避けるためである。
/etc/postfix/helo_restrictionsファイルのサンプル # Illegal HELO command blocking specification # Provided that your mail server's IP address is 223.12.34.56 and its # acceptable domain name is "example.com", specify as follows: # #/^223\.12\.34\.56$/ REJECT #/^(.+\.)?example\.com$/ REJECT
付録B. 拒絶記録抽出用シェルスクリプト
Postfixのメールログから拒絶の記録を抽出するシェルスクリプトである。あなたのコンピュータがメールサーバとウェブサーバを兼ねているなら、これをcgi-binディレクトリ配下のディレクトリの下にパスワード付きで置くことにより、拒絶の記録をウェブブラウザで容易に監視することができる。必要ならば、システム条件や監視したい期間に合わせてスクリプト中のログファイル名を書き換えていただきたい。
付記 再試行アクセスが連続して並ぶように拒絶記録をソーティングして表示する改良型のシェルスクリプトを http://www.gabacho-net.jp/anti-spam/log-sorting-script.html に掲載している。
#!/bin/sh echo "Content-Type: text/plain" echo echo "Mail rejection log" echo cat /var/log/maillog.4 /var/log/maillog.3 /var/log/maillog.2 \ /var/log/maillog.1 /var/log/maillog | \ grep 'reject:' | \ gawk ' BEGIN { count=0 } { printf "%s %2d %s %s\n", $1, $2, $3, substr($0, match($0, /reject:/)) ++count } END { print "\ncount =", count } '