magic-smtpd(magicmail) + vpopmail
qmailの憂鬱
qmailが下のようなメールを大量に送信している事があります。
Hi. This is the qmail-send program at comune.monreale.pa.it. I'm afraid I wasn't able to deliver your message to the following addresses. This is a permanent error; I've given up. Sorry it didn't work out. <hoge@example.com>: Sorry, no mailbox here by that name. vpopmail (#5.1.1)
これは、このメールサーバーに存在しないアカウント宛に大量にメールを送信されたためです。
知らないアカウントばかりにメールが来たので、「そんなアカウントいないよ。」と返事を返すのでqmailは一生懸命働きます。
qmailは、qmailサーバー宛に送信されたメールを一旦全てキューに取り込み、その後宛先のユーザが存在するかどうかを確認します。その為、存在しないユーザ宛にメールを大量に送られて来ると、このようなメールを大量に送信者宛に返信することになり、CPU負荷を無駄に消費するだけでなく、処理待ちのメールがキューに溜まって正常なメールの遅延も発生してしまいます。
qmailのsmtp関連の処理を行うqmail-smtpdを、magic-smtpdに置き換えると、存在しないユーザを一旦キューに取り込むことなくメールを拒否する事ができるので、無駄メールの大量送信待ちによるメール遅延が発生することを防ぐことができます。
magic-smtpdの仕組みは簡単。smtpdの通信のRCPT TOのところで指定されたメールアドレスをその場でチェックし、もし存在しないメールアドレスであれば"550 User does not exist"を返して、即メールの受信を拒否するものです。
今回は、magic-smtpdをvpopmailと組み合わせて利用できるように設定しました。
magic-smtpdのインストール
magic-smtpdはmagicmailというパッケージに含まれます。
インストールはそんなに難しくありません。
# tar zxvf magicmail-0.8.4-2.tar.gz # cd magicmail-0.8.4-2 # make # mkdir -p /etc/magic-mail/control # cp ./magic-smtpd/magic-smtpd /var/qmail/bin/magic-smtpd # chown root:qmail /var/qmail/bin/magic-smtpd # cp ./scripts/vpopmail-check-user.sh /usr/local/bin/ # chown root:root /usr/local/bin/vpopmail-check-user.sh # chmod 755 /usr/local/bin/vpopmail-check-user.sh
daemontoolsを使用しているので、daemontooslsのsmtpd用のrunスクリプトを書き換えました。qmail-smtpdのところをmagic-smtpdに置き換えるだけです。
▼/service/smtpd/run
#!/bin/sh exec env - PATH="/var/qmail/bin:/usr/local/djbtools/bin" \ tcpserver -H -R -l mx.example.com \ -v -x /usr/local/djbtools/conf/smtp.rules.cdb \ -u 501 -g 500 0 smtp magic-smtpd 2>&1
runスクリプトの書き換えが終わったら、smtpdのサービスを再起動します。
# svc -d /service/smtpd # svc -u /service/smtpd
再起動後、telnetコマンドを利用してメールの送信テストをします。
# telnet localhost 25 Trying 127.0.0.1... Connected to mx (127.0.0.1). Escape character is '^]'. 220-mx.example.com ESMTP 220-MagicMail Daemon with Built-In Anti-Spam 220 See http://www.linuxmagic.com for info helo mx 250 mx.example.com mail from: hoge@example.com 250 ok rcpt to: validuser@example.com 250 ok quit 221 mx.example.com Connection closed by foreign host.
magic-smtpdの設定
存在するユーザのみメールの受信を受け取るには下記2つのファイル(check_valid_usersとext_check_user_prog)を作成します。
▼/etc/magic-mail/control/check_valid_users
1
▼/etc/magic-mail/control/ext_check_user_prog
/usr/local/bin/vpopmail-check-user.shvpopmail-check-user.shは、magicmailのソースパッケージに含まれている、scriptsフォルダのものを利用しました。中身はこんな感じです。
▼/usr/local/bin/vpopmail-check-user.sh
#!/bin/sh EMAIL=$1 ALIAS=`/home/vpopmail/bin/valias $EMAIL | wc -l | grep "1" >dev/null 2>&1 ; echo $?` USER=`/home/vpopmail/bin/vuserinfo $EMAIL >/dev/null 2>&1; echo $? | grep "0" >/dev/null 2>&1 ; echo $?` if [ $ALIAS -eq 0 ] || [ $USER -eq 0 ]; then exit 0 else exit 1 fi
これでOKなはずですが…、実際にファイルを作成して、存在するユーザ(validuser@example.com)宛にメールを送っても、"550 User does not exist"が帰ってきてしまいます。こんな感じで↓
# telnet localhost 25 Trying 127.0.0.1... Connected to mx (127.0.0.1). Escape character is '^]'. 220-mx.example.com ESMTP 220-MagicMail Daemon with Built-In Anti-Spam 220 See http://www.linuxmagic.com for info helo mx 250 mx.example.com mail from: hoge@example.com 250 ok rcpt to: validuser@example.com 550 User does not exist quit 221 mx.example.com Connection closed by foreign host.
これは、magic-smtpdの実行ユーザ(qmaild)が、/home/vpopmail/bin/vuserinfoコマンドを実行する権限を持っていないため、/usr/local/bin/vpopmail-check-user.shの中の処理が正しい動きをしない事が原因です。
更に、この環境では/home/vpopmailのディレクトリパーミッションが、以下のようにvpopmailユーザ(とrootユーザ)のみしかアクセスできないようになっているため、valiasコマンドさえも正常に実行することができませんでした。
# ls -ld /home/vpopmail drwx------ 9 vpopmail vchkpw 4096 10月 25 2005 /home/vpopmail
magic-smtpdを利用するためのプログラムの作成
色々と考えた末、/home/vpopmail/bin/vuserinfoと/home/vpopmail/bin/valiasコマンド用にラッパープログラムを用意することにしました。作成したプログラムは2つ。
▼vuserinfo-wrapper.c
#include <sys/types.h>
#include <unistd.h>
#include <pwd.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
struct passwd *pw;
uid_t uid;
if ((pw=getpwnam("qmaild")) == NULL) {
fprintf(stderr, "qmaild is not found.\n");
exit(1);
}
uid=getuid();
if (uid != 0 && uid != pw->pw_uid) {
fprintf(stderr, "you are not allowed.\n");
exit(1);
}
execv("/home/vpopmail/bin/vuserinfo", argv);
}
▼valias-wrapper.c
#include <sys/types.h>
#include <unistd.h>
#include <pwd.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
struct passwd *pw;
uid_t uid;
if ((pw=getpwnam("qmaild")) == NULL) {
fprintf(stderr, "qmaild is not found.\n");
exit(1);
}
uid=getuid();
if (uid != 0 && uid != pw->pw_uid) {
fprintf(stderr, "you are not allowed.\n");
exit(1);
}
execv("/home/vpopmail/bin/valias", argv);
}
以下の手順でコンパイル&インストールします。ここで、注意!!vuserinfo-wrapperとvalias-wrapperにrootユーザでのSUIDを設定しています。
# cc -o vuserinfo-wrapper vuserinfo-wrapper.c # cp vuserinfo-wrapper /usr/local/bin # chown root:root /usr/local/bin/vuserinfo-wrapper # chmod 4711 /usr/local/bin/vuserinfo-wrapper # cc -o valias-wrapper valias-wrapper.c # cp valias-wrapper /usr/local/bin # chown root:root /usr/local/bin/valias-wrapper # chmod 4711 /usr/local/bin/valias-wrapper
実際にmagic-smtpdから呼び出されて、ユーザの有無を確認するシェルスクリプト(vpopmail-check-user.sh)を以下のように作成します。
▼/usr/local/bin/vpopmail-check-user.sh
#!/bin/sh
EMAIL=$1
/usr/local/bin/valias-wrapper $EMAIL >/dev/null 2>&1
if [ $? -eq 0 ]; then
exit 0
fi
/usr/local/bin/vuserinfo-wrapper $EMAIL >/dev/null 2>&1
if [ $? -eq 0 ]; then
exit 0
fi
exit 1
# chown root:root /usr/local/bin/vpopmail-check-user.sh # chmod 755 /usr/local/bin/vpopmail-check-user.sh
これで、/home/vpopmailのアクセス権を変えることなくmagic-smtpdでvpopmailのユーザチェックを行えるようになりました。
▼存在するユーザへのメールの送信
# telnet localhost 25 Trying 127.0.0.1... Connected to mx (127.0.0.1). Escape character is '^]'. 220-mx.example.com ESMTP 220-MagicMail Daemon with Built-In Anti-Spam 220 See http://www.linuxmagic.com for info helo mx 250 mx.example.com mail from: hoge@example.com 250 ok rcpt to: validuser@example.com 250 ok quit 221 mx.example.com Connection closed by foreign host.
▼存在しないユーザへのメールの送信
# telnet localhost 25 Trying 127.0.0.1... Connected to mx (127.0.0.1). Escape character is '^]'. 220-mx.example.com ESMTP 220-MagicMail Daemon with Built-In Anti-Spam 220 See http://www.linuxmagic.com for info helo mx 250 mx.example.com mail from: hoge@example.com 250 ok rcpt to: nonexistent@example.com 550 User does not exist quit 221 mx.example.com Connection closed by foreign host.
SUIDを設定している事に対しては、ちょっと不満が残る設定なのと、できることならvuserinfo-wrapperとvalias-wrapperの所有者をvpopmailにしたかったんですが、vuserinfoのプログラムの中で実行ユーザをチェックされているようで、vuserinfo-wrapperの所有者はrootにせざるを得ませんでした。
SSHで一般ユーザに対してログインを許可しているサーバーなんかでは、/home/vpopmailのアクセス権はきっちりしなきゃいけないので、その事を最優先にラッパープログラムの導入という策を採りましたが、この他にいい方法があったらどなたか教えてください。m(_ _)m
サーバー構築・運用に関わるプロフェッショナルの方々の体験談や解説がいっぱい集まった、こちら↓のページも合わせてご参照ください。
上記でezmlmとか.qmail-defalutとかは対応できましたか?
raymanさん。ezmlmに関しては、/usr/local/bin/valias-wrapperの結果が利いてくるのでOKです。
.qmail-defaultはどんな場合でしょう?
.qmail-defaultはたとえば。
domain : test.com
.qmail-test-default
ってあったら
test-111@test.com
とか
test-21312@test.com
が受信可能になります。
ワイルドカードみたいのがつかえるってことですね♪
そもそも、この設定は、管理しているドメインに存在しないアカウント宛のメールを、はじくための設定です。
ワイルドカードを使えたら意味がありません。
でもezmlmでもqmail-defaultは使用しているでしょ?qmailadminではcatch allなんて設定もあるし。
ezmlmの機能とかは使えてますか?って事ですね。アーカイブを取得したりですね。
catchallを使うことは全く想定していません。catchallを使うのであれば、この仕組みは必要ありません。
ezmlmに関してはご指摘の通りです。ただ現在は、ezmlmはグループメールのような使い方で、登録・削除は管理者のみが行うという運用をしているので問題にはなっていません。
とは言え、ezmlmのその他の機能に関してもちゃんと動くように今度考えます。ご指摘ありがとうございました。



