qmail の危険性について

安全性について

よく、安全性の面において qmail は最強だと言われています。特に、qmail 1.03 については、作者本人によるいくつかの security fix を除いてはセキュリティホールが見つかっていません。確かに安全と言えるでしょう。

しかし qmail を実際に利用する場面では、いくつものパッチを適用してから使用しないとほぼ使い物にならない状況です。現実に、この文書においてもそれは同様です。しかし、このパッチを適用した場合の安全性については誰が検証したのでしょうか。

qmail の安全性の神話はあくまで本体のみの話で、パッチを適用していない状況についての話であることを考慮する必要があります。

速度について

qmail は配送速度が非常に速いことから、メーリングリスト等の配送用サーバとして利用されることが多々あります。しかし、この利用法は本当に正しいのでしょうか?

qmail は 1 通 1 通のメールを、それぞれの配送先に対してセッションを張って配送しますが、これは配送先が同一ドメインの場合でも同様です。

他の MTA では、通常同一ドメインに対しては、1 回のセッションで複数の配送先に対してまとめて配送し、これにより配送時間を短縮することができます。

大規模なメーリングリストなどにおいては、同一ドメインに対する配送というのは良くあることであり、まとめ送りをしない qmail は配送時間の無駄が多くなってしまう可能性が高くなります。

例えば同一ドメインの配送メールが 50 通あった場合、他の MTA では 1 セッションの通信で送り終わるところを、qmail では 50 セッションの通信が発生することとなります。

セッションを張るというのは、比較的コストの高い行為で、実際にメールを配信する上ではかなり時間のかかる行為です。

単純に配送が早いという言葉を鵜呑みにせず、状況に合わせて Sendmail や Postfix などを使った方が、圧倒的に速い場合もありうるということをよく考慮しましょう。

spam について

qmail が開発された時代においては、spam がさほど大きな問題となっていませんでした。このため、qmail の分権思想は非常に優れた設計でした。現状でもそれは変わっていませんし、Sendmail などにおいても、既に root 権限を必要としない部分では root 権限を使用せずに動作させるように変わりました。

ところが、現状の存在しない送り先でも、とにかくメールを送りつけるタイプの spam に関しては、qmail は構造上非常に無力であるばかりか、他のネットワークに対しても非常に多大な迷惑をかけている、非常に迷惑な MTA となってきています。

存在しない送り先に対する spam ならバウンスするからいいじゃないか、という方もいらっしゃるかもしれませんが、そもそも最初から受け付ける段階において拒否してしまえばいいだけです。

これができない場合にバウンスメールが相手に配信される訳ですが、昨今の spam 状況では送り元を詐称していない場合が大半であり、本来 spam を送った訳ではない相手に対してバウンスメールが返っていくこととなります。

さらに、昨今の spam はかなり高い確率で送り元のメールアドレスすら詐称しています。この場合にはどういうことになるかというと、詐称されたドメインのメールサーバ管理者に、すさまじい数の postmaster notify が送られる事となります。参考までに、当サイトで一時期受け取っておいたこの postmaster notify の数を挙げますと、1 時間に 3,000 ~ 3,600 通程です。1 日では 72,000 ~ 86,400 通という数に上ります。

本来管理者が postmaster notify を受け取ってその内容を吟味する必要があるはずですが、このような状況下では現実的に考えて不可能です。こうした状況を作り出している原因の一端を担っているのが qmail であることは考慮するに値する事でしょう。

また、qmail にはバウンスメールを適切な形式で送信しない問題もあります。qmail 以外の MTA の事を考慮していないのです。Postfix などでは、バージョン 2.1 から qmail のような不正なメールアドレスをセットして送ってくるメールはエラーとして返すようになったようです。つまり、(素のままの) qmail から送られるバウンスメールの受け取りが拒否されてしまう状況です。

こうした事からも、qmail の利用に関しては慎重になる必要があると言えるでしょう。

この文書は FreeBSD 環境向けに作成していますが、qmail 自体別に FreeBSD に特化されている訳ではないので、いわゆる UNIX 的な環境では汎用的に利用するでしょう。

各種ファイルはこのサーバにコピーを置いておきますが、オリジナル配布サイトで最新バージョンの確認をしてください。(ここで配布されているバージョンと違った場合にご連絡頂けると幸いです。 (^^;)

また、不明な点、事実と異なる点等ありましたら、ツッコミ頂けると幸いです。 :)

qmail および関連ファイルの入手

qmail は高い安全性と信頼性、そして高速な配送性能と簡単な設定で利用できる、という特徴をもつ MTA です。

他の MTA との性能比較等は他のサイトにお任せするとして、とりあえずここでは qmail を利用することを決定した、という所から始めたいと思います。

まず、以下から必要なファイルを収集して来ます。

qmail 本体

http://www.jp.qmail.org/ などから qmail-1.03.tar.gz が入手できます。

checkpassword utility

クリアテキストによるパスワード認証に利用する checkpassword ユーティリティを http://cr.yp.to/checkpwd.html などから checkpassword-0.90.tar.gz が入手できます。

localtime patch

qmail は標準のままでは常に GMT (あれ、UTC だったかも (^^;) の Date フィールドを付けます。

これを不便だと思われる方は ftp://ftp.nlc.net.au/pub/unix/qmail/ などから localtime パッチが入手できます。

SMTP AUTH patch

qmail は標準では無認証でメールが送付されます。しかし、SMTP AUTH パッチを当てる事で SMTP でも認証が必要にすることができます。(できれば事前にユーザが SMTP AUTH 対応のメールクライアントを利用している事を確認してください)

基本的には簡単に第三者中継を行わない様にできますが、さらに安全性を高める事ができます。

ただし、 Outlook Express や Netscape Messenger などでは認証方式として LOGIN や PLAIN しか利用できなかったりします。 SMTP は基本的には暗号化されずに送付される事を考えると、最低限 CRAM-MD5 形式でパスワードを暗号化して送信できる様に設定した方が良いでしょう。

たとえ社内利用などでも、 LOGIN や PLAIN でしかパスワードが送信できないのであれば SMTP AUTH 以外の方法で安全性を高める (POP before SMTP & APOP とか) 方が良い様に思えます)

YAQSAPhttp://members.elysium.pl/brush/qmail-smtpd-auth/ などから qmail-smtpd-auth-0.30.tar.gz が入手できます。

さらに CRAM-MD5 で認証を行えるようにする為に、 http://members.elysium.pl/brush/cmd5checkpw/ などから cmd5checkpw-0.22.tar.gz が入手できます。

ただ、 2001/5/4 現在、 cmd5checkpw を利用した場合の脆弱性 が解決されていない様なので (この日付よりも cmd5passwd が古い為) 今回は導入を見合わせます。

cmd5checkpw を利用した場合の脆弱性は 0.22 と qmail-smtp-auth 0.26 以降の組み合わせでは解決されていますので、安心して利用することができます。

ご連絡頂きました Masato Toyoshima さん、ありがとうございました。

qmail IPv6 patch

qmail 1.03 は IPv6 対応になっていませんので、 IPv6 対応パッチを当てる事で IPv6 対応にできます。

http://www.rcac.tdi.co.jp/fujiwara/ などから qmail-1.03-v6-20001010.diff が入手できます。

tcpserver

qmail を SMTP デーモンとして立ち上げる際に、 inetd 経由でも利用できますが、より細かいアクセスコントロールと、 inetd の欠点 (TCP Wrapper を併用しないとアクセスコントロールができない点は最近の FreeBSD では標準搭載なので構わないのですが、高負荷時に 10 分程ログも残さずに応答が無くなる点など) を考えて見ると、 tcpserver によって SMTP デーモンを呼び出させる方が良いでしょう。

http://cr.yp.to/ucspi-tcp.html などから ucspi-tcp-0.88.tar.gz を入手できます。

なお、tcpserver は IPv6 対応パッチを利用する事で IPv6 対応にできるのですが、ルールを定義する為の tcprules 側の IPv6 対応が行われていない (20001/5 月末現在) ため、ルールを記述する事が出来ません。このため、事実上 IPv6 でのルール定義が不能となる為、IPv6 での利用を考える場合には inetd + TCP Wrapper がいいでしょう。

この他、追加したい機能がある場合にはそれぞれのパッチ等を入手しておいてください。その後、それぞれのアーカイブ等を入手して展開してください。

なお、当然の事ですがこれらの作業は root ユーザで行わない様にしましょう。 root での作業は必要なアカウントの作成、インストール、デーモン立ち上げ等の設定などだけで十分です。

ビルドとインストール

まずファイルを展開したり、パッチを当てたりします。

qmail 1.03 ビルド準備

とりあえず qmail のアーカイブを展開し、各種パッチを当てます。

% tar zxf qmail-1.03.tar.gz

% cd qmail-1.03/

% patch -p1 < ../qmail-date-localtime.patch

% patch -p1 < ../qmail-1.03-v6-20001010.diff

これらの作業が終ったら、 qmail-1.03/INSTALL.ids に従って必要なアカウントを作成します。

基本的には qmail-1.03/INSTALL.ids の FreeBSD 2.2 の欄をそのまま切り出して先頭の # を外したら sh に流し込むだけで ok なので、コピーを作って編集し、それを流し込むと簡単です。

ユーザのホームディレクトリが無い、と怒られる場合には # mkdir /var/qmail && mkdir /var/qmail/alias してください。

ここまでが終ったら、 qmail-1.03/ で % make します。

マシンが頑張ってがりがりとコンパイルしてくれますので、終った所で root になって # make setup check します。これによりセットアップに必要なチェックとインストール作業が行われます。既に qmail を利用していてデーモンが立ち上がっている場合はこの時点で kill してください。

無事インストールされたら、ホスト情報を準備する為に # ./config-fast `hostname` します。(本来は DNS の参照したりなんだりするので ./config 使った方が良いですが、ここでは簡便に……当然の事ながら、 hostname は 設定しておいてくださいね)

次に root/postmaster/mailer-daemon 宛のメールを受け取れるようにします。 qmail では root にはメールが配送されませんので、 alias に root を作っておかないと root@yourdomain のメールが受け取れなくなってしまいます。

# cd /var/qmail/alias && echo -n '&(your account)' > .qmail-root && cp .qmail-root .qmail-postmaster && cp .qmail-root .qmail-mailer-daemon (your account の部分はあなたが標準で利用するアカウント名にしてください)

標準では touch するだけなのですが、転送先アカウントを設定しておくと root/postmaster/mailer-daemon 宛のメールが自分に来るようになるので便利です。管理用に別アカウントがあるのであれば、そちらに転送する様にしてください。

配送デーモン群を立ち上げる為に # cp /var/qmail/boot/home /var/qmail/rc && /bin/csh -cf '/var/qmail/rc &'します。

# ps ax | grep qmail して、 qmail-lspawn/qmail-rspawn/qmail-send/qmail-clean 等が居れば ok です。

ローカル配送テスト

ローカル配送用には /var/qmail/bin/qmail-inject を使います。 Solaris にある mailx コマンドみたいな物ですね。

とりあえず .qmail ファイルを書かずにテストすると ~/Mailbox に標準では落ちますので、 % echo To: `whoami`@`hostname` | /var/qmail/bin/qmail-inject します。 ~/Mailbox が出来ていたら (そして cat して内容に問題が無かったら) ローカル配送は正しく行われています。安心して smtpd のテストに進みましょう。

ローカル配送が正しく行われていなかったら root で /var/qmail/bin/qmail-qstat してみて、キューにメールが残っているかどうかを確認し、 /var/log/maillog に出ているであろうエラーメッセージを確認しましょう。

SMTP デーモンの立ち上げ

tcpserver のルールファイルを作成します。とりあえず、ローカルホストからとローカルネットワークからのリクエストの場合のみ、環境変数 RELAYCLIENT を設定する事にします。

# mkdir /usr/local/etc/tcp && cd /usr/local/etc/tcp

# echo '127.:allow,RELAYCLIENT=""' > smtp.rule

# echo '192.168.0.:allow,RELAYCLIENT=""' >> smtp.rule

# echo ':allow' >> smtp.rule

これにより、 127.0.0.0/8 からと 192.168.0.0/24 からの配送要求に関しては /var/qmail/control/rcpthosts の制限を受けなくできます。

これは、第三者中継を受け付けなくする為のもので、 control/rcpthosts に書かれていないホスト宛のメールは送信を拒否するようになります。しかし、このままでは他のホスト宛のメールを送信できませんので、特定のアドレスからアクセスがあった場合には control/rcpthosts に書かれていないホストへもメールの送信要求を受け付けるようにします。

ただ、このファイルを書いただけでは tcpserver は参照できませんので独自 DB 形式にコンバートする必要があります。

# tcprules smtp.cdb smtp.tmp < smtp.rule

これで tcpserver を起動する準備が出来ました。 port 25 で既に何かが listen していたら先に殺しておいてください。(標準では sendmail が立ち上がっているのではないでしょうか。私は真っ先に rc.conf から inetd_enable="NO" と sendmail_enable="NO" をするので覚えていませんが…… (^^;)

まず最初に smtpd を立ち上げるユーザである qmaild のユーザ ID とグループ ID を確認します。そして、そこで得られたユーザ ID とグループ ID で起動します。

# grep qmaild /etc/passwd

qmaild:*:50000:3000:User &:/var/qmail:/nonexistent

仮に、上のような場合は以下のように起動します。

# /usr/local/bin/tcpserver -u 50000 -g 3000 -x /usr/local/etc/tcp/smtp.cdb 0 smtp /var/qmail/bin/qmail-smtpd &

プロセス ID が表示されたら ps ax | grep tcpserver してしっかり立ち上がっている事を確認して見てください。

無事立ち上がっていたら telnet localhost 25 して話しかけられることを確認して見てください。話しかけられたら、とりあえず自分自身に対して SMTP 経由で配送できる事を確認してください。

次に、他のホストから telnet xxx.xxx.xxx.xxx 25 して話しかけ、配送テストを行ってみてください。この際、ルール定義で RELAYCLIENT の設定を行うホストと行わないホストの差を確認しておくと良いでしょう。

SMTP AUTH を有効にしている場合は先に cmd5passwd などをインストールしないと送信できないことになるでしょう。

起動スクリプトの作成

FreeBSD では /usr/local/etc/rc.d/ にスクリプトを置いておくと、 boot/shutdown 時に自動でそれぞれ start/stop のパラメータを渡して呼び出してくれるので、これを利用して起動/終了処理を書いておきましょう。

私の環境で利用しているスクリプトを置いておきますので、参考にしていただけると幸いです。

基本的には start の場合は単純に起動処理を、 stop の場合は PID を検索して終了処理を、 restart の場合は自分自身を stop してから再度 start する、というだけのスクリプトです。

stop の処理は他の環境では ps の表示内容に合わせて参照する位置を変更して頂けば簡単に再利用できるのではないでしょうか。

現状

この文書を書いた当人である管理者自身はとっくに qmail を捨て、設定が非常に簡単で、わざわざパッチを当てなくても多彩な機能を標準で利用できる Sendmail へ移行しています。

IPv6、SSL/TLS、Cyrus IMAPd との連携等を考え、かつ FreeBSD 上で利用することを考えたら、Sendmail を利用する事がもっとも簡単な解であることは間違いありませんので。

Sendmail を利用する際、FreeBSD を使用するのが一番簡単に管理ができる環境であるというのは、ほぼ間違いの無い事実でしょう。sendmail.org な人がメンテナンスしていて、sendmail.mc や sendmail.submit.mc の変更を適用するには /etc/mail の下で make cf install && make restart だけでいいとか、そういう世界なので。