何度も何度も悩まされてきたqmailのSPAM対策ですが、ようやくいいものにめぐりあえたかも。
http://www.linuxmagic.com/opensource/magicmail/magic-smtpd/
qmail-smtpdと差し替えて使うmagic-smtpdというやつなんだけど、これを使うとRCPT TOの段階でユーザーの実在するかどうかの判定をしてくれて、いない場合はエラーコードを返して接続を切ってくれる。
通常のqmailの動作としては、アドレスの有無にかかわらずqueueにいったんメッセージを入れて、それからユーザー判別を行う。このため、qmail-scannerが入っていたりすると、SPAMメールであってもウイルスチェックが動いてしまい、そのあとにユーザ判別が動くという、なんともCPUを浪費してくれる動きをしてくれていて困っていた。
某所のメールサーバはこのおかげでload avgがいつも7~16の間にあったりしていた。マシンにかなりの負荷がかかっているんで、qmailのプロセスがなかなか開放されなかったり、メールの配送が遅くなったりいろいろと支障が出ていたわけ。
で、先日上記のmagic-smtpdを見つけて、
http://www.linuxmagic.com/opensource/magicmail/magic-smtpd/manual.html#tth_sEc3.2
に書かれているvalid user判別のための仕組みをperlのスクリプトで用意したところ、見事にRCPT TOの段階でサクサクいらない接続を切ってくれています。いや、これが欲しかったんだよ。
やったことは、ドキュメントどおりにすべてインストールし、check-user.plというスクリプトを用意した。中身はこんな感じ。たいしたことない…。
#!/usr/local/bin/perl
if($ARGV[0] eq "") {
print "please supply with local user name\n";
exit;
}
if($ARGV[1] ne "") {
print "please supply with local user name\n";
exit;
}
$address = $ARGV[0];
chomp($address);
($checkuser, $domain) = split(/\@/, $address);
#print "checking $checkuser\n";
$passwd = "/etc/passwd";
$aliasdir = "/var/qmail/alias";
if(&checkPasswd($checkuser) eq "0") {
# print "0\n";
exit 0;
} elsif(&checkAlias($checkuser) eq "0") {
# print "0\n";
exit 0;
} else {
# print "1\n";
exit 1;
}
sub checkPasswd() {
$checkUser = @_[0];
# print "checkPasswd checking with $checkUser\n";
open(PASS, "<$passwd");
while($line = ) {
chomp($line);
(my $user,my $pass,my $uid,my $gid,my $name,my $home,my $shell) = split(/:/, $line);
if($user eq $checkUser) {
# print "checkPasswd matched with $checkUser\n";
close(PASS);
return 0;
}
}
close(PASS);
# print "checkPasswd not matched with $checkUser\n";
return 1;
}
sub checkAlias() {
$checkUser = @_[0];
# print "checkAlias checking with $checkUser\n";
opendir(ALIAS, "$aliasdir") || die "unable to open $aliasdir\n";
while($line = readdir(ALIAS)) {
next if($line =~ m/\.$|\.\.$/);
if($line =~ m/\.qmail-/) {
$alias = $line;
$alias =~ s/^\.qmail\-//;
$alias =~ s/\:/\./gi;
if($checkUser eq $alias) {
# print "checkAlias matched with $checkUser\n";
closedir(ALIAS);
return 0;
}
}
}
closedir(ALIAS);
# print "checkAlias not matched with $checkUser\n";
return 1;
}
確認のために入れたprint文が痛々しいかもしれないけど、まあこれで何とかできている。うちはvirtual domainを使ってないんで、/etc/passwdと/var/qmail/aliasを確認すればOKなわけです。このスクリプトへのPATHを
/etc/magic-mail/control/ext_check_user_prog
というファイルに書いてあげて、さらに
/etc/magic-mail/control/check_valid_users
というファイルに 1 と書いておくだけで設定完了。あとは、qmailをいったん停止して、qmail-smtpdをqmail-smtpd.bakとかに移動して
ln -s magic-smtpd qmail-smtpd
をしてあげた後に再度qmailを起動してあげればOK。
ちなみにソースコードにはvpopmailを使っている環境でのサンプルスクリプトがすでに入っているんで、vpopmailユーザーはさらに導入しやすいのではないかと。