SPFやSender IDをみてくれるmilter (sendmail由来のmail filterの仕組み) を、IIJのひとたちが実装したものが今週から公開されている。

http://sourceforge.net/projects/enma

Perlで書かれたものはあったけど高負荷時にどうなんだとか、 あるいは大手各社は自分で実装してそうだけど外には出せないんだろうなあ と思っていたので、このようにCでゴリっと書かれたものが 表にでてくるのはありがたい。 開発陣も山本和彦さんとかそうそうたるメンツのようだ。

きょう土曜は中野で LL Future があったようで、 しかしすっかり行くのを忘れてしまい、天気もわるくなってきてそのままずっと家にいたりして、 じゃあenmaを試してみるかと思ったら若干いじる必要があり、 ついでなのでDebian GNU/Linuxのパッケージにしてみた。 debsignもしてないdebですがよければどうぞ。

http://tmp.mrmt.net/enma_1.0.0-1_i386.deb
md5sum bd68b60b5112c4f9a53ac50a0218e535

postfixで使う場合は、/etc/enma.confmilter.postfixtrueに変えて、 /etc/postfix/main.cfに以下みたいに足してやってください。

smtpd_milters = inet:127.0.0.1:10025

glibcマター

enmaはlibbind__res_ndestroy()を呼んでいるんだけど、 近年の glibc ではlibresolvでこのへんを吸収しちゃってるのと (ただ Debian GNU/Linux特有の事情がさらにあって後述)、 __res_ndestroy()が いつからかobsoleteになってて __res_nclose()を呼ぶようにしないといけない。

ただここは意図して__res_ndestroy()のほうを呼んでるようだ。 enma-1.0.0/libsidf/src/dnsresolv.c参照:

void
DnsResolver_free(DnsResolver *self)
{
    assert(NULL != self);
    res_ndestroy(&self->resolver);
    /*
     * glibc-2.4.0 以降ならば
     * res_nclose(&self->resolver);
     * とすることで libresolv でも対応可能.
     * glibc-2.3.x にも res_nclose() は存在するが,
     * マルチスレッド環境下ではメモリリークを引き起こす.
     */
    free(self);
}   // end function : DnsResolver_free

このへん、autoconf/automake レベルできれいに切り分けて upstream に パッチ出したいところだがとりあえず。

ちなみにDebian GNU/Linuxだと、bind 9.x系はライブラリの名前もlibbind9とかですね。

Debian GNU/Linuxマター

daemonは/usr/binじゃなくて/usr/sbinに入れましょうね、はいいとして、 libresolvに入ってる ns_initparse() とかがどうにもリンクできねー。
なんでだよ、と調べてみると、 なんかDebian GNU/Linuxのglibcパッケージ特有の問題みたい。

Re: why debian doesn't allow calling ns_initparse in shared lib?
#291609 - libc6-dev: Missing (not exported) funcions in libresolv.so - Debian Bug report logs

  • libresolvでもそのへんはinternal functionだからね、 ABIとかAPIも保証できんからあえてexportしてないんだよ。
  • はぁ? ns_initparse()なんて十年前から DNS and BINDに載ってますが何か?
という愉快な会話がbugs.debian.orgで1年前にされたままの状態で、 識者もちょっとつかまらず。

しょうがないので LDFLAGS/usr/lib/libresolv.a をベタに足すというナニなことをするはめに。 あまり納得できる感じではないし、Debian specificすぎるので これもupstreamにパッチ投げるには躊躇する話。

postfixと組み合わせて動かすと、 incoming mailのヘッダに以下のように評価結果が足されていきます。

Authentication-Results: localhost; spf=pass smtp.mailfrom=do_not_reply@apple.com; senderid=pass
	 header.From=do_not_reply@apple.com
Authentication-Results: localhost; spf=pass smtp.mailfrom=morimoto@gmail.com; senderid=pass
	 header.Sender=morimoto@gmail.com
Authentication-Results: localhost; spf=none smtp.mailfrom=dfgt@vengeur.net; senderid=none
	 header.From=dfgt@vengeur.net

あとは評価したメールを具体的にどうすんの、って話ですね。

こういうのをいろいろ実験するには、 pure perlなsmtpdであるqpsmtpdも面白いですね。 僕もpostfixのincoming smtpハンドリングのとこをqpsmtpdにして半年ぐらい 遊んでました。ただ本気のトラフィックをどんぐらい捌けるかはどうなんでしょうね。

DNS&BIND(第4版) Postfix詳解―MTAの理解とメールサーバの構築・運用