Postfixスパム対策メモ
出典: Wiki@browncat.org
目次 |
[編集] Postfixでスパム対策
毎日何十通もやってきてとてもうっとうしいスパムメールです。最近ではなかなか賢いスパムフィルタをユーザレベルで使うことが出来ますが、なるべくなら配送される前に出来るだけ捨ててしまいたいものです。
そこで、なるべく簡単に出来て、誤判定が少なく問題の少なそうな範囲でpostfixで弾いてしまうことします。
グレーなのや弾きにくいものについては後段のSpamAssassinやThunderbirdのスパムフィルタと人手に任せます。
メールスパムの歴史は古く、多くの方が悩まされ、対策を採られていますが、参考にさせていただいた代表的なものを。
- MTAのアクセス制御 詳しい解説。多くのことについて書いてあり私も頭の整理になりました
- S25R方式 クライアントが動的IPであるかどうかを正規表現でチェックする方法
- S25R+遅延(Starpitting) S25Rの動的IPにかかったものに遅延をかけ再送してきたら受け取る方式
- Postfixのマニュアル
- 拙サイトPostfixの設定メモ -- 少し古いですが基本的なところを。
最近のメールのスパムはクライアント/ヘッダ偽装やbotマシンからの送信などが増えて、ほぼ固定のパターンでは判定が出来ないものが多いようですが、まだまだヘッダやHELOだけで判定できるものも少なくありません。まずはこのあたりを中心に設定することにします。
ただし、MLや相手のサーバによって問題が発生する可能性もありますのでREJECTではなくDISCARDの方がいいかもしれません。
当方の場合(2007/5時点)以下の設定で合計約15~20%のスパムを削減。
注意:当方でやっているような半固定パターンでの拒否は問題を生じる可能性もありますのでご注意。
[編集] header_checksを有効にする
/etc/postfix/main.cfでheader_checksの行を有効にします。
header_checks = regexp:/etc/postfix/header_checks
[編集] coremail経由のメールを弾く
Received行にCoremailが挟まるものはまず間違いありません。というか私のところにCoremail経由で来るまともなメールはありません。
/etc/postfix/header_checksに以下のような1行を追加。 これでCoremailを経由してきたものを弾けます。ここ近々の3000通を調べたところ相当するものは約200通(=約7%)。スパムでないメールには見当たりませんでした。
/^Received:.*by.*\(Coremail\).*with.*SMTP/i REJECT
[編集] そのままずばりのスパムを弾く
ED関連の薬など。困っていないので。ダイエット薬は必要かもしれない。
さっきと同じ条件で検索して約230通(=約8%)。ただしヘッダがエンコードされていてMTAで判定しにくいものはそのままスパムフィルタに任せることになります。
/^(Subject|From):(viagra|cialis|penis|anatrim)/i REJECT
[編集] heloの不正な応答を拒否する
まずはheloの明らかに不正なホスト名を弾きます。まず私のところのサーバやIPアドレスを騙るもの。それから明らかにおかしいものです。
/etc/postfix/main.cf
smtpd_helo_required = yes smtpd_helo_restrictions = permit_mynetworks, reject_invalid_hostname, check_helo_access regexp:/etc/postfix/helo_restrictions, permit
以下、ブラックリスト方式で来たメールからピックアップ。S25Rのような一般的な形式は正常なものも撥ねてしまうのが怖いので。いたちごっこなんですがね。。。
とりあえず届いたメールのうちThunderBirdとSpamAssassinの両方がスパム判定を下したメールから一日数件づつ手作業でBlackListに加えていっています。この方法はかなり地道で一気に効果がでるものではありませんが、人手を介することで比較的安全に送信元を特定し拒否できると思います。当サーバでも徐々に効果が現れてきています。ただし設定ミスの危険性が常にあるので注意は必要です。
/etc/postfix/helo_restrictions (update: 2007/6/10)
/^XXX\.YYY\.ZZZ\.AAA$/ REJECT -- 自サーバのIPアドレス /^(.+)?<MYDOMAIN>\.org$/ REJECT -- 自サーバのドメイン名 # Illegal Pattern /^[a-zA-Z0-9-]+$/ REJECT /^..$/ REJECT # BlackLists /^[0-9].*\.oradea\.rdsnet\.ro$/ REJECT /^cpe-[0-9]+.*\..*\.rr\.com$/ REJECT /^A.*-[0-9]+-.*\.abo\.wanadoo\.fr$/ REJECT /^ppp.*\.pppoe\.mtu-net\.ru$/ REJECT /^OL.*\.fibertel\.com\.ar$/ REJECT /^[0-9].*\.adsl\.terra\.cl$/ REJECT /^c-[0-9].*\.hsd[0-9]\.ma\.comcast\.net$/ REJECT /^p[0-9A-Fa-z].*.dip0.t-ipconnect.de$/ REJECT /^dialsquare[0-9]+\.freeserve\.co\.uk$/ REJECT /^dsl-[0-9].*\.prod-infinitum\.com\.mx$/ REJECT /^cpe-[0-9]+.*\.az\.commspeed\.net$/ REJECT /^m[0-9][0-9]\.mailyes\.net$/ REJECT /^[0-9]+.*\.speedy\.com\.ar$/ REJECT /^[a-f0-9]+\.virtua\.com\.br$/ REJECT /^lec[0-9]+.*\.dsl\.club-internet\.fr$/ REJECT /^customer-[0-9]+.*\.millicom\.com\.ar$/ REJECT /^[0-9]+.*\.sktn\.hsdb\.sasknet\.sk\.ca$/ REJECT /^adsl[0-9]+.*\.dyn\.etb\.net\.co$/ REJECT /^[0-9]+.*\.broad\..*\.dynamic\.163data\.com\.cn$/ REJECT /^ppp-[0-9]+.*\.revip[0-9]\.asianet\.co\.th$/ REJECT /^[0-9]+.*\.bb\.netvision\.net\.il$/ REJECT /^[0-9]+.*\.user\.veloxzone\.com\.br$/ REJECT /^bb[0-9]+.*\.singnet\.com\.sg$/ REJECT /^adsl-ull-[0-9]+.*\.net24\.it$/ REJECT /^ate[0-9]+\.internetdsl\.tpnet\.pl$/ REJECT
[編集] ウィルスらしきものも拒否
以下の様なあからさまに怪しげなメールも拒否。
/^content-type:.*name=.*\.scr\"/i REJECT /^content-type:.*name=.*\.pif\"/i REJECT
[編集] スパムの多いメーリングリストを購読停止
少し消極的な対策ですがFreeBSD系ML ports-jpの購読を止めたらスパムが減りました。
FreeBSD系のメーリングリストはスパム対策が今ひとつなので、もう少し対策をして欲しいですね。個人的にはほぼ全面的にLinuxに移行したので最近は余り読んでいなかったのですが、長い間お世話になったので。。。
[編集] DNSBLを利用してスパム判定をする
DNSBLはIPアドレスやホスト名を特定の形式でDNSで問い合わせることで、スパムや問題のあるホストであるかを判定してくれるブラックリストの検索機能です。サーバやデータベースは多くありますがだいたいはボランティアベースで運営されています。
個人的にはかなり以前に使おうとして、大量のアドレスをブロックしているところを発見してから使わなくなりました。実際有名なSPAMHAUS等少し厳しすぎる運営に問題もあるかもしれません。最近ではいくつかの判定基準をスコアリングする方法などが有力視されているようです。
とはいえ、スコアリング方式のフリーのソフトは不勉強で知らないので、比較的運営がきめ細かく、データベースの破棄日数も短めなrbl.jpがいいのではないでしょうか。大量なJUNKメールフィルタ向けではないとの評もありますが、信頼できそうなので入れることにします。
smtpd_client_restrictions = permit_mynetworks, reject_invalid_hostname, check_client_access hash:/etc/postfix/access, reject_rbl_client all.rbl.jp, ...
[編集] 送信メールサーバの国によってアクセスを拒否する
接続拒否リストを地道に追加するのに疲れたので、スパムの多い国、メールのきそうにない国からのメールは全て遮断することにしました。 効果は大きいが、影響範囲も大きいはずですが、個人サイトですし、もしやりとりが発生しそうになったらそのときに許可することに。
昔からdnsblの使用は避けてきましたが国情報が得られる countries.blackholes.usはまあいいだろうと使ってみることにします。DNSトラフィックが増えるので出来ればGEOIPを使うか自力で国別拒否リストを作成しようかと思っていたのですが。。。とりあえずはありがたくblackholes.usを使わせてもらうことに。心配なのはデータベースが少し古いかも知れない点。去年の9月当たりで更新が止まってそうな雰囲気。
blackholes.usはrbldnsdフォーマットのリストを配布してくれているので、ローカルのrbldnsdを立ち上げて配布データを加工して使うのが一番いいかもしれません。
当サイトのスパム送信国TOP15は以下の通り。(近々の6300通のスパムから)
US 15.7 % JP 15.2 % PL 9.4 % CN 7.1 % DE 4.9 % KR 4.6 % RU 3.8 % FR 3.0 % BR 2.9 % GB 2.7 % TR 2.2 % ES 2.1 % IL 1.9 % IT 1.6 % PH 1.5 %
さすがにUSとJPからは拒否する訳にはいかないので残りの上位国10つをdnsblで拒否。
smtpd_client_restrictions = permit_mynetworks, reject_invalid_hostname, check_client_access hash:/etc/postfix/access, reject_rbl_client all.rbl.jp, reject_rbl_client pl.countries.blackholes.us, reject_rbl_client cn.countries.blackholes.us, reject_rbl_client de.countries.blackholes.us, reject_rbl_client kr.countries.blackholes.us, reject_rbl_client ru.countries.blackholes.us, reject_rbl_client fr.countries.blackholes.us, reject_rbl_client br.countries.blackholes.us, reject_rbl_client gb.countries.blackholes.us, reject_rbl_client tr.countries.blackholes.us, reject_rbl_client es.countries.blackholes.us, permit
[編集] 送信メールサーバの国によってアクセスを拒否する(GEOIP)
geoipというIPアドレスやホスト名から国情報を取得するライブラリを利用して、postfixのpolicydサーバを作ってみました。
postfixでgeoipを使って国ごとにフィルタするpolicyスクリプト
この方法の利点はdns lookupを行わないのでネットワーク負荷が発生せず比較的高速であることです。フィルタする国のリストが多くなっても速度的にはそれほど遅くなりません。ちなみに私のところでは30国ぐらい拒否リストに入れています。
また前項のblackholes.usのリストは更新が停止してしまっているようですが、geoipはプロサービスも行っており提供元からリストがメンテナンスされているのも利点です。
とはいえ完全拒否も少し心配になってきたのでgraylist.plをgeoipで指定した国はグレーとするような改造をしようかなと思っています。
[編集] postgreyの使い方
rpmforgeにはpostgreyが入っています。これをインストールして使う方法です。
yum -y install postgrey
グループの設定がおかしいので/etc/sysconfig/postgreyを作成して
OPTIONS="--unix=$SOCKET --group postgrey"
とします。
後は/etc/postfix/main.cfに
smtpd_recipient_restrictions = permit_mynetworks, reject_unauth_destination, check_policy_service unix:/var/spool/postfix/postgrey/socket
と追加。postgreyとpostfix再起動。
/etc/init.d/postgrey start /etc/init.d/postfix restart
うまく動くようなら
/sbin/chkconfig postgrey on
[編集] postgrey + geoip
怪しい国からだけ、もしくは許可する国から以外はpostgreyに通すパッチです。設定ファイルなどありませんので適当に改造してくださいませ。 このままだと日本以外は全てgreyにします。使用にはご注意。 まあgeoipで全部拒否より少しましと思います。
--- /usr/sbin/postgrey.orig 2007-08-02 18:46:44.000000000 +0900
+++ /usr/sbin/postgrey 2007-08-06 19:34:34.000000000 +0900
@@ -18,6 +18,7 @@
use Sys::Hostname;
use Sys::Syslog; # used only to find out which version we use
use POSIX qw(strftime setlocale LC_ALL);
+use Geo::IP;
use vars qw(@ISA);
@ISA = qw(Net::Server::Multiplex);
@@ -26,6 +27,10 @@
my $DEFAULT_DBDIR = '/var/spool/postfix/postgrey';
my $CONFIG_DIR = '/etc/postfix';
+my $geoip;
+$geoip = Geo::IP->new(GEOIP_STANDARD);
+die("geoip open error") if (!$geoip);
+
sub read_clients_whitelists($)
{
my ($self) = @_;
@@ -293,6 +298,12 @@
my $real_now = $now;
if(defined $attr->{policy_test_time}) { $now = $attr->{policy_test_time} }
+ my $client = $attr->{client_address};
+ my $country = $geoip->country_code_by_addr($client);
+ my $result = ($country =~ /JP/) ? 'DUNNO' : 'GREY';
+ syslog 'info', "address:%s country:%s result:%s",$client,$country,$result;
+ return 'DUNNO' if ($country =~ /JP/);
+
# whitelists
for my $w (@{$self->{postgrey}{whitelist_clients}}) {
if($attr->{client_name} =~ $w) {
