skucky.com
自宅サーバー復旧後(2005年9月末頃)、しばらくスパムメールの対策を施さずにいましたが、毎日のように届くスパムメールに嫌気がさしたため、対策を施す事にしました。下図はスパムメール受信数の推移です。下図からも分かる通り、スパムメールが来ない日の方が少ないのが分かります。
方法はpostfixの機能を用い、メールサーバーがスパムメールの受信自体を拒否しようというものです。
いわゆるOutlook ExpressやThunder Bird等のメーラーでもフィルタリング機能を用いて、ある程度のスパムメールの分別はできますが、スパムメールを受信してしまっていることには変わらず、リソースの一部がこうしたスパムメールに食いつぶされていると思うと、段々腹が立ってきます。という事で、スパマーとのイタチごっこの始まりです。
まず、postfixの設定ファイルである/etc/postfix/main.cfの最下行に以下の設定を追記します。
1: smtpd_client_restrictions = |
2: permit_mynetworks |
3: check_client_access hash:/etc/postfix/access |
4: reject_rbl_client relays.ordb.org |
5: reject_rbl_client sbl-xbl.spamhaus.org |
6: permit |
1行目の意味するところは、メールを送信しようとするSMTPクライアントの接続に関して以下の条件を設定しますよ、という宣言の様なものと思って良いでしょう。その条件が何かというのが、2行目以降に記述されています。
2行目のpermit_mynetworksでは、自分のネットワーク内からの接続は無条件に許可し、3行目では/etc/postfix/accessというマップファイルを参照し、同ファイルによって接続が許可されているか否かがチェックされます。4、5行目ではRBLという外部リソースを用いて接続先ホストがスパムメール送信元ではないかどうかが検査されます。以上の条件をくぐり抜けた送信元ホストは最終行にある通り、permit、つまり接続が許可されるわけです。
実際に接続を拒否したいホストが分かっていれば、/etc/postfix/accessファイルに以下のように記述します。私の場合、既に受け取ったスパムメールの送信元アドレスを元に設定しましたが、送信元アドレスは簡単に詐称できるそうなので、私のようなやり方ではあまり意味が無いかもしれません(実際にスパムメールの送信元アドレスを見てて思いましたが、意味不明のアドレスが多く、実際にありそうもないドメインばかりです。中にはフリーメールアドレスを用いているものもありましたが)。
spamhost.com REJECT |
SPAMHOST.net REJECT |
hogehoge.com REJECT |
マップファイルを作成したら、以下のコマンドでハッシュ形式のファイルに変換します。それから、postfixに設定ファイルを再読み込みさせておきます。
quark:~# /usr/sbin/postmap hash:/etc/postfix/access |
quark:~# /etc/init.d/postfix reload |
実際スパムメールの送信元となっているホストは、踏台にされている事もあったりするので、マップファイル作成時には本当に拒否して良いホストかどうか見極めてから設定すべきです(私に届いたスパムメールの中にはどう見ても踏台にされているであろう某有名企業、某大学等のドメインが使われたアドレスもあったりしました)。特にフリーメールアドレスなどは、場合によってはうかつに拒否できない事もあるでしょうから注意が必要かもしれません。私の場合、海外の人とメールする事はまず無いので、海外の某有名ポータルサイトyah○○.comなどは拒否設定しています。
メールのヘッダ情報からスパムメールであることを推測し、受信を拒否するための作戦です。それには、まず/etc/postfix/main.cfにある以下の設定を有効にします(デフォルトではコメントされています)。
〜中略〜 |
header_checks = regexp:/etc/postfix/header_checks |
〜中略〜 |
スパムメールであるか否かの判断としては、既に受信したスパムメールの情報を元に傾向を見て設定すれば良いでしょう。私が受信したスパムメールの場合、タイトル(Subject:)が同じようなものが何通か届いている傾向があったので、下記のように設定する事にしました。設定ファイルは/etc/postfix/header_checksという正規表現のマップファイルです。
/^Subject:.*Hello/ REJECT |
/^Subject:.*Hi/ REJECT |
/^Subject:.*Pharmaceutical/ REJECT |
/^Subject:.*Software/ REJECT |
/^From: Doctor/ REJECT |
Subject:以外のヘッダ情報としてはFrom:等がありますが、私の場合は特定のアドレスから何通も届いている傾向がありませんでした。ただし、アドレスを毎回変えて、差出人の表示名がいつも同じお医者さん(Doctor)がバイ○グラと思しきブツの値段を記したメールを何度も御丁寧に送って下さるので、これも受信拒否の設定をしておきました。まったく、余計なお世話である。
ヘッダチェックと同じ要領で、今度は、メール本文の内容からスパムメールか否かを推測し、受信拒否するための作戦です。まず、/etc/postfix/main.cfに以下の設定を追記します。
〜中略〜 |
body_checks = regexp:/etc/postfix/body_checks |
〜中略〜 |
私宛のスパムメールの傾向としては、バイ○グラなどの薬品系、Micr○soft製品の格安販売系のメールが多いのですが、後者のメールを「software」や、「Micr○soft」等の一般的によく使われるキーワードで受信拒否すると、普通のメールまで受信拒否してしまう恐れがありますので、ここは妥協する事ととし、前者に対し作戦を決行します。
敵もなかなか手強く、バイ○グラの綴りをわざと間違えて書いてあったりするので、正しい綴りでフィルタリング設定しても網の目をくぐり抜けてきます。例えば私が受信したスパムの実績から以下のように設定をしておくことにしました。設定ファイルは/etc/postfix/body_checksという正規表現のマップファイルです。ちなみに、以下に記したキーワードは、全て前述の「Doctor」からのメールに実際かかれていた単語です。まったく、とんでもない医者である。
/Vlagara/ REJECT |
/Vlagera/ REJECT |
/Vlagfra/ REJECT |
/Vlaglra/ REJECT |
/Vlagora/ REJECT |
/Vlagrra/ REJECT |
/Vlajgra/ REJECT |
/Vlalgra/ REJECT |
/Vlangra/ REJECT |
/Vlatgra/ REJECT |
/Vlavgra/ REJECT |
最近の新手は1行に1文字だけ書いて送信してくるスパムも増えてきています。まったく、そこまでしてスパムを送りたい輩の気が知れませんが、さすがに1行に1文字だけというのは、ここでの作戦では歯が立ちません。
メールヘッダ情報にあるFrom:フィールドに使用されているメールアドレスのドメインが正当なものであるか否かをチェックしようというのがここでの作戦です。From:フィールドに使用されているメールアドレスのドメインの名前解決を試み、名前解決できない場合、受信を拒否します。
設定方法は、/etc/postfix/main.cfファイルに以下の設定をするだけです。
〜中略〜 |
smtpd_sender_restrictions = reject_unknown_sender_domain |
〜中略〜 |
実際スパムメールの送信元アドレスは詐称されていることが多く、デタラメなアドレスを使用しているので、ドメイン名の名前解決によるチェックは、なかなか良い効果を期待できそうです。
スパムメールの本文には、怪しいサイトへのリンクが張られていることがしばしばあります。上述の本文チェックにこのリンク先URLを追加し、受信拒否しようというのが次の作戦です。
方法としては、まず以下のようなコマンドを実行し、スパムメール本文にあるリンク先となっているドメインを抽出します。
hogehoge@quark:~$ cd ~/Maildir/.Junk/cur |
hogehoge@quark:~/Maildir/.Junk/cur$ cat * | grep 'http:' |\ |
sed 's/.*http:\/\///g' | sed 's/ .*$//' | \ |
sed 's/\/.*//g' | sed 's/^M//g' > ~/domain.lst |
上記のコマンドでは、~/Maildir/.Junk/curディレクトリにスパムメールのメールのみが格納されていることが前提としてあります。私はメール受信プロトコルにIMAPを使用しており、メーラーはThunder Birdを利用しています。この場合、Thunder Bird の学習機能で「迷惑メール」フォルダに自動振り分けされたものが、~/Maildir/.Junk/curディレクトリに格納されています。最後にhogehogeユーザーのホームディレクトリにdomain.lstというファイル名でリダイレクトしています。
上記コマンドを実行し、domain.lstファイルを参照すると、それなりにURLの一覧が抽出されているのがわかるかと思います(一部完全に抽出できない箇所もあるので手作業で編集しましょう)。
さて、怪しいドメイン一覧ができたら、それを上述の/etc/postfix/body_checksに追加し、「REJECT」と設定すれば良いわけですが、スパムメールの受信状況によっては膨大な数のドメインが抽出されているかと思われるので、少し楽をして編集作業をしましょう。方法は先ほど作成したdomain.lstをviエディタで編集し、以下のコマンドをviのコマンドモードで実行します。
:1,$s/^/\// |
:1,$s/$/\/ REJECT/ |
上記の置換により、「/キーワード(ここではドメイン名)/ REJECT」という書式に変換することができます。ここまで編集したら、あとは以下のコマンドで/etc/postfix/body_checksに追記します。上書きしないように注意が必要です。
hogehoge@quark:~/Maildir/.Junk/cur$ su - |
Password: |
quark:~# cat /home/hogehoge/domain.lst >> /etc/postfix/body_checks |
これだけやっても、なおもスパムメールって奴は届くものです。件数こそ減った感はありますが、フィルタリング条件に合致せず網の目をくぐり抜けてくるメールは必ずあります。そこで、次の作戦は新規スパムメールの本文中にリンクされているドメインを自動的に抽出しようというものです。というのも、スパムメールが届く度に上述の作業を行うのは手間がかかるからです。
方法としては、まずスパムメール受信用ユーザー「dlist」を新規に追加して、スパムメールを受信したらこのユーザーに転送します。その時、dlistユーザーの.forwardファイルにperlスクリプトにより本文中からドメイン名を抽出する処理を設定し、dlistユーザーのホームディレクトリにドメイン一覧のファイルを作成しようというものです。
まず、メール転送時にperlスクリプトによるプログラムの実行を許可する設定を/etc/postfix/main.cfファイルに設定します。
〜中略〜 |
allow_mail_to_commands = alias,forward,include |
〜中略〜 |
次に、dlistユーザーのホームディレクトリに以下の内容で.forwardファイルを作成します。dsplit.plについては、こちらをご参照ください。dsplit.plを作成したら、実行権限を付与しておきます。
"| /home/dlist/dsplit.pl >> /home/dlist/spam_domain.lst" |
実際にスパムメールが届いたら、dlistユーザーにスパムメールを転送します。すると、dlistユーザーのホームディレクトリにspam_domain.lstというファイルが作成され、その中にドメイン名が抽出され記述されているはずです。あとは前述している要領で、/etc/postfix/body_checksに追記していけばOKです。
/etc/postfix/body_checksに追記する際、重複してしまう恐れがあるかもしれませんが、網の目くぐって届いているメールなので、重複している可能性は薄いと思います。したがって、何も考えずにルーチンワークとして追記してしまって問題はないと思われます。
参考記事:Linux World 2005年4月号