inetd
inetd(アイネットディー)は、多くのUNIXシステムで使われているスーパーサーバ型デーモンで、インターネットサービスを管理する。InternetDaemonの略。4.3BSDで初めて採用され[1]、通常 /usr/sbin/inetd にある。 後継のスーパーサーバ型デーモンとしては、xinetdがある。
目次 |
経緯 [編集]
inetd登場以前は、1台のサーバで複数のサービス(FTPサーバ、TELNETサーバ等)を稼働させておくには、それぞれのサービスのデーモン(ftpd、tftpd等)を起動しておき、それぞれのデーモンが、それぞれの待ち受けポートを監視する - というスタイルだった。しかし、この方法では、監視するポートの数だけデーモンが起動していることとなるため、実際にそのサービスが利用されていない時には、実質、メモリの無駄遣いということとなる。そこで、待ち受けポートを監視する専用の中継デーモンを用意し、待ち受けポートに要求がきた時には、あらかじめ決められたデーモン(ftpd、tftpd等)を起動させるという動作が用意されるようになった。
- メリット
- メモリの浪費解消
- デメリット
- inetdが中継動作することとなるので、動作レスポンスが遅れる。
- そのため、httpd等はinetdを経由させず、常時起動させておくことが多い。
機能 [編集]
inetd は、FTP、POP3、telnet といったインターネットサービスが使うポート番号を(指定されて)監視する。監視対象のポートにTCPパケットあるいはUDPパケットが届くと、inetd は対応するサーバプログラムを起動し、コネクションを制御させる。この方式では、必要にならない限りサービスが起動されないため、メモリ利用効率がよい。さらに、個々のサーバデーモンはソケットが標準入出力および標準エラー出力にフックされた状態で起動されるため、ネットワークに関するコードを必要としない。トラフィックの多いHTTPやPOP3などのプロトコルでは、直接トラフィックを受け付ける専用サーバの方が望ましい(頻繁にサーバプロセスを起動する無駄を避けるため)。
設定 [編集]
ポート番号とサービス名の対応付けは /etc/services というファイルで行われ、サービス名とサーバ名の対応付けは /etc/inetd.conf というファイルで行われる。例えば、23番のポートにTCP要求が来る場合、/etc/services には次のように記述される。
telnet 23/tcp
/etc/inetd.conf には、これに対応して次の行が記述される(以下の内容は AIX 5.1 の動作するマシンから取得)。
telnet stream tcp6 nowait root /usr/sbin/telnetd telnetd -a
これによると、inetd は /usr/sbin/telnetd というプログラムを telnetd -a という引数付きで起動する。inetd は標準入出力および標準エラー出力をソケットにフックした状態でサーバプログラムを起動する。
一般にTCPソケットは個別のサーバをコネクション毎に並行して起動することで制御される。UDPソケットは一般に単一のサーバインスタンスがそのポート番号の全パケットを扱う。
echo などの単純なサービスは inetd 自身が扱い、別にサーバを起動することはない。
inetd サービスの生成 [編集]
以下のコードはC言語で書かれた単純な inetd サービスの一例である。オプションでファイル名を引数として受け取り、それをログファイル名とし、そのソケット経由で送られてきた文字列を全てそのログファイルに記録する。これは例えば、異なるマシン上の複数のプロセスからメッセージを受け付けて、分散コンピューティングにおけるロギングサービスを実現するものである。inetd サービスをロギングメッセージ受信に使うことで、全てのマシンがメッセージを1つのマシンに送り、単一のログファイルにそれらを格納できる。
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> int main(int argc, char **argv) { /* メッセージのログ用バッファ */ char str[4096]; /* ログファイルへのポインタ */ FILE *fp = NULL; /* inetd が引数を渡してきた場合は、それをファイル名として使用 */ if(argc == 2) fp = fopen(argv[1], "at"); else /* さもなくば、/tmp ディレクトリでファイルをオープン */ fp = fopen("/tmp/errorLog.txt", "at"); /* ログファイルをオープンできない場合は異常終了 */ if(fp == NULL) return -1; while(!feof(stdin)) { /* 改行まで読み込む。最大4095文字。 fgets は文字列をNULLでターミネートする。 */ fgets(str, 4096, stdin); /* ログファイルに文字列を書き込み、フラッシュする。 */ fprintf(fp, "%s", str); fflush(fp); } /* ログファイルをクローズし、終了する。 */ fclose(fp); return 0; }
この場合、全メッセージを単一のファイルに記録したいので、サービスは1つのインスタンスのみで全要求に応えるようにしたい。従って、使うプロトコルとしてはUDPが適切である。まず、使っていないポート番号を選択する。ここでは 9999 が使われていなかったものとし、それを使うことにする。/etc/services には次のような一行が書かれる。
errorLogger 9999/udp
そして /etc/inetd.conf には次のように書かれる。
errorLogger dgram udp wait root /usr/local/bin/errlogd errlogd /tmp/logfile.txt
これにより inetd は /usr/local/bin/errlogd というプログラムを errlogd /tmp/logfile.txt という引数で起動する(inetd.conf の他のフィールドの意味については、inetd.conf のmanページを参照されたい)。第1引数は常に実行ファイル名であり、第2引数はログファイルのファイル名 /tmp/logfile.txt である。inetd は必要に応じてサービスを起動し、入出力ストリームをポート番号 9999 にアタッチし、そのポートに送られた全文字列がログファイルに記録される。wait と指定することで、全要求を単一のサーバインスタンスで扱うことを inetd に知らせる。上で示したtelnetの場合とは異なる(telnet は要求が来るたびに新たなサーバが起動される)。
なお、この例で示したような機能は通常 syslog を使って実装される。そのサーバである syslogd は inetd サービスではなく、inetd とは独立に起動される。
代替実装 [編集]
inetd はセキュリティへの配慮が乏しいため、最近では代替実装として xinetd、rlinetd、ucspi-tcp などがよく使われている。Linuxの対応はディストリビューションによって様々である。Mac OS Xは(Mac OS X v10.2 以降)xinetd を使っていた。Mac OS X v10.4 では、inetd の機能は launchd に統合されている。
inetd が提供するサービスは完全に切捨て可能である。これは、マシンを単機能サーバとする場合によく使われるようになりつつある。例えば、HTTPサーバは、httpd だけを起動するよう設定し、他のポートを全くオープンしないようにできる。ファイアーウォール専用マシンは全くサービスを起動しないようにできる。
セキュリティ問題 [編集]
サービスディスパッチャとしての inetd はセキュアでないというわけではないが、inetd が提供するサービスの長いリストはセキュリティ専門家でも正しく保つのが難しい。サービスに潜在的なセキュリティ問題がある可能性などを考慮する必要がある。このため不要なサービスをデフォールトではOFFにしておくのが一般化している。/etc/inetd.conf のほぼ全てのサービスがコメントアウトされたディストリビューションも珍しくない。
関連項目 [編集]
脚注 [編集]
参考文献 [編集]
- inetd(8) FreeBSD版マニュアル
- inetd(8) Linux版マニュアル(JM Project)
- inetd(1M) man page(Solaris 10 Reference Manua)(英語)
- inetd(1M) man page(HP-UX リファレンス)
|
||||||||||||||||||||||||||