Virtual Services Howto Brian Ackerman, brian@nycrc.net v1.2, 4 November 1997 伊佐治 哲, isaji@mxu.meshnet.or.jp 23 Dec 1997 このドキュメントはサービスの仮想化の方法についてますます増えてきた要求 に応じて書かれました。 (訳者:訳文に関する質問は必ず伊佐治までお願いい たします。またこのHOWTO本体(英語)の最新版は ftp://sun- site.unc.edu/pub/Linux/docs/HOWTO/ から入手できます)。 ______________________________________________________________________ 目次 1. イントロダクション 1.1 必要な知識 1.2 目的 1.3 フィードバック 1.4 改訂履歴 1.5 著作権、配布条件(Copyright/Distribution) 2. IPエイリアス 3. バーチャルデーモン(virtuald) 3.1 どのような動作をするか 3.2 inetd 3.3 virtual.conf 3.4 virtualdのソース 4. 仮想スクリプト(Virt scripts) 4.1 virtfs 4.2 virtexec 4.3 virtfsとvirtexecに関する注意 5. DNS 6. Syslog 6.1 問題点 6.2 解決方法 7. 仮想FTP 8. 仮想Web 9. 仮想的なMail/Pop 9.1 Qmail の注意点 9.2 問題 9.3 悪い解決方法 9.4 良い解決方法 10. その他仮想的にできること 11. まとめ 12. FAQ 13. 作業メモ 13.1 virtfsについて 13.2 その他のエラー 13.2.1 /var/log/syslog: 13.2.2 FTP 13.2.3 Mail 13.2.4 Web ______________________________________________________________________ 1. イントロダクション 1.1. 必要な知識 仮想サービスの設定はそんなに難しいものではありません。しかし基礎的な事 柄に加えてそれ以上の知識も必要とされます。このドキュメントではLinuxマ シンの設定の仕方については取り扱いません。 このドキュメントを理解するには以下述べるドキュメントの内容にちゃんと慣 れ親しんでいるものと仮定します。 o LinuxカーネルのコンパイルとIP aliasingサポートの追加 IP alias mini- HOWTO o ネットワークデバイスのセットアップと設定 NET-3 HOWTO o inetdの設定 NET-3 HOWTO o ネットワークパッケージのコンパイルとインストール Sendmail Site Apache Site Wu-Ftpd FAQ o DNSの設定 DNS HOWTO もし上に述べた事柄についてまだ理解していなければ、これらのパッケー ジに慣れるように上に指示されたリンクを使いそのドキュメント等を読ま れることを強くお奨めます。これらのドキュメント内容についてメールを 送っていただいても返事は出しません。HOWTOの該当する著者に直接聞いて 下さい。 1.2. 目的 仮想サービスの目的は複数のネットワークカードを使わないで複数のIPアドレ スを単体マシンに認識させるというものです。IPエイリアスはカーネルオプ ションで、このオプションは各ネットワークデバイスに一つ以上のIPアドレス を割り当てるようにするためのです。カーネルはバックグランドで各IPアドレ スを高速にスワップすることにより多重送信 (multiplexes)を行います。ユー ザーにとってはひとつ以上のネットワークカードがあるかのように見えるわけ です。 この多重送信(multiplexing)によってwww.domain1.com, www.domain2.comなど といった複数のドメインをひとつのドメイン程度のコストで運営できます。残 念なことに多くのサービス(ftp, web, mail)はそのままではこの複数のドメイ ンで使えません。それらを適切に動作させるためには、設定ファイルとソース コードを修正しなくてはなりません。このドキュメントは仮想マシンのセッ ティングにおいてその修正をどのように行うか解説しています。 デーモンも同様に仮想サービスの機能を提供するために必要です。今回使うデ ーモン(virtuald)のソースは、この後ドキュメント中に出てきます。 1.3. フィードバック パッケージがアップデートされたり設定の変更があった時に、このドキュメン トを拡張します。このドキュメントで、はっきりしないなどの不具合がありま したらその提案や質問などをメールに書いて送って下さい。またコメントはで きるだけはっきりと、どこの章がわかりにくいかを明記して下さい。その結果 著者がHOWTO全文に目を通さずにすみます。サブジェクトにはVIRTSERVICES HOWTOと書いて送っていただくことも大切です。その他のメールは個人用とな ります。個人用メールを読まずせっかく送ったメールも処分してしまうかもし れないので十分注意して下さい。 このドキュメントで著者が提示した例はほんの一例にすぎないので、そのまま コピーして使わないで下さい。読者各自が自分の環境にあうように書き換えて おいて下さい。もし何か問題がありましたら著者までメールを送って下さい。 その際メールにはちゃんと設定ファイル、エラーメッセージを書いてくだされ ば、ちゃんと目を通してその解決などの提案をメールで返事します。 1.4. 改訂履歴 V1.0 初期バージョン V1.1 Virtual Web Sectionのエラー更新 V1.2 日付の更新 1.5. 著作権、配布条件(Copyright/Distribution) This document is Copyright (c) 1997 by The Computer Resource Center Inc. A verbatim copy may be reproduced or distributed in any medium physical or electronic without permission of the author. Translations are similiarly permitted without express permission if it includes a notice on who translated it. Commercial redistribution is allowed and encouraged; however please notify Computer Resource Center of any such distributions. Excerpts from the document may be used without prior consent provided that the derivative work contains the verbatim copy or a pointer to a verbatim copy. Permission is granted to make and distribute verbatim copies of this document provided the copyright notice and this permission notice are preserved on all copies. In short, we wish to promote dissemination of this information through as many channels as possible. However, I do wish to retain copyright on this HOWTO document, and would like to be notified of any plans to redistribute this HOWTO. (和訳文を付けておきますが、正式な著作権は英語の原文に従います) 著者の承認をとらずに原文のコピーをして物理的/電子的媒体で改変/配布して もかまいません。翻訳も同様に特別な許可はいりませんが、その場合は誰が翻 訳したのか必ず明記して下さい。商用的な再配布は認めます。また推奨しま す。しかしそのような配布をする時も Computer Resource Centerにまで届け 出て下さい。 本文からの引用は事前の同意(原文引用や原文へのポインタを含んだ内容を提 供する際の同意)なしで使っていただいてかまいません。 ドキュメントの原文コピーを改変/配布する際は、著作権の表示やこの許可条 項が文書に含まれている限り可能です。 できるだけ多くの分野でこの情報が普及すること希望します。しかしドキュメ ントの著作権は保護されますし再配布する場合は届け出て下さい。 2. IPエイリアス IPエイリアス(IP aliasing)は仮想ホストマシンを稼働するために設定するカ ーネルオプションのことです。mini-HOWTOがすでにあるのでこちらを参照して ください (IP aliasing)。設定方法の質問などが扱われています。 (訳注:具 体的なエイリアスの設定。カーネルオプションでエイリアスオプションを選択 してカーネルの再構築をします。その後rootで ifconfig eth0:0 (追加するIP) route add -host (追加するIP) dev eth0:0 とします。詳しくは「NET-2/3-HOWTO」の13.11.2.1を参照して下さい)。 3. バーチャルデーモン(virtuald) 3.1. どのような動作をするか ネットワーク接続は"IPアドレス"と"ポート番号"のペアからなっています。 ネットワークプログラミングのAPI(Applications Program Interface)はsockets apiと呼ばれます。ソケットは開いたファイルのように 振舞い、これに対する読み書きをすることでネットワーク経由でデータをやり とりができます。 ローカルソケットのIPアドレスを返すファンクションコールgetsockname があ ります。 virtualdはgetsockname(訳注:/lib/libc.so)を、どのローカルマシンのIPが アクセスされているかを決めるのに用います。 Virtualdは設定ファイルを読 み込み、そのIPに対応するディレクトリを取得します。そのディレクトリに chrootした後、実際に行われるサービスに接続を引き渡します。 chroot はルートディレクトリ'/' を別のディレクトリにセットし直し、そ のディレクトリ(新しいルートディレクトリ)よりも上にある全てのものは実行 されているプログラムからは見えません(切り離されます)。こうして各IPアド レスはそれぞれの仮想ファイルシステムを取得します。これはネットワークプ ログラムからは透過的なので(上に書いたような操作は隠してあるので)、プロ グラムは何事もなかったかのように動作します。 このようにして、inetdといったプログラムと連結されたVirtuald はいろいろ なサービスを仮想化して使うことができるのです。 3.2. inetd Inetdは複数のポートを監視し、接続があった場合に(例えばpop要求があった ときなどに)ネットワークネゴシエーション行って指定されたプログラムに接 続を引き渡すスーパーサーバです。これにより、必要がなくて何もしていない サーバがないようにします。 標準的な /etc/inetd.confファイルは ftp stream tcp nowait root /usr/sbin/tcpd wu.ftpd -l -a pop-3 stream tcp nowait root /usr/sbin/tcpd in.qpop -s となります。(訳注:pop-3はpop3の場合はpop3にして下さい)。 また仮想的な/etc/inetd.confファイルは ftp stream tcp nowait root /usr/bin/virtuald virtuald /virtual/conf.ftp wu.ftpd -l -a pop-3 stream tcp nowait root /usr/bin/virtuald virtuald /virtual/conf.pop in.qpop -s となります。 3.3. virtual.conf それぞれのサービスに対応するIPとディレクトリをコントロールする confファイルを取得します。一つのマスターconfファイルがあり、またドメイ ンの異なるリストのサービスが必要なときはそれに応じたconfファイルを用意 することができます。virtual.confは以下のような内容です。 # This is a comment and so are blank lines # Format IP dir 10.10.10.129 /virtual/foo.bar.com 10.10.10.130 /virtual/bar.foo.com 10.10.10.157 /virtual/boo.la.com (訳注:実際の中身は各設定環境に合わせて書き換えて下さい。そしてこの ファイルは(上のinitd.confの設定に合わせた)該当ディレクトリおよびファイ ル名にコピーします)。 3.4. virtualdのソース (訳注:このVirtualdのソースは gcc -o viturald virtuald.cとしてコンパイ ルできます。また後の文章と合わせるために/usr/binにコピーします) ______________________________________________________________________ #include #include #include #include #include #include #include #define BUFSIZE 8192 main(int argc,char **argv) { char buffer[BUFSIZE]; char *ipaddr,*dir; logit("Virtuald Starting: $Revision: 1.2 $"); if (!argv[1]) { logit("invalid arguments: no conf file"); quitting_virtuald(0); } if (!argv[2]) { logit("invalid arguments: no program to run"); quitting_virtuald(0); } if (getipaddr(&ipaddr)) { logit("getipaddr failed"); quitting_virtuald(0); } sprintf(buffer,"Incoming ip: %s",ipaddr); logit(buffer); if (iptodir(&dir,ipaddr,argv[1])) { logit("iptodir failed"); quitting_virtuald(0); } if (chroot(dir)<0) { logit("chroot failed: %m"); quitting_virtuald(0); } sprintf(buffer,"Chroot dir: %s",dir); logit(buffer); if (chdir("/")<0) { logit("chdir failed: %m"); quitting_virtuald(0); } if (execvp(argv[2],argv+2)<0) { logit("execvp failed: %m"); quitting_virtuald(0); } } int logit(char *buf) { openlog("virtuald",LOG_PID,LOG_DAEMON); syslog(LOG_ERR,buf); closelog(); return 0; } int quitting_virtuald(int retval) { exit(retval); return 0; } int getipaddr(char **ipaddr) { struct sockaddr_in virtual_addr; static char ipaddrbuf[BUFSIZE]; int virtual_len; char *ipptr; virtual_len=sizeof(virtual_addr); if (getsockname(0,(struct sockaddr *)&virtual_addr,&virtual_len)<0) { logit("getipaddr: getsockname failed: %m"); return -1; } if (!(ipptr=inet_ntoa(virtual_addr.sin_addr))) { logit("getipaddr: inet_ntoa failed: %m"); return -1; } strncpy(ipaddrbuf,ipptr,sizeof(ipaddrbuf)-1); *ipaddr=ipaddrbuf; return 0; } int iptodir(char **dir,char *ipaddr,char *filename) { char buffer[BUFSIZE],*bufptr; static char dirbuf[BUFSIZE]; FILE *fp; if (!(fp=fopen(filename,"r"))) { logit("iptodir: fopen failed: %m"); return -1; } *dir=NULL; while(fgets(buffer,BUFSIZE,fp)) { buffer[strlen(buffer)-1]=0; if (*buffer=='#' || *buffer==0) continue; if (!(bufptr=strchr(buffer,' '))) { logit("iptodir: strchr failed"); return -1; } *bufptr++=0; if (!strcmp(buffer,ipaddr)) { strncpy(dirbuf,bufptr,sizeof(dirbuf)-1); *dir=dirbuf; break; } } if (fclose(fp)==EOF) { logit("iptodir: fclose failed: %m"); return -1; } if (!*dir) { logit("iptodir: ip not found in conf file"); return -1; } return 0; } ______________________________________________________________________ 4. 仮想スクリプト(Virt scripts) 4.1. virtfs 各ドメインはそれぞれのディレクトリ構造を持っています。 chroot を使って いるのでシェアライブラリ(shared libraries), バイナリ, conf ファイル等 の 重複したコピーが必要になります。著者は各ドメイン用の /virtual/domain.comを作り、それぞれにコピーして使っています。そのため 多くのディスクスペースを使いますが新しいマシンやネットワークカードを購 入するよりは安価でしょう。もしディスクスペースを節約したいのならそれぞ れのファイルをリンクすれば間に合います (訳注:このリンクはシンボリック リンクではありません)。 ここでvirtfsスクリプトの例をあげます。 ______________________________________________________________________ #!/bin/bash echo '$Revision: 1.2 $' echo -n "Enter the domain name: " read domain if [ "$domain" = "" ] then echo Nothing entered: aborting exit 0 fi leadingdir=/virtual echo -n "Enter leading dir: (Enter for default: $leadingdir): " read ans if [ "$ans" != "" ] then leadingdir=$ans fi newdir=$leadingdir/$domain if [ -d "$newdir" ] then echo New directory: $newdir: ALREADY exists exit 0 else echo New directory: $newdir fi echo Create $newdir mkdir -p $newdir echo Create bin cp -pdR /bin $newdir echo Create dev cp -pdR /dev $newdir echo Create dev/log ln -f /virtual/log $newdir/dev/log echo Create etc mkdir -p $newdir/etc for i in /etc/* do if [ -d "$i" ] then continue fi cp -pd $i $newdir/etc done echo Create etc/skel mkdir -p $newdir/etc/skel echo Create home for i in a b c d e f g h i j k l m n o p q r s t u v w x y z # (訳注:ここの[a-z]はそれぞれ設定するユーザー名に変更します) do mkdir -p $newdir/home/$i done echo Create home/c/crc mkdir -p $newdir/home/c/crc chown crc.users $newdir/home/c/crc # (訳注:ここも設定したユーザーに合わせて変更して下さい) echo Create lib mkdir -p $newdir/lib for i in /lib/* do if [ -d "$i" ] then continue fi cp -pd $i $newdir/lib done echo Create proc mkdir -p $newdir/proc echo Create sbin cp -pdR /sbin $newdir echo Create tmp mkdir -p -m 0777 $newdir/tmp chmod +t $newdir/tmp echo Create usr mkdir -p $newdir/usr echo Create usr/bin cp -pdR /usr/bin $newdir/usr echo Create usr/lib mkdir -p $newdir/usr/lib echo Create usr/lib/locale cp -pdR /usr/lib/locale $newdir/usr/lib # (訳注:ここのディレクトリ適当に変更します) echo Create usr/lib/terminfo cp -pdR /usr/lib/terminfo $newdir/usr/lib echo Create usr/lib/zoneinfo cp -pdR /usr/lib/zoneinfo $newdir/usr/lib echo Create usr/lib/\*.so\* cp -pdR /usr/lib/*.so* $newdir/usr/lib echo Create usr/sbin cp -pdR /usr/sbin $newdir/usr echo Linking usr/tmp ln -s /tmp $newdir/usr/tmp echo Create var mkdir -p $newdir/var echo Create var/lock cp -pdR /var/lock $newdir/var echo Create var/log mkdir -p $newdir/var/log echo Create var/log/wtmp cp /dev/null $newdir/var/log/wtmp echo Create var/run cp -pdR /var/run $newdir/var echo Create var/run/utmp cp /dev/null $newdir/var/run/utmp echo Create var/spool cp -pdR /var/spool $newdir/var echo Linking var/tmp ln -s /tmp $newdir/var/tmp echo Create var/www/html mkdir -p $newdir/var/www/html chown webmast.www $newdir/var/www/html # (訳注:ここのchownも適当に変更しておいて下さい。以下同様) chmod g+s $newdir/var/www/html echo Create var/www/master mkdir -p $newdir/var/www/master chown webmast.www $newdir/var/www/master echo Create var/www/server mkdir -p $newdir/var/www/server chown webmast.www $newdir/var/www/server exit 0 ______________________________________________________________________ 4.2. virtexec 仮想環境でコマンドを実行するにはそのディレクトリへ chroot してから実行 します。ここでコマンドを操作するvirtexecを呼び出すシェルスクリプトを書 きました。 (訳注:以下のコードを切り取って/usr/binディレクトリにコピー します。属性の変更(chmod +x)をしておいて下さい)。 ______________________________________________________________________ #!/bin/sh echo '$Revision: 1.2 $' BNAME=`basename $0` FIRST4CHAR=`echo $BNAME | cut -c1-4` REALBNAME=`echo $BNAME | cut -c5-` if [ "$BNAME" = "virtexec" ] then echo Cannot run virtexec directly: NEED a symlink exit 0 fi if [ "$FIRST4CHAR" != "virt" ] then echo Symlink not a virt function exit 0 fi list="" num=1 for i in /virtual/* do if [ ! -d "$i" ] then continue fi if [ "$i" = "/virtual/lost+found" ] then continue fi list="$list $i $num" num=`expr $num + 1` done if [ "$list" = "" ] then echo No virtual environments exist exit 0 fi dialog --clear --title 'Virtexec' --menu Pick 20 70 12 $list 2> /tmp/menu.$$ if [ "$?" = "0" ] then newdir=`cat /tmp/menu.$$` else newdir="" fi tput clear rm -f /tmp/menu.$$ echo '$Revision: 1.2 $' if [ ! -d "$newdir" ] then echo New directory: $newdir: NOT EXIST exit 0 else echo New directory: $newdir fi echo bname: $BNAME echo realbname: $REALBNAME if [ "$*" = "" ] then echo args: none else echo args: $* fi echo Changing to $newdir cd $newdir echo Running program $REALBNAME chroot $newdir $REALBNAME $* exit 0 ______________________________________________________________________ これを実行するには各自のシステムに dialog プログラムがインストールされ ている必要があります。注意してください。 (訳注:dialog = シェルスクリ プトからダイアログボックスを開くコマンドです。ほとんどのシステムではイ ンストールされています)。 virtexecを使うためにシンボリックリンクをはり ます。例えば、 ln -s /usr/bin/virtexec /usr/bin/virtpasswd ln -s /usr/bin/virtexec /usr/bin/virtvi ln -s /usr/bin/virtexec /usr/bin/virtpico ln -s /usr/bin/virtexec /usr/bin/virtemacs ln -s /usr/bin/virtexec /usr/bin/virtmailq ここでvirtvi、virtpasswd、virtmailq等と入力すればそれぞれviが起動した り、ユーザーのパスワードが変更できたり、仮想システム上のメールキューを チェックできたりします。必要に応じてもっと多くリンクをはることもできま す。しかしプログラムがシェアライブラリ(shared library)を必要とするとき は仮想ファイルシステム上になければなりません。バイナリファイルも同様に 仮想ファイルシステム上になければなりません。 4.3. virtfsとvirtexecに関する注意 著者は全てのスクリプトを/usr/binにインストールしています。仮想ファイル システム上に置きたくないものは/usr/localに置いています。スクリプトはコ ピーに関してなにもタッチしないようにします。仮想ファイルシステム間でま たがらないことが重要な全てのファイルは削除しなくてはいけません。例え ば、著者のシステムにはsshがインストールされていますが、プライベートキ ー (private key)はどの仮想ファイルシステムからも見えるようにはしたくあ りません。そこでvirtfsを実行した後にそれぞれの仮想ファイルシステムから プライベートキーを削除しています。 (訳注:sshはSecure Shellのことで す。secure authentication, encryption, encrypted X11 connections, encrypted TCP/IP forwarding をもったリモートログインプログラムで,適当 なアーカイブサーバの archives/net/ssh/ディレクトリなどから入手できま す) またresolv.conf(訳注: DNS情報など /etc/resolv.conf) も変更し他のドメ イン名があるファイルは全て移動しています。例えば /etc/hosts や /etc/HOSTNAMEなどです。 virtexecにシンボリックリンクをはっているプログラムは o virtpasswd -- パスワード変更 o virtadduser -- ユーザー追加 o virtdeluser -- ユーザー削除 o virtsmbstatus -- samba status o virtvi -- ファイルの編集 o virtmailq -- mailqのチェック o virtnewaliases -- エイリアステーブル再構築 です。 5. DNS DNSは普通に設定できます。このシステムの良い点は、全てのサービスにおい てマシンが(実は一台にもかかわらず)わかれているかのように振舞うというこ とです。 DNSに関するHOWTOは DNS を参照してください。 6. Syslog 6.1. 問題点 syslogはUNIXシステムで共通して使われるシステムログユーティリティです。 (訳注:syslog=カーネル(kernel)のメッセージ・リング・バッファーを読んだ り消去(clear)したりする)。 syslogはFIFO(First In First Out)と呼ばれる スペシャルファイルを開くデーモンです。FIFOはパイプ(pipe)に似たスペシャ ルファイルです。 syslogデーモンはリードサイドからのデータを待ち、ライ トサイドに書き込むための C関数があります。もしこれらのC関数でプログラ ムを書けば出力はsyslogに入ります。 chroot 環境を使っていて、FIFO /dev/logは仮想環境には存在しないことに 注意して下さい。これは全ての仮想環境がsyslogへの記録ができないというこ とを意味しています。プログラムは新しく作ったものの代わりとして/dev/log を使えないので、ファイルを単にコピーすることもできません。 syslogの特定のバージョンにはudpソケットをFIFOの代わりに使っているもの もありますが、これは一般的なことではありません。 6.2. 解決方法 syslogは、コマンドラインで指定すれば、異なるFIFOを探します。例えば以下 のようにします。 syslog -p /virtual/log そして/dev/logを/virtual/logにリンクをはります(シンボリックリンク)。 ln -sf /virtual/log /dev/log つぎに以下のようにしてこのファイルに全ての/dev/logをリンクします (これ はハードリンクでシンボリックリンクではないことに注意)。 ln /virtual/log /virtual/domain.com/dev/log 上記のvirtfsスクリプトではすでにこれを行っています。/virtualは一つの連 続したディスクにあり、/dev/logはリンクされているので同じinode 番号かつ 同じデータを指すことになります。chrootはこれをストップできないので全て の仮想/dev/logは機能します。全環境からのメッセージは一つの場所に記録さ れます。しかしもしプログラムを書きたくなく、それぞれlog ファイルを分け たいという場合は以下のようにして別々にsyslogを使うこともできます。 syslog -p /virtual/domain1.com/dev/log syslog -p /virtual/domain2.com/dev/log もっともこうすることはプロセスIDの浪費なのでお奨めしません。このバー ジョンのsyslog.initは、不適切な設定がされている場合には起動する度に毎 回 /dev/log に再リンクしてしまいます。以下、修正したsyslog.initファイ ルを挙げておきます。 ______________________________________________________________________ #!/bin/sh # Source function library. . /etc/rc.d/init.d/functions case "$1" in start) echo -n "Starting dev log: " ln -sf /virtual/log /dev/log echo done echo -n "Starting system loggers: " daemon syslogd -p /virtual/log daemon klogd echo echo -n "Starting virtual dev log: " for i in /virtual/* do if [ ! -d "$i" ] then continue fi if [ "$i" = "/virtual/lost+found" ] then continue fi ln -f /virtual/log $i/dev/log echo -n "." done echo " done" touch /var/lock/subsys/syslog ;; stop) echo -n "Shutting down system loggers: " killproc syslogd killproc klogd echo rm -f /var/lock/subsys/syslog ;; *) echo "Usage: syslog {start|stop}" exit 1 esac exit 0 ______________________________________________________________________ 一台のディスクに全ての仮想ファイルシステムを置かなくてもよいことに注意 して下さい。もっともディスク上に仮想ファイルシステムを持つ各パーティ ション用のsyslogを実行しなければならないでしょう。 7. 仮想FTP Wu-ftpdも仮想化して使うように設定できます(訳注:「Virtual-wu-ftpd」 (吉峯 幸郎さん訳)も出ているのでそちらも参照して下さい)。しかし各ドメイ ンでパスワードファイルをわけた状態にはできません。例えばもし bob@domain1.com と bob@domain2.com の両方がアカウントを必要とした場 合、どちらか一方をbob2としたりします。つまり違う名前にする必要がありま す。各ドメインの仮想ファイルシステムがある状態なのでパスワードファイル をわけてしまえばこの問題は解消します。virtnewuserスクリプトと virtpasswdスクリプトを上に書いたような方法で作って設定してください。仮 想ファイルシステムによって各仮想環境上で影響を受けることなくanonymous ftp を行うことができます。 inetd.confにwu-ftpをエントリします。 ftp stream tcp nowait root /usr/bin/virtuald virtuald /virtual/conf.ftp wu.ftpd -l -a 8. 仮想Web Apacheはそれ自身で仮想ドメインをサポートしています。内部仮想ドメインメ カニズムを使うことを著者が推奨しているプログラムです。inetdを通して何 か実行する時はコストがかかります。この場合、プログラムは実行する毎にス タートせねばなりません。つまりwebサービスには不向きな遅い応答であると いうことを意味しています。 Apacheは多くのアクセスが生じた時の接続を止 めるメカニズムも持っています。 もしinetdを通さずApacheを使い場合はinetd.confファイルに以下の行を追加 してください。 www stream tcp nowait www /usr/bin/virtuald \ virtuald /virtual/conf.www httpd -f /var/www/conf/httpd.conf そして /var/www/conf/httpd.confファイル(訳注:環境によって httpd.confがある場所は違います)に以下のように明記します。 ServerType inetd デフォルトでは"standalone"を設定しています。あとはシングルドメインで 使っていた時と同じようにApacheサーバの設定をします。 これを書いている時点では仮想web HOWTOはありません (訳注: 「Virtual-Web-HOWTO」が現在は出ています)。しかしこれが出てくるだろうと 思います。やがてはそのHOWTOを参照してここに書こうと思います。もしまだ 出てこず、要求が出て来たらApache仮想ホストの設定方法についての章を書く つもりです。 9. 仮想的なMail/Pop 9.1. Qmail の注意点 この章はsendmailのみに関する内容です。qmailの章はHOWTOの次のバージョン で追加します(訳注:Qmailに関するマニュアルは「Qmail+MH」などが出ていま す)。 9.2. 問題 現在、仮想メールのサポートに関する要求はますます増えていま す。Sendmailは仮想メールをサポートすると言っていますが、その内容は異な るドメインからのメール取り込みのことのようです。メールをどこかにフォワ ードさせるということができます。しかしもしローカルマシンにフォワードし たりbob@domain1.com、bob@domain2.comにメールが来る場合などでは同じメー ルフォルダにたまってしまうでしょう。これは bob宛のメールが実際は違う人 宛で中身も違うのだから問題です。 9.3. 悪い解決方法 ユーザー名に番号を追加(例えばbob1, bob2など)したり、頭に文字を入れて dom1bob, dom2bobにしたりすることによってユーザーの一意性(unique)を保証 することはできます。これを裏で変換するように mailやpop をハック(hack) することもできますが汚い(messy)方法です。出ていく方のメールもまたバー ナー(ヘッダ)にmaindomain.comがついていて各サブドメインのメールバーナー も違ったものにしたいのです。 9.4. 良い解決方法 各仮想ファイルシステムに各ドメイン用の/etc/passwdを用意しています。こ れはbob@domain1.comとbob@domain2.comが、別々の /etc/passwd上の違うユー ザーであり、メールのトラブルはないということになります。このユーザー達 には自分用のspoolディレクトリが用意されていて、各仮想ファイルシステム 上のメールフォルダは互いに違うものであることになります。 しかし、sendmailはちょっとしたソースコードの修正が必要です。 sendmailは/etc/sendmail.cwと呼ばれるファイルを持っています。これ はsendmailが他のホストに転送しないでローカルに配送する全てのホスト名を 含んでいるファイルです。 sendmailはマシン上の全デバイスの内部チェックを、ローカルIPでこのリスト を初期化するために行います。もし同じマシン上の仮想ドメイン間でメールを 送る場合、問題が出てきてしまいます。sendmailには他の仮想ドメインがロー カルアドレスであり、メールもローカルにスプールするという考えはないので す。 例えばbob@domain1.comさんがfred@domain2.comにメールを送ったとしま す。domain1.comのsendmailはdomain2.comがローカルであると判断するの でdomain1.comにメールをスプールしてしまい、結果として domain2.comにメ ールが届くことはありません。そこでsendmailを修正してやります(著者 はv8.8.5のsendmailでこれを行い、特に問題はありませ ん)。src/main.cの494行辺りを編集します。 sendmailのソースは適当なサイ トやディストリビューションCDROMから入手できます。 vi v8.8.5/src/main.c # Approximately Line 493 として、 load_if_names(); という箇所を /* load_if_names(); Commented out since hurts virtual */ とコメントアウトしてしまいます(訳注:この関数はインターフェースの走査 と追加名の場所をしめす関数でconf.c line 4399にこの関数自体がありま す。IPリストのスキャンなどを行っています)。もし仮想ドメイン間のメール 送信が必要ならこれを行うだけでよいことに注意して下さい。 問題は解決されたのですが、メインのイーサネットデバイスeth0は削除されて いません。そこで、もし同一マシンの仮想IPからeth0上のIPにメールを送る場 合はローカルに送られます。著者はダミーIPvirtual1.domain.com (10.10.10.157)として使っています。このホストにはメールを送らないのでど の仮想ドメインもいりません。これはシステムが大丈夫かどうかチェックする ために sshでログインする時に使うIPでもあります。 /etc/sendmail.cwの編集 vi /etc/sendmail.cw mail.domain1.com domain1.com domain1 localhost m4を使って/etc/sendmail.cfを好きなように作ります。著者は以下のようなも のを使いました。 divert(0)dnl VERSIONID(`@(#)tcpproto.mc 8.5 (Berkeley) 3/23/96') OSTYPE(linux) FEATURE(redirect) FEATURE(always_add_domain) FEATURE(use_cw_file) FEATURE(local_procmail) MAILER(local) MAILER(smtp) (訳注:m4はUNIXマクロプロセッサで、たいていのシステムに入っています。 最新バージョンはftp://prep.ai.mit.edu/pub/gnu/から入手できます。m4 linux.mc > /etc/sendmail.cfなどとして使います。 m4の例 が/usr/lib/m4-exampleにあります。オプションはm4 --help で調べて下さい) /etc/sendmail.cfを仮想ドメイン応答するように編集。 vi /etc/sendmail.cf # 86行辺りを編集 # my official SMTP hostname (defined automatically) #Dj$w.Foo.COM という箇所があるので、これを # my official SMTP hostname (defined automatically) Djdomain1.com としておきます。 sendmailはそれ自身ではそのサービスを始めることができず、inetdを通して 起動する必要があります。これは役に立つことでもなく起動時間を遅くしてい るだけでしょう。読者が高速なサイトを管理しているなら仮想マシン上に他の ドメインを占有させるべきではないかもしれません。 -bd フラグを付けて起動することは決してしないで下さい。 (訳注:このフ ラグはsendmailをデーモンとして起動するオプションです。くわしいこと はman sendmailして下さい)。また各ドメインで配送していないメールを送り 出す(queue up)するために sendmail -qと実行する必要があることに注意して ください。 #!/bin/sh # Source function library. . /etc/rc.d/init.d/functions case "$1" in start) echo -n "Starting sendmail: " daemon sendmail -q1h echo echo -n "Starting virtual sendmail: " for i in /virtual/* do if [ ! -d "$i" ] then continue fi if [ "$i" = "/virtual/lost+found" ] then continue fi chroot $i sendmail -q1h echo -n "." done echo " done" touch /var/lock/subsys/sendmail ;; stop) echo -n "Stopping sendmail: " killproc sendmail echo rm -f /var/lock/subsys/sendmail ;; *) echo "Usage: sendmail {start|stop}" exit 1 esac exit 0 popは特に何もせずにインストールしてしまいます。virtualdのパートを追加 した上で inetdのエントリーをすることが必要です。sendmailとpopに関す るinetd.confのエントリは、 pop-3 stream tcp nowait root /usr/bin/virtuald virtuald /virtual/conf.pop in.qpop -s smtp stream tcp nowait root /usr/bin/virtuald virtuald /virtual/conf.mail sendmail -bs となります。 10. その他仮想的にできること 他のサービスも同じような手順です。 o 仮想ファイルシステムにバイナリ、ライブラリファイルを追加 o /etc/inetd.confの追加 o /virtual/conf.serviceを作る o 必要に応じて仮想スクリプトを編集する sambaパッケージとEudoraを使っての仮想poppassdを試してみました。どち らも問題なく動作しています。もしもっと興味があれば仮想sambaのインス トール方法についての章も設けたいと考えています。 11. まとめ 以上が必要な作業です。この文書によって人びとの前向きな反応に出会えるこ とを期待しています。連絡は Computer Resource Center までお願いいたしま す。もし疑問な点やドキュメントのアップデートなどありましたら教えて下さ い。今後のHOWTOに追加したいと思います。 12. FAQ Q1. どうしてこのFAQについて質問がないのですか? A1. まだだれも質問してないからです。 (訳注:以上ここまでが原文) 13. 作業メモ 13.1. virtfsについて 実行すると Enter the domain name: domain.com Enter leading dir: (Enter for default: /virtual): と聞かれます。それぞれ入力して下さい。上の例では以下のようなディレクト リが作られ、適当なファイルがそれぞれのディレクトリにコピーされます。 /virtual/domain.com/ |- bin |- dev |- etc |- home |- lib |- proc |- sbin |- tmp |- usr |- var \-log 13.2. その他のエラー 13.2.1. /var/log/syslog: Dec 22 23:28:46 kaien virtuald[298]: Virtuald Starting: $Revision: 1.2 $ Dec 22 23:28:46 kaien virtuald[298]: getipaddr: getsockname failed: Socket opera Dec 22 23:28:46 kaien virtuald[298]: getipaddr failed ======> ip-aliasが設定されていません。 Dec 23 00:30:26 kaien virtuald[1132]: Virtuald Starting: $Revision: 1.2 $ Dec 23 00:30:26 kaien virtuald[1132]: Incoming ip: 192.168.1.1 Dec 23 00:30:26 kaien virtuald[1132]: iptodir: fopen failed: No such file or dir Dec 23 00:30:26 kaien virtuald[1132]: iptodir failed ======> /etc/initd.confに設定したconfファイルがありません。 13.2.2. FTP ftp は /virtual/etc/passwdで設定したユーザーでloginできます。 例: Connected to 192.168.1.4. <=== IP-alias address 220 kaien FTP server (Version wu-2.4(1) Tue Dec 5 20:51:15 CST 1995) ready. Name (192.168.1.4:apple): 331 Password required for hogehoge 230-No directory! Logging in with home=/ ===>これはまだ /virtual/home/hogehogeを作っていないから。 230 User hogehoge logged in. Remote system type is UNIX. Using binary mode to transfer files. ftp> 221 Goodbye. 13.2.3. Mail 13.2.4. Web [訳者 : 伊佐治 哲 (isaji@mxu.meshnet.or.jp) 校正 : 藤原 輝嘉さん (fujiwara@cim.pe.u-tokyo.ac.jp) ]