qmail の動作

back

(改装中です)


このドキュメントは qmail の動作をおおまかに説明し、運用の助けと なるために書かれました。
インストールの方法を書いたものではありません。インストールの 方法については、www.jp.qmail.org から「qmail 付属文書」→「インストール」をたどってください。 公式サイト(英文)は http://cr.yp.to/qmail.html にあります。
私がなぜ qmail を導入したか、その経過については qmail 導入記を参照。


qmail の特徴

  1. qmail は sendmail に比べて安全であり、堅牢であり、 設定が楽である。しかも、体感できるほど軽い。
  2. sendmail と違い、いつ kill -TERM してもメールが失われる ことがない。そのため安心して停止・再開ができる。
  3. qmail のセキュリティホールは、発表当時からいまだに 発見されていない。sendmail のように、しょっちゅう穴がみつかって バージョンアップする必要が生じたりはしない。
  4. よいシステム管理は、管理者がそのシステムの動作をきちんと 理解していなければできない。qmail は、sendmail のように 1つの「主役」プログラムがすべての機能を担っているわけでは なく、複数の単純なプログラム群が連携して動いている。 そのため、中でなにがどうなっているのかがわかりやすい。

qmail の動作

はじめに、メイル管理に関する基礎知識をおさらいします:

これらについてより詳しく学習したい方は、jp.qmail.org サイトの メイル管理入門 を読んでください。

MTA のローカル配送とリモート配送について、 もうすこし詳しく説明しておきます。

あるホスト上から 1通のメールを送るとします。メールの視点から 見ると、このメールは次のように処理されます:

  1. まず MUA によってヘッダとメッセージが作成される。
  2. そのホスト上で動いている MTA に渡される (MTA はそのメールを「ローカル受信」したことになる)。
  3. MTA はそのメールの表書きアドレスを見る。
  4. どちらの場合も、最終的にメールスプールにたまった メールを、宛て先のユーザが MUA を使って読む。

いっぽう、あるホスト上で動いている MTA から見ると、 メールの配信とは次の 4つの操作のどれかをやっていることになります:

  1. ローカル受信して、ローカル配信
    (そのホストのユーザが同一ホストのメールスプールに配信、 ファイルのコピーと似たようなもの)
  2. ローカル受信して、リモート配信
    (そのホストのユーザが他のホストにメールを送る)
  3. リモート受信して、ローカル配信
    (他のホストからくるメールをそのホストのメールスプールに配信)
  4. リモート受信して、リモート配信
    (他のホストからくるメールをさらに他のホストに転送、 いわゆるメールの中継)

図1 をみよ。 ここには qmail がどのようにメールを処理するかの流れが書いてある。 赤く記されているのがそのプログラムの動作を決定する 設定ファイルである。これらは /var/qmail/control/ に置かれている。


図1. qmail の動作

例として、ローカルからメールを出す場合を考えてみよう。 図1 の左上をみよ。まずユーザが MH あるいは Mew などの MUA で メッセージを作る。MUA は qmail-inject を起動し、この メッセージを渡す。qmail-inject は 2つの設定ファイル defaultdomaindefaulthost を見て、このメッセージの ヘッダを書き換える。つまり、

といったことをする。これでメッセージは完璧になった。 このメッセージには表書きがつけられ、 図1 の中心にある qmail-queue に渡されて送信キューにためられる。

さて、qmail の一番の中心はキューである。 来たメールは (ローカルにせよリモートにせよ) いったんキューにためられ、それが qmail-send によって配送される。 qmail-send はキューのメッセージをひとつ取り、その表書きを見て ローカル宛のものであるかリモート宛かを判断する。このとき 設定ファイル locals が使われる。 このファイルには一行ずつドメイン名が書いてあり、 qmail-send はこのファイル中にあるドメイン宛のメールは ローカル配信だと判断する。

では次に、リモートからメールがきた場合。SMTP によるメールは まず inetd によりとりつがれ、tcpd をへて qmail-smtpd に渡される。 qmail-smtpd は設定ファイル rcpthosts に書いてある宛先以外のメールは一切受けとらない。これは不正な メール中継を防ぐためである。しかしこれではゲートウェイにおける、 ふつうの (研究室内ホストからの) 中継ができない。 そのため、つぎのような方法が用意されている。qmail-smtpd は起動時に 環境変数 RELAYCLIENT を調べる。もし起動時にこの RELAYCLIENT フラグが 立っていると qmail-smtpd は rcpthosts の内容を無視してすべてのメールを受けとる。したがって 研究室内の他のホストからメールを転送するには、研究室内の ホストから接続されたときだけ RELAYCLIENT が立っているようにすればよい。 これは tcpd を使うとできる。tcpd は相手先のアドレスを見て、 必要に応じてこの変数を立ててくれる。これは tcpd の設定ファイル /etc/hosts.allow を書き換えることによって行う。 qmail-smtpd を通過したメールは qmail-queue によってキューに入り、 あとはローカルからきたメールと同じ道をたどる。


sendmail の動作

さて、プロセスと設定ファイルという面から同じように sendmail を見てみると 図2 のようになる。 sendmail デーモンひとつがつねに動いているし、設定ファイルも sendmail.cf だけなのでシンプルである。 じつに単純 (外側から見れば)。 しかしプログラムはさぞかし複雑だろう。バグがあっても不思議なし。


図2. sendmail の動作

(3/23 追記 - Satoh Wataru さんから情報をいただきました。ありがとう ございます。実際にはローカル配送は sendmail が直接やっているのでは なくて、binmail (/bin/mail や mail.local) がやっているようです。また、 「mailer との情報伝達が、smtp 以外は一方向の pipe なので、 配送エラーが起こった際の処理が脆弱だし、1通毎に MDA を fork -> exec してるので処理が重いです(MDA の return status が 75 なら rollback するはずだけどしばしば忘れ られている)。」とのこと)

(6/20 前野 年紀さんより、sendmail はメール送信時にも ユーザによって起動されるため、sendmail.cf はそのときにも 読まれるというご指摘をいただきました。ありがとうございます)


田中・徳永研究室のメール環境

図3 参照。ここでは いくつかの条件下で qmail の設定ファイル (とくに rcpthosts, locals, smtproutes) をどのように設定すべきかを解説する。

なお、control/ 以下のファイルを書きかえたときは kill -HUP ではなく、qmail-send を上げ直すこと (ただし locals と virtualdomains は別)。


図3. 田中・徳永研究室のメール配送

各マシンの設定ファイル:

cl0, cl0i (田中・徳永研究室ゲートウェイ)
まず、研究室外のホストはこれに対して @cs(.titech.ac.jp) 宛か @cl(.cs.titech.ac.jp) 宛のメールしか送らないはずだ (そうでないとしたら不正中継だ)。だから rcpthosts はこの 2つ。 さらに来たメールが @cs 宛のものだったらこれは外向きだから koudai へ転送し (田中・徳永研メンバー宛であってもいったん koudai でアドレスを書き換えてもらわねばならない)、 @cl 宛だったら内向きとみなして snow へ転送する。 また、研究室内のホストを中継しているのでまったくの外部行きも ここを通るはずだ。そういうのは直接相手に送信。したがって smtproutes にはこの 3つのルール (実際には直接送信は書く必要がないので 2つ) を書く。

rcpthosts: (実際は .cs.titech.ac.jp が cl を含んでいるのでこれだけでよい)

       localhost
       cs.titech.ac.jp
       .cs.titech.ac.jp
       

smtproutes: (ホスト名がついてたときに 備えて 2つずつにしてある)

       cl.cs.titech.ac.jp:snow.cs.titech.ac.jp
       .cl.cs.titech.ac.jp:snow.cs.titech.ac.jp
       cs.titech.ac.jp:koudai.cs.titech.ac.jp
       .cs.titech.ac.jp:koudai.cs.titech.ac.jp
       
snow (田中・徳永研究室ファイルサーバ)
これも rcpthosts は cl0 と同じ理由。 ただ、このマシンはメールスプールだから、@cl 宛のメールはここで ローカル配信する。したがって locals に このドメインを 1つ書く。それ以外のメールはもう外向けと わかりきっているので、すべて cl0 に転送する。よって smtproutes にはそのルールが 1つ。

rcpthosts:

(cl0 と同じ)

locals:

       cl.cs.titech.ac.jp
       .cl.cs.titech.ac.jp
       

smtproutes:

       :cl0i.cs.titech.ac.jp
       

(ハマリ記録: snow から研究室外にいくメールが、はじめ 拒否された。これは smtproutes の行き先を 研究室の内側の口である cl0i (131.112.20.2) ではなく、 外側の口 cl0 (131.112.16.208) にしていたことが原因。 snow も外側の口 wons (131.112.16.198) を持っているため、 cl0 に転送するときはそっちを使ってしまい、cl0 の tcpd が「こいつは研究室の外のやつだ」と判断してしまうため である)

その他の研究室内のマシン
これも rcpthosts は同じ。 smtproutes は、@cl 宛なら わざわざ cl0 に送る必要もなので直接 snow に転送。 それ以外なら snow と同様に cl0 へ。

rcpthosts:

(cl0 と同じ)

smtproutes:

       cl.cs.titech.ac.jp:snow.cs.titech.ac.jp
       .cl.cs.titech.ac.jp:snow.cs.titech.ac.jp
       :cl0i.cs.titech.ac.jp
       

無断リンク集


MUA の設定

qmail についてくる「にせ sendmail」の機能:

-t
ほかのオプションを無視する。
-f差出人
sender を変える。
-F差出人の名前
sender のフルネーム。
-bp
キューを表示。
-bs
標準入出力から SMTP で通信。
MH
メールを出す場合、MH の send コマンドは /usr/(local/)lib/mh/post を呼び出す。しかしこれは ローカルホストにわざわざ SMTP で投げるので、ローカルに tcp_wrapper を入れておかねばならず面倒。直接 qmail-inject で キューに入れてほしい場合、この post を同じディレクトリにある spost に置き変えれば OK。

あと、/usr/(local/)lib/mh/mtstailor を、

       mmdfldir:
       mmdflfil:	Mailbox
       sendmail:	/var/qmail/bin/sendmail
       
としておけば各人の ~/.mh_profile は書きかえる必要なし。
Mew
Maildir を使う場合はいろんなページに書いてある。 $HOME/Mailbox の場合、~/.im/Config の Imget.Src を
       Imget.Src=local:${HOME}/Mailbox
       
にすれば OK か。あるいは im の共有設定ファイル /usr/local/lib(share?)/im/SiteConfig を書きかえる。

Last modified: Fri Sep 28 13:36:24 2001
Yusuke Shinyama