メール配送の仕組みとqmailを知る
最近、qmailを管理するようになったが、まったくといっていいほど理解していないので、ポイントをメモします。
メール配送のしくみ
図の参照元 => http://japan.internet.com/webtech/20030807/7.html
1. メールクライアントにてメールを記述(宛先、件名、内容など)
2. メールクライアントはリレー許可のあるSMTPサーバ(以降、メールサーバ)に配送を依頼
3. メールクライアントから送信依頼を受けたメールサーバは、メールが送り届けられるべきメールサーバを調べます。この情報は、メールの宛先とネームサーバ(DNSサーバ)のMXレコードから調べられます。
4. メールが送り届けられるべきメールサーバがわかったら、そのサーバに接続して配送します。
5. メールが送られてきたメールサーバは、そのサーバ内の受け取り人のメールボックスにメールを届けます。
6. 最後に、受取人がメールクライアントを用いて、そのメールをダウンロードし、実際に読まれます。
SMTPサーバとリレー
メール配送は、SMTP(Simple Mail Transfer Protocol)という通信規則を用いて行われています。SMTPはTCPの25番ポートを利用する通信で、手元にあるメールを相手に送り渡すときに利用されます。
通常、SMTPで受信を受け付ける(受け取る)メールは限定されています。それは自サーバ内にメールボックスが設置されているメール以外は受け取る必要がないからです。したがって、SMTPで接続されてメールを送られてきたとしても、あて先の情報を見て、自サーバ宛のものではないという場合は、受け取りを拒否します。
しかし、「2」をよく見るとメールサーバ[A]は、自サーバ内にメールボックスがないメールについても受け取っています。これは、リレーと呼ばれる機能を実現するために特別に受け取っているのです。
リレーは、完全な配送機能をもっていないメールクライアントなどからひとまずメールを受け取り、代わりにそのメールが本来届けられるべきサーバに送信するものです。したがって、中継と呼ばれることもあります。
リレーの設定を間違えると、悪意を持った人から、SPAMなどの踏み台にされてしまう可能性があります。実際、踏み台にされてしまうと、サーバに負荷をかけられ本来の機能を実現できなくなってしまったりします。なんといっても、ほかの人に迷惑をかけてしまう可能性があり、非常に深刻な問題となります。
なぜ、このような問題が起きてしまうのかというと、SMTPでの通信にあたって、特にパスワード認証などが行われていないためです。適切な設定ができていないと、赤の他人によって利用されて不正中継などの問題を生むのです。
したがって、通常は、あらかじめリレーを許可するマシンのIPアドレスを登録しておき、SMTP接続されると、毎回そのリストと相手のIPアドレスを比べることで自サーバ宛以外のメールを受け付けるかどうかを判定します。最近では、固定されたIPアドレス情報だけでなく、POP before SMTPやSMTP Auth などといった手法を用いて制限する方法も利用されています。
メールの形式
メールを構成する基本要素
メール(メッセージ)はテキスト形式のデータであり、大きく分けて「ヘッダー部」と「ボディ部(本文)」の2つの部分で構成されます。メールはヘッダー部で始まり、区切りのための空行が1行、そしてボディ部の順に現れます。
メールにはASCII文字だけを含めることができます。よってASCII文字以外のコードが含まれるバイナリーデータや、SJIS(Shift_JIS)やEUC-JPコードで符号化されている日本語を含めることはできません。バイナリーデータをメールで送付したい場合は、バイナリーからASCIIテキスト形式に変換しなければなりません。また、日本語を含めるときはJIS(ISO-2022-JP)コードを用います。
ヘッダー部に日本語を含めたい場合は、JISコードの日本語文字列をさらにMIME(Multipurpose Internet Mail Extensions)エンコードと呼ばれる形式で符号化する必要があります。
メールヘッダー部の形式
メールのヘッダー部には、件名、送信者と送付先の名前やアドレス、日付、配送経路などの情報が含まれています。各情報は「フィールド」と呼ばれる単位で保持され、1つのフィールドは次のような形式になっています。
フィールド名: フィールド内容
代表的なフィールドとその内容と意味を紹介
From:フィールド | メール送信者のアドレス情報 |
To:フィールド Cc:フィールド | あて先:Toは本来伝えたい相手、Ccは関係者などに使い分ける |
Bcc:フィールド | 内容・用途はCcフィールドに同じ、Bcc:はあて先アドレスを隠蔽するために利用される |
Reply-To:フィールド | メールの返信先アドレスを指定 |
Subject:フィールド | メールの件名 |
Date:フィールド | メールの送信日時 |
Message-ID:フィールド | メールを一意に特定するために識別子。メールクライアントが自動的に付加する |
Received:フィールド | メール配送システム(MTA)が付加する受信情報。受信元と配送システムのホスト名とIPアドレス、受信した時間などが含まれる |
メールアドレス
メールアドレスは、アットマーク「@」を境に2つの部分から構成されます。
user@example.gr.jp
※user = ローカル部、example.gr.jp = ドメイン部
ローカル部(local part)は】ユーザー名、ドメイン部(domain part)は、ユーザーが所属するサイトを識別するホスト名あるいはドメイン名。
エンベロープアドレス
メール配送システムは、メールクライアントやほかのメール配送システムからメールを受信するときに、送信者アドレスと宛先アドレス、そしてメールのメッセージを受け取ります。ここで注目すべきは、メール配送システムは、送信者と宛先のアドレス情報を得るためにメールのヘッダー部は参照しないという点です。
メールクライアントでメールを作成するとき、送信者と宛先のアドレスは、メールヘッダー部のFrom:/To:フィールド(あるいはそれに相当する入力欄)に指定することと思います。作成したメールの送信を指示すると、メールクライアントはメールのヘッダー部の該当フィールドから送信者のアドレスと宛先アドレスを抜き出し、そのアドレスとメールメッセージを配送システムに渡します。
通常、メールがメールクライアントから送出された後は、メールヘッダー内のメールアドレスが配送に影響を与えることはありません。
インターネットメールの配送にかかわる要素を従来の郵便物による配送に当てはめると次のように対応します。
インターネットメール配送 | 郵便による配送 | |
宛先アドレス | → | 封筒の宛先欄に書かれている住所 |
送信者アドレス | → | 封筒の送信者欄に書かれている住所 |
メール(メッセージ) | → | 便箋(封筒の中身) |
このように、メール配送における宛先と送信者のアドレスは、封筒(envelope)に書かれた宛先と送信者の住所のようなものです。実際、メール配送における宛先アドレスのことを「エンベロープ受信者アドレス(envelope recipient address)」、送信者のアドレスのことを「エンベロープ送信者アドレス(envelope sender address)」と称します。その両方を指して「エンベロープアドレス」と称します。
qmail
セキュリティへの配慮
qmailでは、開発時にセキュリティホールに対して極めて厳格なポリシーのもとに開発されているため、非常に堅牢といえます。たとえば、セキュリティーホールを生み出しやすいCライブラリを利用せずに、Bernstein氏が用意したライブラリを利用しているなど工夫がなされています。このほかに、qmailではセキュリティ向上のために、次のような工夫がなされています。
- 構成を単純にする
- 相互には信用しない機能別のプログラムに分割する
- root権限でする仕事は最小限にする
- setuidすることは最小限に抑える
安全性の確保
sendmailをはじめとして従来は、mbox形式やmhフォルダ形式が採用されていました。しかし、これらはメール配送中にマシンがクラッシュすると、メールデータが破壊される可能性がありました。そこで、qmailでは、新しい方式としてmaildir形式を採用しています。この方式では、各メールデータがそれぞれ独立して扱われることで、mbxo形式やmhフォルダ形式に見られるトラブルを防ぐことができます。
高速なメール配送
大量のメールを配送を短時間で完了するためにはそれなりの工夫が必要です。その点では、qmailではデフォルトでかなりの配送速度を実現しています。
qmailの構成
qmailは非常にシンプルな構成をとっています。ここでは、qmailのディレクトリ構造やプロセス構造を中心に見ていきます。
qmailのディレクトリ構造
qmailでは、/var/qmail以下に各役割を持つディレクトリを利用します。各ディレクトリはqmailの動作にとって非常に重要な意味を持っています。
bin | 実行ファイルが配置 | |
control | 動作設定ファイルが配置 | |
alias | 転送設定ファイルが配置 | |
/var/qmail | queue | キュー管理用ディレクトリ |
doc | ドキュメントファイルが配置 | |
man | マニュアルが配置 | |
boot | 起動スクリプト | |
users | qmail-lspawnが生成するユーザーデータベースファイル配置 |
qmailのプロセス
qmailは、1つのプログラムファイルではなく、複数のプログラムで成り立っています。これは、郵便局員にたとえると「1人がポストから集配を担当し、1人が仕分け作業、もう1人が配達を」といった具合に、役割ごとに作業を分担を行っているのです。
qmialの中心となるプロセスとして、qmail-send, qmail-clean, qmail-lspawn, qmail-rspawn, sploggerの5つがあげられます。この5つのプロセスは常に起動していて、キューの確認やメッセージの配送を行います。
qmailのプログラム群
qmailには多くのプログラムが準備されています。実際、/var/qmail/bin 以下を確認すると40近くのプログラムがあります。この中には、qmailを操作したり、メールを送信するためのユーティリティがあります。ユーティリティの中には、単体で起動し実行するものと、ほかのプログラムと連携して利用するものがあります。
プログラム | 役割 |
qmail-inject | コマンドライン版のメールクライアント |
qmail-smtpd | SMTP経由でメールを受信する。受信したメールは qmail-queue に渡される |
qmail-queue | メールをキューに登録する |
qmail-clean | システムがクラッシュしたときににキュー内に残された不要なファイルを削除する |
qmail-send | キュー上のメールの配送制御を行う |
qmail-lspawn | qmail-localを呼び出してローカルユーザ宛のメールを配送させる。qmail-sendから呼び出される |
qmail-local | ローカルユーザ宛のメールを配送する |
qmail-rspawn | qmail-remoteを呼び出してリモートユーザ宛のメールを配送させる。qmail-sendから呼び出される |
qmail-remote | リモートユーザにメールを配送する |
qmail-showctl | 現在の設定を表示する |
qmail-start | メールの配送のためのプロセス qmail-send、qmail-lspawn、qmail-rspawn、qmail-cleanを起動する |
qmail-qmtpd | QMTPでの接続を受け付ける |
qmail-pop3d | POP3の接続時に、ユーザーのメール読み込み・削除を支援する |
qmail-popup | POP3の接続時に、ユーザ・パスワード情報を確認するために利用する |
qmail-qread | キューにあるメールの情報を表示する |
qmail-qstat | キューにたまっているメールの数を表示する |
qmail-tcpto | qmail-remoteのタイムアウトテーブルを表示する |
qmail-tcpok | qmail-remoteのタイムアウトテーブルを初期化する |
sendmail | sendmailコマンド互換のインターフェースを持つプログラム。sendmailの置き換えのために準備されている |
splogger | syslogに各種ログを渡す |
tcp-env | ネットワーク接続時の情報を環境変数に設定する |
qbiff | 新着メールが届くと画面にその旨を表示する |
maildir2mbox | maildir形式のメールボックスをmbox形式に変換する |
maildirmake | maildir形式のメールボックスを作成する |
maildirwatch | 環境変数MAILDIRに指定されたメールボックスの新着メールを表示する |
qmail-newmrh | 設定ファイルmorercpthostsからデータベースファール morercpthosts.cdbに書き出す。このファイルはqmail-smtpdが利用する |
qmail-newu | 設定ファイル /var/qmail/users/assignの情報を、データーベースファイル /var/qmail/users/cdbに書き出す。このファイルは qmail-lspawnがりようする。 |
qmail-pw2u | /etc/passwdなどのユーザ情報ファイルを標準出力から読み込み、/var/qmail/users/assignに出力する |
qmailの設定ファイル
qmailは設定情報に基づいて動作します。qmailの設定ファイルは/var/qmail/controll 以下に配置することになっています。
qmailでは、1つの設定項目に対して、1つのファイルが割り当てられています。ファイル名が設定項目名であり、ファイルの本文が設定値となります。設定項目によって設定値を1つだけ指定できるものと複数できるものがあります。複数指定する場合は、1つの設定ファイルを記述するごとに改行することで、1行に月1つの設定値を記述するようにします。
必須の設定ファイルはmeとrcpthostsだけです。(厳密には不正中継の可能性がなければmeのみでも動作します)
qmail全般の設定
設定ファイル | 初期値 | 設定内容 |
me(※) | なし※必須 | qmailが稼動するホストのFQDN(Fully Qualified Domain Name)を記述する |
badmailfrom | (none) | 拒絶アドレスリスト |
bouncefrom | MAILER-DAEMON | 差戻し管理者名 |
bouncehost | me | 差戻しホスト名 |
concurrencylocal(※) | 10 | ローカル配送多重度 |
concurrencyremote(※) | 20 | リモート配送多重度 |
databytes | 0 | 受信データ量上限 |
defaultdomain(※) | me | メールの送信先(To:)にドメイン名が無い場合に補完するドメイン名を記述する |
defaulthost | me | 省略時ホスト名 |
doublebouncehost | me | 2重バウンスホスト名 |
doublebounceto | postmaster | 2重バウンスの宛先 |
envnoathost | me | ホスト省略時ドメイン名 |
helohost | me | SMTP開始ホスト名 |
idhost | me | Message-IDホスト名 |
localiphost | me | 当ホストの対応IPアドレスを指定 |
locals(※) | me | qmailが受信するメールのホスト名とドメイン名を記述する |
morercpthosts | (none) | 受信ドメイン一覧(2)rcpthostsの補助的役割に使用 |
percenthack | (none) | %ハック適用ドメイン名一覧 |
plusdomain | me | 追加ドメイン名 |
qmqpservers | (none) | qmqpサーバリスト |
queuelifetime | 604800 | メールがキューに保存される秒数 |
rcpthosts(※) | (none) | qmailが受信するメールのホスト名とドメイン名を記述する |
smtpgreeting | me | SMTP応答用ホスト名 |
smtproutes | (none) | SMTP経路指定 |
timeoutconnect(※) | 60 | 接続時待ち時間 |
timeoutremote(※) | 1200 | 応答待ち時間 |
timeoutsmtpd(※) | 1200 | SMTPデータ待ち時間 |
virtualdomains(※) | (none) | 仮想ドメイン名一覧 |
qmailと環境変数
qmailでは、UNIXの環境設定を巧みに利用しています。環境変数を利用することで設定値を(設定ファイルを越えて)変更することができます。たとえば、SMTPでのメール受信時に環境変数RELAYCLIENTが指定されていると、qmail-smtpdはcontrol/rcpthostsの設定を無視し、どんな宛先のメールでも受信するようになります。
環境変数はそれを解釈する各プログラムを実行する前に設定します。これを実現するのが、tcpserverやTCP wrappers(tcpd)などのプログラムです。
これらは、外部からの接続があると指定されたプログラムを起動して接続に対応しますが、そのときに接続情報などを環境変数として渡すことができます。
qmailによるメール配送のしくみ
qmailでは、複数のプログラムによってメールの配送が行われます。配送に当たっては、9つのプログラムが主にかかわっています。
図 => A high performance MTA, qmail (Make full use of qmail, a high performance mail transfer agent)
qmail-smptd
qmail-smtpdは外部ホストからの接続によってメールを受け取り、qmail-queueにそのメール情報を渡します。
qmail-smtpdには外部からの接続を直接受け付ける機能がないため、tcpserverやinetdなどのプログラムが利用されます。これらは、外部ホストからSMTPでの接続があると自動的にqmail-smtpdを起動し、接続の橋渡しをします。
qmail-smtpdを起動されSMTPでの接続が確立されると、外部ホストからメールを受け取ります。その様子は下記のようになります。telnetでSMTPのポート(25番)に接続し、メールを送っています。
$ telnet mail.hogehoge.com 25 Trying 121.119.174.207... Connected to mail.hogehoge.com. Escape character is '^]'. 220 mail.hogehoge.com ESMTP HELO mail.hogehoge.com 250 mail.hogehoge.com MAIL FROM: fuga@mail.hogehoge.com 250 ok RCPT TO: bar@mail.hogehoge.com 250 ok DATA 354 go ahead To: bar@mail.hogehoge.com Subject: Test From: fuga@mail.hogehoge.com test mail . 250 ok 1239692617 qp 3222 QUIT 221 mail.hogehoge.com Connection closed by foreign host.
qmail-inject
qmail-injectはコマンドライン用のメールクライアントです。ローカルからのメール送信を受付、qmail-queueにそのメール情報を渡します。
qmail-injectは、標準入力からメールを受け取ります。その後必要に応じて、ヘッダ情報を整形します。たとえば、From:情報がない場合、qmail-injectを起動したユーザーや環境変数の情報をもとにFrom:をヘッダに付け加えます。
qmail-send
qmail-sendjは、絶えずキューを確認してメール配送の管理を行っています。キュー上にメールがあれば、qmail-rspawnやqmail-lspawnプログラムに対してそのメールを配送するように促します。メールの宛先がローカルユーザのときはqmail-lspawn、リモートユーザの時はqmail-rspawnとなります。
qmail-clean
qmail-queueやqmail-sendがキュー内のファイルを操作している最中にシステムがクラッシュすると、キュー内に処理途中の不完全なファイルが取り残されてしまうことがあります。qmail-cleanは、そのようにして残されたゴミファイルを削除します。
qmail-rspawn
qmail-rspawnは、リモートユーザー宛のメールを配送する場合に、qmail-sendから呼び出されます。その後、qmail-rspawnは、qmail-remoteを起動しメールの配送を実行させます。
キュー
qmailのキュー
配送待ちのメールはキューと呼ばれるしくみによって管理されます。キューは複数のディレクトリを用いることで、キュー内のメールの状態がわかるようになっています。qmailのキューはディレクトリ /var/qmail/queue以下のサブディレクトリによって管理されています。
新しいメールは、まず一意なファイル名が付けられ、キューに格納されます。その後、qmail-localやqmail-remoteによって配送されることになります。
キューのサブディレクトリ
ディレクトリ | 中身 |
pid | 空のファイル(メールをキューに登録するときに利用) |
mess | メール(メッセージ) |
intd | 送信者と宛先のアドレス(アドレスをキューに登録するときに利用) |
todo | 送信者と宛先のアドレス(qmail-queueからqmail-sendに渡すときに利用) |
info | 送信者のアドレス |
local | 宛先のアドレス(ローカル配送) |
remote | 宛先のアドレス(リモート配送) |
bounce | 配送に失敗したメールの情報(宛先アドレスとしっぱりの理由) |
lock | ロックファイル |
qmailのインストール
※一番最後に記述しました。
maildir形式のメールボックスの利用
メールボックスの配置場所は、各ユーザのホームディレクトリの「Mailbox」という名前ファイルになります。qmailでは、mbox形式以外に、maildir形式のメールボックスを利用することができます。
maildir形式のメールボックスは、mbox形式のように1ファイルに複数のメールを格納することはしません。専用のディレクトリを作り、その中に1メール1ファイルという形式で保管します。このことで配送効率を上げ、安全性を向上します。ただし、その一方でmaildir形式に対応していないアプリケーション(メールクライアント、POP/IMAPサーバなど)があるので、相性の面で注意が必要です。
maildir形式を個人的に利用する場合は、自分のホームディレクトリに .qmail というファイルを作成し、そのファイルに次のように記述しておきます。
■.qmailへの記述
./Maildir/
また、自分のホームディレクトリに maildir形式に対応したディレクトリを作成する必要があります。maildir形式のメールボックスを作成するためには maildirmake を利用します。このとき、作成されたメールボックスの所有者・パーミッションには注意が必要です。
$ cd $ pwd /home/user $ /var/qmail/bin/maildirmake Maildir
これで、このユーザーへ配送されるメールはmaildir形式のメールボックス ~/Maildir へ配送されます。
一方、すべてのユーザーに対して maildir形式を利用する場合は、 /var/qmail/rc を修正するほうが効率が良いでしょう。
■/var/qmail/rcの修正
(修正前) qmail-start ./Mailbox splogger qmail
(修正後) qmail-start ./Maildir/ splogger qmail
これで、qmailを再起動すれば、maildir形式でメールが配置されるようになります。ただし、このときも各ユーザに対して maildirmake で maildir形式のディレクトリを作成させる必要があります。
ユーザーを追加するたびに、コマンド maildirmake を実行するのは面倒なため、Linuxなどでは次のようにしておくとよいでしょう。
■実行例
# /var/qmail/bin/maildirmake /etc/skel/Maildir
これで、ユーザを追加をするときに、ホームディレクトリに maildir形式のディレクトリができるようになり、便利です。useraddは、ユーザのホームディレクトリを作成するときに、/etc/skel 以下のファイルやディレクトリをコピーしてくれます。
SMTPサーバの設定
qmail環境でSMTPサーバを構築するには、qmail-smtpdを利用します。しかし、qmail-smtpd自体にはSMTP接続を受け付ける機能はありません。したがって、tcpserverやinetd, xinetdなどのスーパーサーバーを経由してSMTP接続を受け付けます。
tcpserverはqmailの作者であるD.J.Bernstein氏が作ったサーバ制御ツールです。
tcpserverにおけるリレー設定
リレーを許可するホストのアクセス制御情報を記述したデータベースファイルを準備する必要があります。このデータベースファイルを tcpserver が認識することおで、リレーの許可がうまく適用されることになります。tcpserverではデータベースファイルとして cdb という形式を採用しています。
それでは、このエータベースファイルである cdb ファイルを作りましょう。cdbファイルを作成するためにファイル /etc/tcp.smtp を準備します。
172.25.0.:allow,RELAYCLIENT=""
127.:allow,RELAYCLIENT=""
これはIPアドレスが172.25.0.*と127.*.*.*(*は任意)であるホストからの接続に対しては、環境変数RELAYCLIENTを設定するという意味です。 qmail-smtpdにRELAYCLIENTが渡されると、その接続に対しては(tcpthostsにかかわらず)リレーが許可されます。
それでは、このファイルtcp.smtpを用いてデータベースファイル tcp.smtp.cdbを作成しましょう。作成にはtcprulesコマンドを用います。コマンド tcprulesの書式は以下のとおりです。
tcprules <生成するcdbファイル> <生成時に利用する一時ファイル>
今回の場合は、以下のようになります。
■実行例
# /usr/local/bin/tcprules /etc/tcp.smtp.cdb /etc/tcp.smtp.tmp < /etc/tcp.smtp
これでデータベースファイル /etc/tcp.smtp.cdb が生成されます。一時ファイルはコマンド tcprulesを実行し終えたら、自動的に削除されます。
では、このデータベースファイルを使って tcpserverを起動し、qmail-smtpdが特定のホストからのリレーを受け付けるように設定しましょう。tcpserverはオプション -x cdb ファイルでデータベースファイルを読み込むようになっているため、次のようにします。
■tcpserverにアクセス制御データベースファイルを指定して起動
# nohup /usr/local/bin/tcpserver -HR -x /etc/tcp.smtp.cdb -u 502 -g 501 0 smtp /var/qmail/bin/qmail-smtp &
これで、/etc/tcp.smtp に記述したとおりにリレーが実現されるようになっているはずです。
※-u 502 -g 501 はqmaildのユーザID、nofilesのグループIDです。
$ id -u qmaild 502 $ id -g qmaild 501
tcpserverの書式とオプション
tcpserverの書式は次のとおりです。
tcpserver [オプション] <監視IPアドレス> <監視ポート> <デーモンプログラム>
オプション | 役割 |
-c 接続数 | 同時に起動できる接続数の上限を指定 |
-x cdb ファイル | cdbファイルに指定されたルールに従う |
-u UID | ポート監視開始後tの実行ユーザID |
-g GID | ポート監視開始後の実行グループID |
-h | 接続元のホスト名をDNSに問い合わせ、結果を $TCPREMOTEHOST に格納(デフォルト) |
-H | 接続元のホスト名をDNSに問い合わせない |
-p | ホスト名を調べた後、逆引きを問い合わせ、IPアドレスが一致しない場合、$TCPREMOTEHOSTの情報を削除する(デフォルト) |
-P | ホスト名を調べた後、逆引きを問い合わせない |
-r | 接続元ホストから、$TCPREMOTEINFOを 得る(デフォルト) |
-R | 接続元ホストから、$TCPREMOTEINFOを得ない |
POPサーバの設定
tcpserverによるPOPの設定
tcpserverを利用して、POPの接続を受け付けるようにしてみます。
その前に、準備として、checkpasswordプログラムを導入します。これはPOP接続時のユーザ・パスワード認証を担うものです。qmail-pop3dには、認証機能が実装されていません。すなわち、認証に関してはほかのソフトウエアに任せています(ここでは checkpassword です)。
$ tar xzvf checkpassword-0.90.tar.gz $ cd checkpassword-0.90 # make setup check
これにより、プログラムが /bin/checkpassword にインストールされます。
POPサーバの起動
基本的なやり方はSMTPサーバと同じです。
# nohup /usr/local/bin/tcpserver -HR 0 pop3 /var/qmail/bin/qmail-popup <サーバのFQDN> /bin/checkpassword /var/qmail/bin/qmail-pop3d Maildir &
サーバのホスト名が host.example.com の場合、次のようになります。
■実行例
# nohup /usr/local/bin/tcpserver -HR 0 pop3 /var/qmail/bin/qmail-popup host.example.com /bin/checkpassword /var/qmail/bin/qmail-pop3d Maildir &
SMTPの認証の必要性
メールサーバーを管理する上で、SMTPのリレーを許可する範囲を決めることは極めて重要な判断です。しかし、モバイル環境の発達した現在、SMTPサーバを外出先や出張先からも利用したいというニーズは少なくありません。しかし、インターネットのどこからでもリレーを許可するわけにはいきません。したがって、何らかの方法によって、接続相手を認識し、適切な相手のみに対してリレーを許可するという方法をとる必要があります。現在、これを実現する方法として、SMTP AUTHとPOP before SMTPがあります。
SMTP AUTHは、SMTPに対して認証を行うAUTHコマンドを拡張定義したもので、SMTPでの接続時にユーザ認証を行い、接続元の確認を行います。認証に成功すればリレーが許可され、そうでなければリレーは送信できません。
本来ならば、SMTP AUTHによる方法がシンプルですが、メールクライアント側での実装がなかなか進まないのが現状であるため、既存のSMTPとPOPをうまく組み合わせる方法が採用されています。それが、POP before SMTPです。これは、リレーを許可する相手を識別するためにPOPでのユーザ認証を利用します。SMTPによるリレー送信をする前にPOPでの接続を行い、そこでユーザ認証を行います。POPで認証が成功した接続元に関しては、その後の一定期間のリレーが許可されるようになります。すなわち、リレー送信をする前にあらかじめPOPでユーザー認証を行うというものです。
.qmailファイルの利用
.qmailファイルの役割
.qmailファイルは通常はユーザのホームディレクトリに置かれ、ユーザーに配送されたメールをどのように扱うかを制御します。メールの配送指定には、次のいずれかの方法を指定できます。
.qmailファイルを評価して指定された配送処理を実行するのは、qmail-localコマンドです。.qmailファイルが存在しない、あるいは.qmailファイルのサイズが0バイトの場合、qmail-localはqmail-startコマンドを介して指定されたデフォルトの配送方法を実行します。ただし、拡張メールアドレスの場合、対応する.qmailファイルが存在しないとき、メールはバウンスされます。
拡張メールアドレス
qmailが稼動しているシステムで自分宛のメールを受け取っているユーザは、自分のユーザー名に続いてハイフン「-」と任意の文字列を足したものをローカル部に持つ「拡張メールアドレス」を利用することができます。たとえば、yoursite.example.com ドメインのユーザー carol は、「carol@yoursite.example.com」のほかに「carol-anything@yoursite.example.com」といったアドレスでも受け取れます。
拡張アドレスは好きな数だけ用意することができます。ハイフン以降の「anithing」の部分は、メールアドレスのローカル部に含めることができる文字であれば、どんあものでもかまいません。ただし、末尾が「-default」、「-owner」となっているアドレスは特殊です。
非常時接続環境におけるメール送信
非常時接続環境における問題と解決方法
多くのMTAは、何らかの理由で配送先のメールサーバに接続できなかった場合、メールをキューに滞留し、しばらく時間をおいたあとに配送を再施行するようになっています。qmail(qmail-send)の配送の仕様もそのようになっており、一時的な理由で配送に失敗したメールは、しばらくキューに滞留し続けます。
MTAはこの特性を利用するならば、オフライン状態になるローカルの環境内に1つMTAサーバを用意して、ローカル環境のメールクライアントからのメール送信にそれを使用するように設定するだけで、目的は達成されます。
ローカルのqmailの配送経路の設定
オンライン時にDNSが利用できるなら、もちろんローカルのqmail自身に配送させることもできます。しかし特定のSMTPサーバーに配送をまかせることで、ローカルのqmailは宛先アドレスごとの送付先ホストの検索(ドメインのMXレコード検索)をしなくて済む分、配送にかかる時間を短縮できます。
また、わずかですが、ネットワークの帯域を節約できます。
qmail(qmail-remote)に静的な配送経路を指示するには、control/smtproutesファイルを指定します。control/smtproutesファイルの各行には、ドメイン名とそのドメイン宛のメール配送を依頼するSMTPサーバ名を、以下のような書式で記述します。
ドメイン名:SMTPサーバー名:SMTPポート番号
リモートへのメール配送をすべて特定のSMTPサーバに送るには、次のようにドメイン名を省略した行を記述します。ポート番号を省略すると、SMTP標準のポート番号(25)が利用されます。
■リモートへのメール配送をすべてISPのSMTPサーバーに以来する(control/smtpproutes)
:mailhost.isp.example.net
control/smtproutesファイルの設定を終えたら、オンライン状態でメールを送信し、正しく配送が行われることを確認してください。
ローカルのqmailに配送させたいなら
オンライン時にqmailが稼動するホストからDNSが利用できるなら、qmail自身に宛先ホストの検索(MXレコードの検索)と配送を行わせることができます。よって、先の節で解説したcontrol/smtproutesファイルの設定は必要ありません。
特定のドメイン宛のメールだけMXレコードに従い配送させたいという場合は、control/smtproutesファイルに宛先のSMTPサーバー名を省略した行を記述します。control/smtproutesの設定は、明示的にドメインが指定されている行のほうが優先されます。
■特定のドメイン宛のメールはMXレコードに従い配送させる(control/smtpproutes)
:mailhost.isp.example.net specific.domain.example.jp:
キューの最長滞留時間の調整
長期にわたりオフライン状態になる可能性があるなら注意が必要です。qmailはデフォルトで7日以上キューに滞留していたメールはバウンスし、送信者に返してしまいます。キューの視聴の滞留時間は /control/queuelifetime ファイルで設定可能です。通常であれば、このファイルを用意せずデフォルト(604800秒、つまり7日間)にしておけばよいでしょう。
SMTPによるメール配送を制限する
qmail(qmail-smtpd)は、SMTPのMAILコマンドで渡される送信者アドレス(control/badmailfrom)や、RCPTコマンドで渡される宛先アドレスのドメイン部(control/rcpthosts, morercpthosts)、DATAコマンドで渡されるメールのサイズ(control/databytes)により、メールの受信を拒否することができます。
大量メール配信時のパフォーマンス改善
送信処理の最大並列数の上限を上げる
■最大並列数に指定できる値の上限
qmailはメール配送処理を、複数のプロセスを生成し平行して実行します。ローカルユーザへの配送の最大並列数は control/concurrencylocal、リモートへの配送の最大並列数はcontrol/concurrencyremoteの設定により制限され、デフォルトの最大並列数はローカル配送は10、リモート配送は20に設定されています。大量のメールを配送する必要があるならば、配送処理の最大並列数をあげることで(ほかにボトルネックが生じない限り)、その分だけメール配送のパフォーマンスは向上します。
しかし、control/concurrencylocal、control/concurrencyremoteで指定できる並列数は、最大で120に制限されています。この制限は、qmailのコンパイル時、qmailのソースツリーに含まれる conf-spawnファイルに記述されている値で決まります。このファイルの値を増やしてqmailをコンパイルすることで、121以上の並列配送を実現できます。
しかしそれでも、conf-spawnファイルに記述できる最大並列の最大値は255に制限されます。これはqmail内部実装による制限です。
■最大並列数の上限を256以上にする
次のパッチを適用することで、qmailは256以上のプロセスを生成できるようになります。
■256以上の最大並列数を指定可能にするパッチ
big-concurrency.path
■このパッチの適用例
$ cd source/dir/of/qmail-1.03 $ patch -p1 < /path/to/big-concurrency.path
このパッチにより、実装として最大65536の並列実行に対応しますが、65000以下に制限するように作られています。conf-spawnファイルは1000に書き換わります。通常UNIXカーネルは、システム全体あるいはユーザごとに、同時に実行できるプロセスや扱えるファイル記述子の数、消費メモリサイズなどに制限をかけています。このパッチを適用しqmailの制限を増やすだけでなく、同時にカーネルパラメーターの調整を確認することを忘れないようにしてください。
qmailのインストール例
for Linux. qmail version 1.03。下記はCentOS5.2上で行ったものです。
■qmail $ su - # mkdir /var/qmail # groupadd nofiles # useradd -g nofiles -s /sbin/nologin alias -m -d /var/qmail/alias -k /dev/null # useradd -g nofiles -d /var/qmail -s /sbin/nologin -M qmaild # useradd -g nofiles -d /var/qmail -s /sbin/nologin -M qmaill # useradd -g nofiles -d /var/qmail -s /sbin/nologin -M qmailp # groupadd qmail # useradd -g qmail -d /var/qmail -s /sbin/nologin -M qmailq # useradd -g qmail -d /var/qmail -s /sbin/nologin -M qmailr # useradd -g qmail -d /var/qmail -s /sbin/nologin -M qmails # mkdir ~/src # cd ~/src # wget ftp://ftp.jp.qmail.org/qmail/qmail-1.03.tar.gz # tar zxvf qmail-1.03.tar.gz # cd qmail-1.03 # wget http://www.itheart.com/phpgw/qmail-date-localtime.patch # wget http://members.elysium.pl/brush/qmail-smtpd-auth/dist/qmail-smtpd-auth-0.31.tar.gz # wget http://qmail.mirrors.summersault.com/qmail-smtpd-relay-reject # wget http://www.qmail.org/big-concurrency.patch # tar zxvf qmail-smtpd-auth-0.31.tar.gz # /bin/mv qmail-smtpd-auth-0.31/* . # patch < qmail-date-localtime.patch # patch < auth.patch # patch < qmail-smtpd-relay-reject # patch -p1 < big-concurrency.patch # sed -i 's/1000/509/g' conf-spawn # vi error.h - extern int errno; + #include<errno.h> # make setup check # ./config-fast `hostname` # echo `hostname -d` >> /var/qmail/control/me # echo `hostname -d` >> /var/qmail/control/rcpthosts # echo `hostname -d` >> /var/qmail/control/locals # cd # echo "MANPATH /var/qmail/man" >> /etc/man.config ■checkpasswordインストール # cd ~/src # wget http://cr.yp.to/checkpwd/checkpassword-0.90.tar.gz # tar zxvf checkpassword-0.90.tar.gz # cd checkpassword-0.90 # vi error.h - extern int errno; + #include<errno.h> # make && make setup check # cd # chown root:nofiles /bin/checkpassword # chmod 4750 /bin/checkpassword ■tcpserverインストール # cd ~/src # wget http://cr.yp.to/ucspi-tcp/ucspi-tcp-0.88.tar.gz # tar zxvf ucspi-tcp-0.88.tar.gz # cd ucspi-tcp-0.88 # vi error.h - extern int errno; + #include<errno.h> # make setup check # cd # echo '127.:allow,RELAYCLIENT=""' > /etc/tcp.smtp # tcprules /etc/tcp.smtp.cdb /etc/tcp.smtp.tmp < /etc/tcp.smtp ■sendmailの停止 # /etc/rc.d/init.d/sendmail stop # chkconfig sendmail off # chkconfig --list sendmail # chmod 0 /usr/lib/sendmail # chmod 0 /usr/sbin/sendmail # mv /usr/lib/sendmail /usr/lib/sendmail.bak # mv /usr/sbin/sendmail /usr/sbin/sendmail.bak # ln -s /var/qmail/bin/sendmail /usr/lib/sendmail # ln -s /var/qmail/bin/sendmail /usr/sbin/sendmail ■qmail起動スクリプト作成 # cp /var/qmail/boot/home /var/qmail/rc # sed -i 's/Mailbox/Maildir\//g' /var/qmail/rc # yum -y install tcsh #yum list installed | grep tcsh で入っていたらいらない $ touch qmail $ vi qmail + #!/bin/bash + # + # qmail + # + # chkconfig: 2345 80 30 + # description: qmail start/stop script + + # Source function library. + . /etc/rc.d/init.d/functions + + PATH=/var/qmail/bin:/usr/local/bin:/bin:/usr/bin + + [ -f /var/qmail/rc ] || exit 0 + + start() { + # Start daemons. + if [ -z $(/sbin/pidof qmail-send) ]; then + echo -n "Starting qmail" + + # qmail + csh -cf '/var/qmail/rc &' 2>&1 > /dev/null + + # SMTP + tcpserver -qv -l0 -HR -u `id -u qmaild` -g `id -g qmaild` \ + -x /etc/tcp.smtp.cdb 0 smtp \ + qmail-smtpd `hostname` /bin/checkpassword /bin/true 2>&1|\ + splogger smtp & + + RETVAL=$? + echo + [ $RETVAL = 0 ] && touch /var/lock/subsys/qmail + return $RETVAL + else + echo "qmail is already started" + fi + } + + stop() { + # Stop daemons. + if [ ! -z $(/sbin/pidof qmail-send) ]; then + echo -n "Shutting down qmail" + /bin/kill $(/sbin/pidof tcpserver) + /bin/kill $(/sbin/pidof qmail-send) + until [ -z $(/sbin/pidof qmail-send) ] && [ -z $(/sbin/pidof tcpserver) ]; do :; done + echo + rm -f /var/lock/subsys/qmail + else + echo "qmail is not running" + fi + } + + case "$1" in + start) + start + ;; + stop) + stop + ;; + restart) + stop + start + ;; + status) + if [ ! -z $(/sbin/pidof qmail-send) ] ; then + echo -n "qamil (pid" + echo -n " `/sbin/pidof qmail-send`" + echo -n " `/sbin/pidof tcpserver`" + echo ") is running..." + else + echo "qmail is stoped" + fi + ;; + *) + echo "Usage: qmail {start|stop|restart|status}" + exit 1 + esac + + exit 0 $ sudo cp qmail /etc/rc.d/init.d/qmail $ sudo chmod +x /etc/rc.d/init.d/qmail ■qmail起動 # /etc/rc.d/init.d/qmail start # chkconfig qmail --add # chkconfig qmail on # chkconfig --list qmail ■Maildir 作成 # /var/qmail/bin/maildirmake Maildir ## root $ /var/qmail/bin/maildirmake Maildir ## 一般ユーザー