milter-greylist にまつわるその他諸々

本当はもっと早く書かなきゃいけなかった事など、諸々と。

設定ファイルの更新

greylist.conf の変更後に、milter-greylist の再起動は必要ない。milter-greylist が MTA からの要求を受けた時にファイルが更新されていると、勝手に読み込む。greylist.conf のシンタックスが間違っていないかを確認するには「milter-greylist -c」とすればチェックしてくれる。

もし、milter-greylist が死んだら

milter-greylist に限らず、MTA から milter を呼び出すのに失敗した場合、sendmail のデフォルトでは*1呼び出さなかったのと同じになる。つまり、メールが届かないとか、遅延する、ということはない。その代わり、大量に spam を受け取ることになる。

ただし、Postfix でのデフォルトでは一時エラー扱いになる(参照:Postfix設定パラメータ:milter_default_action)。

もし、greylist.conf の記述にシンタックスに間違いがあった場合、milter-greylist がエラーを返し、sendmail のデフォルトなら spam が流れてくることになり、Postfix のデフォルトならエラーの原因を解消するまで、一切のメールを受け付けなくなる。なので、greylist.conf を書き換えたら「milter-greylist -c」でチェックを忘れずに*2。

デフォルトの変更

特に時間に関するデフォルト値は、Postgrey の方が適切な感じがする。前に timeout(Greylist に入ってから、再送が無くて、Greylist から削除されるまでの時間)が 5 日というのは長い、と書いたが、他にいくつか、調整した方が良いと思うパラメータがある*3。

delay

Greylist に入ってから、再送を拒否する時間だが、デフォルト 45 分は長い。CentOS 5.4 で生成した sendmail であれば 30 分、Postfix のデフォルトが 1000 秒(16 分 40 秒)だから、45 分では最初の再送が拒否される可能性が高い。実際、5分程度で再送してくるものもあるので、Postgrey のデフォルトに合わせて5分で良いと思う。

delay 5m
autowhite

デフォルトで5日だが、これは、milter-greylist の稼働状況に、どれだけ気を配るかによると思う。

1日に1回、/var/lib/milter-greylist/db/greylist.db を見て、再送によって受信されたメールを確認する場合だと、autowhite は1日でも良いだろう。再送で救われてメールが、本来、受信すべきメールであったのならば、ホワイトリストに追加して遅延を発生させないようすれば良いし、spam だったら「困ったなぁ」と(^^;。

greylist.db で自動ホワイトリストに入っているものは、

  • 疑いがかけられたけど、受信したメール

になるわけだから、ここにリストアップされるケースを少なくなるように、ACL を調整するのが良い。

subnetmatch

大規模なメールサービスなどの場合、再送時の IP アドレスは必ずしも一致しない。milter-greylist のデフォルトでは、IP アドレスが完全に一致していないと、再送と認識されない。これも、Postgrey のデフォルトに会わせて、24 bit のネットマスクで評価するようにしておいた方が良い。

subnetmatch /24

Tarpitting

Tarpitting は、TCP のコネクションを維持したまま、サーバからの応答メッセージをわざと遅らせる手法。Ver 4.3.4 で使えるようになっている*4。ただし、Ver 4.3.x は開発版という位置づけである。

この方法は原理的に理にかなっている。というのは、spam を送る側にとっては大量にメールを送る必要があるので、「無言電話」のような時間はもったいない。一方、通常の MTA であれば、数分は無言電話のままでも平気。

ただ、無言電話でも電話代は課金されるのと同様に、無通信でも TCP のコネクションを張っている以上、サーバのリソースを食っていることになる。本来であれば、1通のメールの為に保持しているコネクションなんて、サイズが大きくなければ1秒で終わるものが、分単位で残ることになる。

なので、これも Greylisting と同様、S25R や DNSBL で引っかかった物を対象に Tarpitting するのが効果的。Tarpitting を耐えたられたら Greylisting してやる、とすれば、Greylist として保持するエントリ数を少なくする事も出来る。

greylist.conf のサンプル

とまぁ、こんな感じが良いかな、と。

socket "/var/run/milter-greylist/milter-greylist.sock"
dumpfile "/var/lib/milter-greylist/db/greylist.db" 600
dumpfreq 1
user "smmsp"

quiet
subnetmatch /24

list "my network" addr { 127.0.0.1/8 192.168.1.0/24 }

# SPF が pass だった時に許可したい差出人のメールアドレス
list "whitelist with spf" from { \
        /[.@]docomo\.ne\.jp[> ]*$/ \
        /[.@]gmail\.com[> ]*$/ \
        /[.@]apple\.com[> ]*$/ \
}

# DNSBL の結果が OK だった場合に許可したいメールアドレス
list "whitelist with dnsbl" from { \
        /[.@]example\.co\.jp[> ]*$/ \
}

# 差出人が自組織のメールアドレス
list "my domain" from { \
        /[.@]example\.com[> ]*$/ \
}

# DNSBL に spamhaus の ZEN を定義
dnsrbl "ZEN" zen.spamhaus.org 127.0.0.0/28

# 拡張正規表現を使う
extendedregex

# 再送が無かったときに Greylist から消える時間
timeout 12h

# 再送されても拒否する時間
delay 5m

# localhost や内部からのメールは無条件に許可
racl whitelist list "my network"

# SPF の設定が wide open になっている物を拒否
racl blacklist spf self msg "SPF is wide open"

# SPF の結果が pass になるものを許可
racl whitelist list "whitelist with spf" spf pass

# DNSBL の結果が OK だった場合に許可
racl whitelist list "whitelist with dnsbl" no dnsrbl "ZEN"

# 自分のドメインから届くのに、その IP が DNSBL で NG のものは拒否
racl blacklist list "my domain" dnsrbl "ZEN" msg "Where are you?"

# S25R に引っかかるものは Greylisting
racl greylist domain /^\[.+\]$/ msg "S25R rule 0"
racl greylist domain /^[^.]*[0-9][^0-9.]+[0-9].*\./ msg "S25R rule 1"
racl greylist domain /^[^.]*[0-9][0-9][0-9][0-9][0-9]/ msg "S25R rule 2"
racl greylist domain /^([^.]+\.)?[0-9][^.]*\.[^.]+\..+\.[a-z]/ msg "S25R rule 3"
racl greylist domain /^[^.]*[0-9]\.[^.]*[0-9]-[0-9]/ msg "S25R rule 4"
racl greylist domain /^[^.]*[0-9]\.[^.]*[0-9]\.[^.]+\..+\./ msg "S25R rule 5"
racl greylist domain /^(dhcp|dialup|ppp|[achrsvx]?dsl)[^.]*[0-9]/ msg "S25R rule 6"

# DNSBL に引っかかったものは Greylisting
racl greylist dnsrbl "ZEN"

# デフォルトは許可
racl whitelist default

Greylisting の感想

当初、Greylisting しても、ほとんど再送されるんじゃないか、と思ったら、意外なぐらいに再送して来ない。原理的には Tarpitting の方が効果的だと思うが、Greylisting だけでもボットから送ってくるようなものは、ほとんど防ぐ事が出来る。

spam を送る側も、いろいろ工夫してくるとは思うが、今のところ Greylisting の効果は高い。再送するような spam が増えてきたら、サーバの余裕を見て tarpitting を使う、という方向で考えておくと良いかな。

*1:milter プログラムの呼び出しに失敗した時にどうするかは、INPUT_MAIL_FILTER で「F=」の指定で変更出来る。参照:つれづれ日記:sendmail の MAIL_FILTER で指定するオプション

*2:この時、「-c」を忘れると、二重起動になった。で、待ち受ける UNIX ドメインのソケットが後から起動したプロセスに取られるらしく、間違って起動した milter-greylist のプロセスを殺すと、MTA から milter-greylist につながらなくなった。ということで、「-c」は忘れずに。

*3:調整の仕方としては、グローバルな設定として設定する方法の他に、ACL の行で指定する方法がある。この場合だと、「このルールに引っかかった時は delay は1時間」といった具合に、ACL 毎に時間を変える事が出来る。ただし、timeout は ACL では指定出来ない。

*4:CVS から引っ張り出したソースに付いている ChangeLog を見ると、4.3.5 で Tarpitting に関するデッドロックのバグを直した、と書いてある。