magic-smtpd(magicmail) + vpopmail

2008 / 07 / 02 ( Wed )
この記事をはてなブックマークに登録する この記事をYahoo!ブックマークに登録する この記事をlivedoorクリップに登録する

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-smtpdvpopmailと組み合わせて利用できるように設定しました。

magic-smtpdのインストール

magic-smtpdmagicmailというパッケージに含まれます。

http://www.linuxmagic.com/opensource/magicmail/magic-smtpd/

インストールはそんなに難しくありません。

# 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.sh
vpopmail-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-smtpdvpopmailのユーザチェックを行えるようになりました。

▼存在するユーザへのメールの送信
# 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

サーバー構築・運用に関わるプロフェッショナルの方々の体験談や解説がいっぱい集まった、
こちら↓のページも合わせてご参照ください。
ブログランキング

テーマ:ソフトウェア - ジャンル:コンピュータ

09:03:45 | Unix/Linux | トラックバック(0) | コメント(6) | page top↑
<<デザイナーとウェブ製作者 | ホーム | 第2回関西OpenOffice.org勉強会に参加しました。>>
コメント
--ユーザ判定--

上記でezmlmとか.qmail-defalutとかは対応できましたか?

by: rayman * 2008/08/01 09:25 * URL [ 編集] | page top↑
--ezmlmはOKです--

raymanさん。ezmlmに関しては、/usr/local/bin/valias-wrapperの結果が利いてくるのでOKです。
.qmail-defaultはどんな場合でしょう?
by: 眠れないSE(´〜`) * 2008/08/01 20:06 * URL [ 編集] | page top↑
--.qmail-default--

.qmail-defaultはたとえば。

domain : test.com

.qmail-test-default

ってあったら

test-111@test.com
とか
test-21312@test.com

が受信可能になります。
ワイルドカードみたいのがつかえるってことですね♪

by: rayman * 2008/08/04 13:27 * URL [ 編集] | page top↑
--.qmail-defaultは使えません。--

そもそも、この設定は、管理しているドメインに存在しないアカウント宛のメールを、はじくための設定です。

ワイルドカードを使えたら意味がありません。
by: 眠れないSE(´〜`) * 2008/08/04 22:23 * URL [ 編集] | page top↑
--.qmail-default--

でもezmlmでもqmail-defaultは使用しているでしょ?qmailadminではcatch allなんて設定もあるし。

ezmlmの機能とかは使えてますか?って事ですね。アーカイブを取得したりですね。


by: rayman * 2008/08/04 23:41 * URL [ 編集] | page top↑
----

catchallを使うことは全く想定していません。catchallを使うのであれば、この仕組みは必要ありません。

ezmlmに関してはご指摘の通りです。ただ現在は、ezmlmはグループメールのような使い方で、登録・削除は管理者のみが行うという運用をしているので問題にはなっていません。

とは言え、ezmlmのその他の機能に関してもちゃんと動くように今度考えます。ご指摘ありがとうございました。
by: 眠れないSE(´〜`) * 2008/08/07 23:55 * URL [ 編集] | page top↑
コメントの投稿














管理者にだけ表示を許可する

トラックバック
トラックバックURL
http://iamse.blog110.fc2.com/tb.php/106-f187e0c0
この記事にトラックバックする(FC2ブログユーザー)
| ホーム |