qmailオフィシャルサイト: http://www.qmail.org/
解説: Life with qmail, Qmailwiki

qmail

2007年11月30日、qmail の作者 Daniel Julius Berstein 氏 (当文執筆現在、イリノイ大学の数学教授) は、qmailライセンスを放棄し、再配布を自由化した。これまで、qmail は、改造を加えての再配布を極度に制限した D.J.Bernsein 独自規定によるライセンスの下に配布されており、ここ数年来、「GNUにして普及を促すべき」との議論も行われていた。そうした再配布の制限が、Linux ディストリビューションによる qmail 正式採用を阻害してきたことは疑いようもない。(敵対というわけではないけれど) これが、qmail 発祥の Maildir 方式を取り入れた Postfix の一人勝ち状態を生んだこともまた明白だ。本当の意味でのフリーとなった qmail はこれから、あらかじめ各種の機能拡張パッチを適用したり独自のチューニングを施したバイナリパッケージとして、単独あるいは別の商用パッケージの一部として方々で配布されるようになっていくかもしれない。ただし、少々時を逸した感が否めないのも事実だ。
セットアップ方針
netqmail と qmail-vida を組み合わせたインストールは少々趣が異なるので、インストール手順のもうひとつのバリエーションとして 別ページ にまとめた。そちらに沿ってインストールする場合には、あとでここに戻って一通り読んでもらうと、qmail の全体像がよくつかめると思う。

Table of Contents

インストールに必要なもの

qmail には、無垢のオリジナルソースと、それ及び主立ったパッチと幾つかのインストール補助スクリプトをセットにした netqmail-1.05 (Charles Cazabon, Dave Sill, Henning Brauer, Peter Samuel, Russell Nelson らによる) が存在する。後者をベースにしたほうが、パッチをすべて自力でかき集めるよりインストールは少し楽だ。

本体ソース

netqmail-1.05 qmail-1.03 ソース + 主なパッチ。こちらを推奨。 qmail のライセンスフリー化により、 netqmail-1.06 からはあらかじめパッチを適用した状態のソースから成る
qmail-1.03 qmail 本来のソース。左記リンク (http://cr.yp.to/qmail.html) 冒頭のリンクからダウンロードできる

機能拡張/修正パッチ

名称 内容 netqmail
に付属
qmail-local.c qmail-local.c にある分岐条件ミスを修正 (手作業)。
648行目
while ((k > i) && (cmds.s[k - 1] == ' ') || (cmds.s[k - 1] == '\t'))
while ((k > i) && ((cmds.s[k - 1] == ' ') || (cmds.s[k - 1] == '\t')))
という風に ( ) を追加して OR のほうを優先させる。パッチファイルは netqmail-1.05 に同梱されている
smtpd-auth SMTP認証機能を追加する。qmail-smtpd-auth-0.31ベースの古いパッチはこちら ×
date-localtime
(リンク切れ)
Received ヘッダのローカルタイムゾーン対応パッチ (コピー) ×
oversize-dns-patch qmail が「DNS を引いたとき返答の UDP パケットが 512 バイトを超えると処理できなくなる」を修正
moreipme RFC1122 に準拠して 0.0.0.0 がローカルホストを表すよう修正。また、"problem seen when a host has more IP addresses than it knows about" (意味がよく分からん) も修正
glibc errno errno の定義方法の変更。glibc のバージョンが 2.3.1 以降の場合必須。RedHat7.2 は大丈夫だった。Fedora Core では必要。netqmail-1.05 に付属
sendmail-flagf qmail 付属の sendmail ラッパーを、"-f" オプションで呼んだ時、本来の sendmail と同じようにデフォルト From: ヘッダを設定するように修正
QMAILQUEUE qmail-smtpd などが qmail-queue にメール処理を渡す前に、環境変数 "QMAILQUEUE" を読ませる。変数に qmail-queue 以外のプログラムを設定しておくことで処理のリダイレクトや挿入が可能となる。qmail-scanner を使う場合に必要
qregex-20040601 badmailfrom ファイル (smtp段階で受信拒否する from アドレス情報) 内に正規表現を使えるようにする。さらに、標準の qmail には無い badmailto, badhelo によるフィルタも可能になる。最新版は qregex-20040725 で、上記に加えて badmailfromnorelay, badmailtonorenay というファイルも読み取るようになったが、必要ないし、処理が複雑になるため他のパッチと干渉する可能性が高いので、敢えて 20040601 を使用する。その前の 0317 からの変更点は README がアップデートされただけ。
smtpd-auth パッチを当てた後だと、一部正常に patch できない。その場合、ソースディレクトリに .rej ファイルが吐き出されるので、そこだけ手動でソース編集すべし。
しかし、面倒くさいので、自分でパッチを作り直した (diff を取り直しただけで、内容に変更は加えていない) :
smtpd-auth + qregex-20040317 (netqmail-1.05用)
また、qmail-vida ともコードがバッティングするので、それ用のパッチも作成した:
qregex-20040601 (qmail-vida でパッチした後の netqmail-1.05用)
×
validrcptto
(リンク切れ)
qmail サーバへのディクショナリーアタックを防止するのに効果的な qmail-smtpd へのパッチ。qmail は元来、 rcpthots に設定されたドメイン宛ならば、宛先のユーザがサーバ上に存在するかしないかにかかわらず 「とりあえず」 受け取ってしまう。もし "ランダムに生成したユーザ名@自サーバ" 宛のスパムを大量に送り込まれたら、マシンパワーと帯域を空費され、キューは、バウンス不可能な不達通知メールで溢れてしまう。 このパッチを導入すれば、有効なメールアドレスを validrcptto ファイルにリストしておくことで、無効なユーザ宛のメールを SMTP セッション段階で拒否できる。
本来なら、qregex とはコードがバッティングするので併用は難しい。そこで、qregex と validrcptto の統合パッチを作成した。その過程で validrcptto ファイルにも正規表現を使えるように拡張した:
qregex-20040601 + validrcptto (netqmail-1.05用)
vida-qregex-20040601 + validrcptto (qmail-vida でパッチした後の netqmail-1.05用)
×

追加ユーティリティ [おすすめ]

checklocalpwd 1.0 pop3、smtp-auth の認証に、システムの passwd ファイルとは別の、専用のパスワードファイルが使える
mailquotacheck メールユーザのメールフォルダに容量制限を設ける shスクリプト
qmHandle キューを表示、削除できる perl スクリプト
Qmail-Scanner メールコンテンツスキャナ。メールのアンチウィルスやアンチSPAM の補助プログラムとして働く

その他のメジャーなパッチやユーティリティ

checkpassword qmail の作者 D.J.Bernstein による、パスワード認証用プログラム。glibc が 2.3.1 以上の場合は errno パッチが必要 (パッチは netqmail-1.05 に付属しているが手動による適用が必要)
cmd5checkpw checkpassword の機能拡張版で、CRAM-MD5 認証を可能にする
qmail-vida SMTP認証へのもうひとつのアプローチ。主として、qmail と checkpassword へのパッチと、メールアカウント管理プログラムから成る。いわば、vpopmail と smtpd-auth と cmd5cvheckpw などなどをひとつにしたようなもので、極めて多機能。SMTP認証には CRAM-MD5 による暗号化が使え、POP3認証では APOP が可能となる。パスワードファイルはシステムの passwd とは別個で、しかも cdb 化して扱うので高速。
qmail-vida を盛り込んだインストール手順は別ページにまとめた
ezmlm D.J.Bernstein による、qmail 用に作られたメーリングリストマネージャ
Majordomo メーリングリストマネージャ
qmail-vacation 自動返信ツール
QmailMSP SMTPセッションで、環境変数 SUBMISSION が設定されている時にはローカルユーザ宛てのメールも受け付けなくさせるパッチ。サブミッションポートを使用したSMTPの実装で利用する

追加ユーティリティ [強く推奨]

ucspi-tcp 0.88 xinetd の代わりとなるもの。qmail の作者が書いたプログラム。xinetd よりもきめ細かい制御ができる

ucspi-tcpに当てるパッチ

glibc errno

glibcが 2.3.1 以降の場合必須。netqmail に付属

△※
ucspi-rss
または
ucspi-tcp-0.88.a_record
ucspi-tcp 付属プログラムのひとつ rblsmtpd を改良する。rblsmtpd は、RBLチェックプログラム (リンク集を参照のこと)。qmail-1.03 開発時点では、不正ホスト情報をテキストで提供するRBLが多かったが、現在ではDNSのAレコード問い合わせ式が主流。このパッチは、rblsmtpd を Aレコード問い合わせに対応させる。 netqmail ソースには ucspi-tcp-0.88.a_record.patch のファイル名で付属 △※
ucspi-tcp-0.88.a_record
ucspi-tcp-0.88.nobase
上記 ucspi-rss を当てない場合 (Aレコードサーバを使わない場合) にのみこの2つを適用すべし。rblsmtpd がデフォルトで問い合わせに行くRBLは、もはやテキスト形式をサポートしていない。その点を修正。netqmail に付属 △※

※パッチはnetqmail-1.05/other-patches に付属するが、パッチ適用は手動で行う必要がある。

オリジナルスクリプト

qmail_ids qmail のインストールに必要なグループとユーザの作成を自動化するシェルスクリプト。 [2004/10/1] /var/qmail (変数にて簡単に変更可能) ディレクトリが未作成の場合、自動的に作成されるようにした
detectpid qmail、qmail-smtpd、qmail-pop3d の起動時にPIDファイルを正しく書き出すための、PID探知スクリプト
addpopuser メール専用ユーザを簡単に作れるシェルスクリプト
rmpopuser メール専用ユーザ削除スクリプト
qqclean キューに留まっているメールを選択的に削除するスクリプト
qmail のインストール

パッチ適用

netqmail-1.05 では、 ./collate.sh を走らせるだけで、qmail-1.03.tar.gz の解凍と付属パッチの適用が済んでしまう。それ以外のパッチだけ当てればよい。

※ netqmail-1.06 からは、qmail を改造して配布することが自由となったことを受け、あらかじめパッチの当たったソースが収録されいるため collate.sh はなくなった。

対象のパッチはqmailソースdirのひとつ上にあるとすると:

root# cd qmail_source_dir
root# patch -p1 < ../xxxx.patch

patchコマンドの -p オプションについて

path名の除去深度を指定。(ソース patch は早い話が "diff -u(rN) old new " の出力)
例)qmail-1.03 ディレクトリに居て、パッチファイル中での対象ソースファイルの指定が:

それでもうまくパッチが当たらない場合には、ファジー値を "-F 3" と高くしてみる手もある。 patch プログラム自体のファジー値のデフォルトはたいてい 2 。高くし過ぎると元ソースとの矛盾が起こる恐れがあるので、 3 を限度に。

qmailインストール前の準備 (ここからはrootに"su -"してから)

sendmailを殺す

RedHat 系 Linux では、システムがエラーメッセージを root に通知するために内部で sendmail を使っているため、OSインストール時に問答無用で sendmail がインストールされる。もう要らないので捨てる。RHEL6以降の場合は既定のMTAがPostfixなので、ここまで徹底的にやる必要はない。

service sendmail stop とにかく止める
chkconfig --del sendmail スタートアップスクリプトから外す
which sendmail 現在の sendmail バイナリはどこにあるか調べておく。おそらく /usr/sbin/sendmail
ls -l sendmail_bin_file RedHat, Fedora の場合、sendmail はシンボリックリンク () かもしれない
ls -l /usr/lib/sendmail /usr/lib/sendmail もあるだろう。確認しておく。リンク () かも
rpm -qa |egrep 'switch.*mail' MTA変更ユーティリティ "switchmail" がインストールされているか
rpm -e --nodeps sendmail sendmail をアンインストール (依存関係無視)
rpm -e --nodeps redhat-switch-mail (あれば) switchmail をアンインストール (依存関係無視)。 Fedora Core 2, 3 では system-switch-mail。 GNOME X環境を使っている場合はそのグラフィカルインターフェースである redhat (system) -switch-mail-gnome ももう要らない
RedHat 系 の sendmail リンクについて

RedHat Linux や Fedora Core で RPM によるメールエージェント (sendmail にしろ postfix にしろ) のインストールを行うと、 "sendmail" という実行ファイルは、 alternatives (標準プログラム変更ツール) や MTA変更ツールでの設定に都合が良いように、複雑なリンク構造を成す。 RPM インストールした MTA をすべてアンインストールするならこうした構造は残らないが、いずれかでも残っていれば、下のような構造 ( "->" はリンクを示す) になっている:

/usr/lib/sendmail -> /etc/alternatives/mta-sendmail -> /usr/lib/sendmail.sendmail -> /usr/sbin/sendmail -> /etc/alternatives/mta -> /usr/sbin/sendmail.<MTA> <MTA>はsendmail, postfix など

つまり、alternatives プログラムや switch-mail ユーティリティは、/etc/alternatives/mta のリンク先を変更していると推測される。こうしたことから、あとで sendmail ラッパーのリンクを張り直す際にちょっとコツがある。同じような構造を持っているものとして /usr/sbin/mailq, /usr/bin/rmail, /usr/bin/newaliases, /etc/pam.d/smtp があるので、興味があれば解析してみると良いだろう。

qmailシステム用ユーザの作成

まず qmail のホームディレクトリを作成:

root# mkdir /var/qmail

qmailの各プロセスが使用する user と group を作成 (ここでは gid と uid は600番台とするが自由) :

root# groupadd -g 600 nofiles
root# groupadd -g 601 qmail
root# useradd -u 600 -g nofiles -d /var/qmail/alias \
  -m -k /dev/null -s /sbin/nologin alias
root# useradd -u 601 -g nofiles -d /var/qmail \
  -m -k /dev/null -s /sbin/nologin qmaild
root# useradd -u 602 -g nofiles -d /var/qmail \
  -m -k /dev/null -s /sbin/nologin qmaill
root# useradd -u 603 -g nofiles -d /var/qmail \
  -m -k /dev/null -s /sbin/nologin qmailp
root# useradd -u 604 -g qmail -d /var/qmail \
  -m -k /dev/null -s /sbin/nologin qmailq
root# useradd -u 605 -g qmail -d /var/qmail \
  -m -k /dev/null -s /sbin/nologin qmailr
root# useradd -u 606 -g qmail -d /var/qmail \
  -m -k /dev/null -s /sbin/nologin qmails

※ RH7.x 時代は偽シェルは /bin/false だった。Ferora では nologin がいいようだ。

user と group の作成は、シェルスクリプトにしておくと便利。 qmail_ids

qmailコンパイルとインストール

ソースdir に cd して

root# make setup check

でインストールは完了。初めてのインストールの場合は、最低限の設定ファイルを生成するため、ソースディレクトリにて以下を実行する、。引数はメールサーバのドメイン名。詳しくは 「qmail の設定 (基本編)」 で述べる:

root# ./config-fast my_domain
ucspi-tcpのインストール

tcpserver (ucspi-tcp) の解説は専用ページに移したので、詳しくはそちらを参照。

必要なパッチを当てたあと、 ucspi-tcp ソース dir にて:

root# make
root# make setup check

qmail-smtpdのための設定

ucspi-tcp をインストールするのは、第一に、そのなかの tcpserver というプログラムを使いたいからだ。 tcpserver は、TCP ラッパーのようなもので、起動するプロセスの 実行UID, GID を指定したり、ルールファイルを指定することによってクライアントの IP アドレスによるアクセス制限を掛けたり、その際に環境変数をプロセスへ渡したりできる。 qmail に対してこれを使う主な目的は、SMTP サーバで、外 => このサーバ => 他の smtp サーバ のリレーを禁止し、オープンリレーになるのを防止することだ。この設定では、外からの SMTP セッションでは、リレーを許さない。一方、サーバ上から直接送信する場合には、他ドメインへの送信も可能。サーバ内部から自ホスト宛のメールも規制は受けない。

ルールテキストの作成

手順としては、テキストファイルにルールを記述してから、tcprules コマンドで cdb 形式のバイナリファイルに変換する。ルール cdb と元テキストは、 /etc/service/ に置くことにする。このファイルは、あとで、起動スクリプトの中で -x オプションを使って読み込む。ファイル名はなんでもいいのだが、わかりやすく tcp.smtp とでもしておこう。

設定例:
127.0.0.1:allow,RELAYCLIENT=""
:allow

「ローカル発の接続は、許可するとともに環境変数 RELAYCLIENT を設定する。その他は、接続は許すが RELAYCLIENT は設定しない」 の意。RELAYCLIENT は qmail-smtpd が利用する変数で、これが設定されていると、 rcpthosts に設定されていないドメインへのメールでも smtp 受付を行う。外部のネットワーク (多くはインターネット) を経由してこの smtp サーバを利用する場合、このサーバにメールアカウントを持つ正規のユーザも 「その他」 (:allow のほう) に該当するわけだが、 smtp-auth パッチでの拡張により、認証が通れば RELAYCLIENT が設定される仕組みになっているので、そうしたユーザも外部へのメール送信が可能となる。書式の概論は tcpserverのページ参照のこと。

cdbへの変換

tcprulesコマンドの概念については tcpserverのページ参照。

実際の作業例:
root# cd /etc/service
root# tcprules tcp.smtp.cdb tcp.smtp.tmp < tcp.smtp

tcpserverの起動書式

tcpserverのページ参照。

checklocalpwdのインストール

qmail-vida を導入する場合はこの行程は不要。

qmail の作者 djb は、checkpassword というパスワード認証プログラムを別途配布しているが、checkpassword はシステム本来のパスワードファイル (/etc/passwd) を使用するので、セキュリティ面で不安があるし、応用が利かない。それに対して checklocalpwd は、専用のパスワードファイルで認証を管理できる点で優れている。
インストールは、ただ単に、ソースdir に cd して "make install" で完了。 /usr/local/bin/ に、認証システムの御本尊であるバイナリ checklocalpwd と、パスワードファイル管理のための Perl スクリプト poppasswd_basicpoppasswd_change がインストールされる。

メール専用のパスワードファイルを作成

root# poppasswd_basic > /etc/poppasswd

で、システムの /etc/passwd を元に /etc/poppasswd を作成する (poppasswd_basicchecklocalpwd で提供される Perl スクリプト)。
メールに関係のないユーザの行をすべて削除する。 root の行も要らない。qmaild など qmail 関係で作成したユーザも poppasswd ファイルには不要。必要なのは SMTP または POP3 でメールをやりとりしたいユーザだけ。

各メールユーザのメール専用パスワードを登録

poppasswdファイルの書式:
メール用LoginID:cryptされたパスワード:システムユーザID:その人のメールホームPATH

後述の 「システムアカウントを増やさずにメールユーザを作る」 の場合はメール用とシステム上の LoginID は異なるが、システムアカウントを持つユーザの場合は、第1フィールドと第3フィールドは同じになる。
まだパスワードの部分は "!none!" となっているはず。

root# poppasswd_change メール用LoginID パスワードフレーズ

で各ユーザにパスワードを与える。「パスワードフレーズ」は生のパスワードでよく、 poppasswd_change スクリプトにより crypt() で暗号化されて poppasswd ファイルの第2フィールドに書き込まれる。

例えば "hoshu" というユーザを "somepassword" というパスワードで登録する例:

root# poppasswd_change hoshu somepassword