milter-greylist だとこんな感じ

Postgrey に比べて、こっちの方が日本語の情報が少ない感じがする。

  • そもそも、Milter って sendmai 発祥。
  • 日本語情報なら Postfix の方が圧倒的に多いし、sendmail は難しすぎる。
  • Postfix 側の設定さえ、ちゃんとしてしまえば、Postgrey はそれなりに動く。
  • それに比べ、milter-greylist は milter-greylist 用の設定ファイルを書かなきゃいけないから面倒。

といった辺りが原因かなぁ、と勝手に思う。

かくいう自分も最初に試したのは Postgrey。milter-greylist を調べ始めたときには、軽くめまいが...。

その他にも導入を妨げる要因として、CentOS 用の milter-greylist のパッケージが無いこともある。いや、あることはある。確かに rpmforge にはある。ところが、とにかく古い。2009-12-26 現在、Ver 4.2.3 が正式リリース版として最新だが、rpmforge にあるのは Ver 3.0。新しいバージョンでは SPF の結果と組み合わせたり、Greylisting にとどまらない、いろんな処理ができるのに、Ver.3.0 ではその辺が...。

ということで、Fedora あたりから拾ってきて、パッケージを作り直すしかない。

で、どうせ作り直すなら、libspf2 も有効にしておきたい。後述(の予定)するが、milter-greylist と libspf2 の組み合わせで、おもしろい処理ができる。

しかし、libspf2 のパッケージもなかなかなくて、別の Milter プログラム(smc_milter)が用意したパッケージとか、Peter Pramberger さんのパッケージ(http://www.pramberger.at/peter/services/repository/rhel5/)から取得することになる。

ということで、参考までに自分が要した手順を書くと、こんな感じ。

  1. まず、gcc とか bison、flex、rpmbuild といった、ビルドに必要なプログラムをインストール。
  2. Peter Pramberger さんのサイトから、libspf2 のパッケージをダウンロードしてインストールする。
  3. Fedora から milter-greylist のソースパッケージを取得する。
  4. ソースパッケージをばらして、spec ファイルを適時編集。
  5. rpmbuild -ba とかで、パッケージを作成

...って、かなり敷居が高いなぁ(^^;

その辺はともかく、無事、milter-greylist がインストールできたとする(料理番組みたいだなぁ)。

greylist.conf の基本

  • 「#」の後ろは行末までコメント
  • キーワードと値の間はスペースで、「=」などは入らない。
  • 行末で「\」とすれば継続行
  • 自分で定義した「名前」はダブルクォーテーションでくくる。
  • 正規表現を使う場合は「/」でくくる。
  • 時間を表す値の場合、数値の後ろに「d」「h」「m」「s」を付ける。

milter-greylist の設定ファイルは、/etc/mail/greylist.conf(Fedora ベースのパッケージの場合)になる。ファイルに記述する内容は、主に 3 つに分けられる。

グローバルな設定

milter-greylist の全体的な挙動を設定する。たとえば、milter-greylist の動作ユーザ(sendmail が相手で CentOS 上だと smmsp)とか、待ち受けするための UNIX ドメインソケットのパスとか。

グローバルな設定で調整が必要なのは timeout の設定で、デフォルトで 5 日になっている。この timeout の期間に同じ IP アドレスから、同じ差出人、宛先アドレスのメールが来れば再送と見なされる。

確かに、再送を繰り返して、あきらめるのが 5 日、という MTA は多いと思うが、あくまでも spam 除けとして、意図的に一度だけ一時エラーを返すのだから、5 日間も Greylisting で再送待ちをすると、自動ホワイトリスト入りするのが多くなってしまう。せいぜい長くても 1 日、12 時間程度でも十分だと思う。

それと、後々、S25R のパターンを書く時に拡張正規表現を使いたいので、extendedregex は指定したい。これを書かないと標準正規表現になる。

書き方はこんな感じ

timeout 12h
extendedregex

名前の定義

後で動作のルールを記述する時に利用する「名前」を定義する。

たとえば、無条件で転送を許可したい IP アドレスを列挙して、名前を付けておき、ルールを記述するときに利用する。

list "my network" addr { 127.0.0.1/8 10.0.0.0/8 192.0.2.0/24 }

上記のように書けば、IP アドレスが 127.0.0.1/8、10.0.0.0/8、192.0.2.0/24 の範囲にある場合を "my network" という名前でルールに記述できるようになる。

また、milter-greylist 中で DNSBL を使う場合には、利用する DNSBL をあらかじめ定義しておく必要がある。

dnsrbl "ZEN" zen.spamhaus.org 127.0.0.0/29

ルール

milter-greylist としては ACL と呼んでいるが、ACL と呼ぶのが適切なのか、個人的には微妙な気がするけど...。

ACL には「racl」「dacl」の 2 つがある。

  • racl ...... SMTP の RCPT TO を受け取った段階で評価する。
  • dacl ...... SMTP の DATA の後に送られてくるメールの内容で評価する。

ちなみに、Ver.3 では acl というキーワードを使っていたが、Ver.4 ではまだ互換性を持っているみたいだけど、非推奨になっている。

「racl」「dacl」のキーワードに続いて記述するのは、「blacklist」「greylist」「whitelist」の 3 つ。

  • blacklist ...... 受け取りを拒否する(SMTP の 500 番台のエラーを返す)。
  • greylist ...... Greylisting する(SMTP の 400 番台のエラーを返し、Greylist に記録する)。
  • whitelist ...... 受け取る 。

ACL は記述した順序で評価され、最後の ACL に「どの条件にも引っかからなかったらどうするのか」を記述する。

一番単純に、Greylisting をしたければ、こんな感じになる。

list "my network" addr { 127.0.0.1/8 10.0.0.0/8 192.0.2.0/24 }

racl whitelist list "my network"
racl greylist default

こう書けば、"my network" 以外からやってきたメールはすべて Greylisting される。

S25R だけを対象に Greylisting をしたい場合は、こんな感じになる。

list "my network" addr { 127.0.0.1/8 10.0.0.0/8 192.0.2.0/24 }
extendedregex

racl whitelist list "my network"
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"
racl whitelist default

「domain」は接続してきた IP アドレスを逆引きした結果で、逆引き自体は MTA 側で行われる。逆引きの結果が無ければ、"unknown" という文字列が MTA から渡ってくる。で、逆引きの結果が S25R のパターンに該当したら Greylisting をする、というのが 7 行続いている*1

「msg」は、SMTP でエラーコードを返した際に付けられるメッセージで、これがログに残るので、後でどの ACL に該当したのか、という手がかりになる。

ACL はこの順序で評価されるので、上記の記述なら、

  1. "my network" からの接続は無条件に受け取る
  2. S25R に該当した場合は、どのルールに該当したのかをメッセージとして出力させて Greylisting する。
  3. "my network" でもなく、S25R にも引っかからなければ受け取る。

という事になる。これで「S25R に引っかかった時だけ Greylisting」が実現できる。

...... だいぶ長くなったので、SPF を使ったテクニックなどは次回へ(^^;

*1:この記述は、http://milter-manager.sourceforge.net/blog/ja/2009/5/3.html で紹介されている内容を引用