INETD(8)

名称
inetd - インターネット “スーパサーバ”

書式
inetd [-d] [-l] [-w] [-W] [-c maximum] [-C rate] [-s maximum] [-a address | hostname] [-p filename] [-R rate] [configuration file]

解説
inetd ユーティリティは、ブート時に /etc/rc の中で起動されます (rc(8) 参照)。 起動されると、 inetd は定められたインターネットソケットを監視し、接続要求を待ちます。 監視しているソケットに対して接続要求が出されると、 inetd はそのソケットに対応したサービスを 判定し、サービスを提供するプログラムを起動します。 サーバプログラムはサービスソケットを標準入力・標準出力・ エラー出力として起動されます。 サービスプログラムが完了すると、 inetd は再びソケットの監視を行ないます (後述するような例外もあります)。 inetd を用いれば 1 つのデーモンで 複数のサービスプログラムを起動することができるので、 システムの負荷を軽減することができます。

inetd は、起動時に以下のオプションを指定できます。

-d  デバッグモードにします。

-l  成功した接続のログをとります。

-w  外部サービスに対して TCP Wrapping をオンにします。 TCP Wrappers サポートについての更なる情報については、 実装に関する注 の節を参照してください。

-W  inetd 組み込みの内部サービスに対して TCP Wrapping をオンにします。

-c maximum
    同時に起動可能なサービスの、デフォルトにおける最大値を指定します。 デフォルトでは、無制限です。 サービスごとに指定される "max-child" パラメータによって上書きされ得ます。

-C rate
    1 分間に単一の IP アドレスから起動されるサービスのデフォルトにおける最大値 を指定します。 デフォルトは未設定です。 サービスごとに指定される "max-connections-per-ip-per-minute" パラメータによって上書きされ得ます。

-R rate
    1 分間に起動できる最大のサービス数を指定します。デフォルトは 256 です。 rate に 0 を指定すると、起動可能な数は無制限になります。

-s maximum
    単一 IP アドレスに対して同時起動可能な各サービスの最大数のデフォルト値です。 デフォルトは無限です。 「IP あたりの子の数の最大」パラメータを使用して、サービス毎に上書き可能です。

-a  バインドする IP アドレスを 1 個指定します。 代りに、ホスト名を指定可能です。 この場合、ホスト名に対応する IPv4 または IPv6 のアドレスが使用されます。 通常、 inetd が jail(8) 内で起動される時点で、ホスト名が指定されます。 この場合、ホスト名は jail(8) 環境に対応するものです。

    ホスト名指定が使用され、IPv4 および IPv6 両方のバインドを望む場合、 /etc/inetd.conf の各サービスに対して、 各バインドに対する適切な プロトコル のエントリが必要です。 例えば TCP ベースのサービスは 2 エントリが必要であり、 ひとつは プロトコル に “tcp4” を使用し、もうひとつは “tcp6” を使用します。 後で説明する /etc/inetd.conf の プロトコル フィールドを参照してください。

-p  デフォルトとは異なるプロセス ID を保持するファイルを指定します。

inetd は実行時に設定情報を設定ファイルから読み込みます。 デフォルトでは設定ファイルは /etc/inetd.conf です。 設定ファイルの各フィールドにはエントリが 1 つなければなりません。 各フィールドのエントリはタブやスペースで区切ります。 コメントは行頭に “#” をつけます。 設定ファイルのフィールドは以下のものからなります:

    サービス名
    ソケットタイプ
    プロトコル
    {wait|nowait}[/最大子プロセス数[/IPあたりの分あたりの最大接続数[/IPあたりの子の数の最大]]]
    ユーザ名[:グループ名][/ログインクラス名]
    サーバプログラム名
    サーバプログラム引数

ONC RPC ベースのサービスを記述する場合には、以下のエントリを記述します。

    サービス名/バージョン
    ソケットタイプ
    RPC/プロトコル
    ユーザ名
    サーバプログラム名
    サーバプログラム引数

inetd が起動することのできるサービスは 2 種類あります。 1 つは標準で、もう 1 つは TCPMUX です。 標準サービスには割り当てられた well-known ポートがあります。 これは公式のインターネット標準を実装したサービスや BSD 特有のサービスです。 RFC 1078 に書かれているように、TCPMUX は非標準サービスであり、 well-known ポートが割り当てられていません。 そういった非標準サービスは、あるプログラムが “tcpmux” well-known ポートに接続してそのサービス名を指定したとき、 inetd によって起動されます。 この機能はローカルに開発されたサーバを追加するときに 便利です。 TCPMUX リクエストが受理されるのは、 TCPMUX ベースのサーバに至るまでにおいて、 マルチプレクササービス自身が有効にされているときのみです。 後述の内部サービスに関する議論を参照してください。

サービス名 のエントリには、 /etc/services ファイルに記述されているサービス名か、 UNIX ドメインソケット (後述) の指定が記述されます。 “内部” サービス (後述) については、 名前としてそのサービスのオフィシャル名 (すなわち /etc/services 内の最初のエントリ) を指定すべきです ONC RPC ベースのサービスを指定するためには、このフィールドは /etc/rpc に書かれた有効な RPC サービス名でなければなりません。 “/” の右の部分が RPC のバージョン番号です。バージョン番号は、 数字もしくは、バージョンの幅 (レンジ) で指定します。 幅を指定する場合は低い番号から高い番号を指定します。たとえば “rusers/1-3” のように記述します。 TCPMUX サービスでは、 サービス名 のフィールドは、文字列 “tcpmux” 、スラッシュ、そしてローカルに選ばれたサービス名から なります。 /etc/services に書かれたサービス名と “help” は予約済であり、ローカルなサービス名には使用できません。 TCPMUX サービスのためにユニークな名前をつけるには、 頭に組織名をつけ、末尾にバージョン番号をつけるとよいでしょう。

ソケットタイプ のエントリは、 “stream”, “dgram”, “raw”, “rdm”, “seqpacket” のいずれかである必要があります。それぞれ、ソケットが stream, datagram, raw, reliably delivered message, sequenced packet socket である場合に対応しています。 TCPMUX サービスは “stream” を使わなければなりません。

プロトコル のエントリには、 有効なプロトコル名か “unix” が記述されます。 例えば “tcp” や “udp” などです。 この場合、後方互換性のため、暗黙的に本エントリは IPv4 を意味します。 名前 “tcp4”, “udp4” は、IPv4 のみを指定します。 名前 “tcp6”, “udp6” は、IPv6 のみを指定します。 名前 “tcp46”, “udp46” は、エントリに IPv4 とワイルドカード AF_INET6 ソケット経由の IPv6 の両方を受理させます。 サービスが T/TCP 経由で到達可能とするためには、 “tcp/ttcp” を指定する必要があります。 後方互換性のため、暗黙的に本エントリは IPv4 を意味します。 名前 “tcp4/ttcp” は、IPv4 のみを指定し、 名前 “tcp6/ttcp” は、IPv6 のみを指定します。 名前 “tcp46/ttcp” は、エントリに IPv6 とワイルドカード AF_INET6 ソケット経由の IPv6 の両方を受理させます。 RPC ベースのサービスの場合、 “rpc/tcp” や “rpc/udp” のような指定になります。 IPv4 と IPv6 を、4, 6, 46 のいずれかのサフィックスを使用して指定可能です。 例えば “rpc/tcp6” や “rpc/udp46” とします。 TCPMUX サービスは “tcp”, “tcp4”, “tcp6”, “tcp46” のいずれかを使用する必要があります。

wait/nowait エントリは、 inetd によって起動されたサーバがサービスアクセスポイントに 関連付けられたソケットを引き継ぐかどうか、すなわちサーバが終了するまで inetd が新しいサービス要求を監視するのを待つ必要があるか否かを 指定します。 datagram サーバは、特定のサービスアドレスと結び付いた datagram ソケットで毎回起動されるため、 “wait” を使わなければなりません。こういったサーバは、終了する前に少なくとも 1 データグラムをソケットから読まなければなりません。 もし datagram サーバが相手に接続したときソケットを 解放するなら、 inetd はソケットに対するメッセージをさらに受けることができます。 このようなサーバは “マルチスレッド” サーバと呼ばれます。 サーバはソケットから datagram を 1 つ読み込み、相手に接続する新しい ソケットをつくります。 サーバは fork() を行い、親プロセス側は終了しなければいけません。 これにより inetd は新しいサービス要求をチェックし、新しいサーバを起動することが できるようになります。 入って来る全ての datagram を処理し、 時間切れまで動作する datagram サーバは、 “シングルスレッド” サーバと呼ばれます。 comsat(8), (biff(1)), talkd(8) のユーティリティは、後者のタイプの datagram サーバの例です。 tftpd(8) ユーティリティは、マルチスレッドで動く datagram サーバの例です。

stream ソケットを使うサーバは一般にマルチスレッドで動き “nowait” エントリを使います。 こういったサーバへの接続要求は inetd で受け付けられ、新たに受理し、クライアントにつながった ソケットのみがサーバに与えられます。 多くの stream ベースのサービスはこのように行われます。 “wait” エントリを使う stream ベースのサーバは、 サービスのソケットを監視し、少なくとも 1 つの接続要求を受け入れてから 終了しなければなりません。 そういったサーバは通常、時間切れとなるまで、入って来る要求を 受け付け処理します。 TCPMUX サービスは “nowait” を使わなければなりません。

“nowait” サービスの子プロセス (あるいは “スレッド” ) の最大数は、 “nowait” キーワードの後に “/” と数字を付け加えることで指定できます。 通常 (あるいは 0 が指定された場合)、子プロセスの数に制限はありません。 一方、最大数に達すると、それ以降の接続要求は、存在する子プロセスが終了するまで 待ち行列に蓄えられます。これは、 “wait” モードでも同様ですが、通常は 1 (デフォルトの値) 以外は意味がありません。 指定した IP アドレスからの 1 分あたりの最大接続数を指定することも可能です。 この場合、 “/” および最大子プロセス数を指定します。 最大値に達した場合、指定した IP アドレスからの接続は、 この 1 分が経過するまで、落とされます。 さらに、単一 IP アドレスに対して同時起動可能な各サービスの最大数の指定が、 “/” に続けて未完了の子プロセスの最大数を追加することで可能です。 最大値に達した場合、指定した IP アドレスからの接続は、 落とされます。

ユーザ名 エントリには、サーバを実行するユーザ名を書きます。 これによりサーバを root よりも低い権限で実行できます。 オプションの グループ名 部分は “”: で分けられ、 このユーザのデフォルトグループ以外のグループ名を指定可能です。 オプションの ログインクラス名 部分は “/” で分けられ、 デフォルトの “daemon” 以外のログインクラス名を指定可能です。

サーバプログラム名 のエントリには、ソケットに要求があったとき inetd が起動し、当該エントリのサービスを提供する サーバプログラムのパス名を指定します。 inetd 内部にすでに実装されているサービスを提供する場合には、サーバプログラムとして “internal” を指定します。

サーバプログラム引数 のエントリは、サーバを起動する際の引数を、サーバプログラムの起動文字列 である argv[0] を含めて記述します。 inetd 内部に実装されているサービスを提供する場合には、サーバプログラム引数 として、サービスの サービス名 (と引数) または語 “internal” を指定します。

現在、引数を取る内部サービスは “auth” のみです。 オプション無しだと、このサービスは常に “ERROR : HIDDEN-USER” を返します。 このサービスの動作を変更するために使用可能な引数は次の通りです:

-d fallback
    fallback ユーザ名を指定します。 本物の “auth” サービスが (後述の -r オプションで) 有効になっている場合、 ソケットの credential 取得またはユーザ名検索に失敗したときに、 エラーを返す代りにこのユーザ名を返します。 本物の “auth” サービスが無効になっている場合、 すべての要求に対してこのユーザ名を返します。 主に、本サービスを NAT マシン上で実行しているときに有用です。

-g  ident 要求者にユーザ名を返す代りに、 アルファベットと数字からなるランダムなユーザ名を報告します。 例えば “c0c993” です。 -g フラグは、ユーザ名に優先するだけでなく、 .fakeid や .noident のファイルにも優先します。

-t  sec[.usec] サービスのタイムアウトを指定します。 デフォルトのタイムアウトは 10.0 秒です。

-r  RFC 1413 にある、真の “auth” サービスを提供します。残りのすべてのフラグが使用されるのは、この場合のみです。

-i  ユーザ名の代りに数値のユーザ ID を返します。

-f  識別されるユーザのホームディレクトリに .fakeid というファイルがある場合、 本当のユーザ名の代りにそのファイル中のユーザ名を報告します。 .fakeid 中のユーザ名が実在するユーザのものの場合、本当のユーザ名を報告します。 -i が共に指定されると、 .fakeid 中のユーザ名が既存のユーザ ID の代りにチェックされます。

-F  -f と同じですが、 .fakeid が実在するユーザ名にマッチしてはならないという制約が除外されます。

-n  識別されるユーザのホームディレクトリに .noident というファイルがある場合、 “ERROR : HIDDEN-USER” を返します。 これは、 fakeid ファイルに優先します。

-o osname
    uname(3) が報告するシステム名の代りに、 osname を使用します。

inetd ユーティリティはまた、内部ルーチンを用いて簡単なサービスを自身で提供します。 これらのサービスとは “echo”, “discard”, “chargen” (文字生成), “daytime” (人間が読む形式で時間を出力します), “time” (機械可読形式の時間。1900 年 1 月 1 日 0 時からの経過秒数を出力します) です。 これらのサービスは TCP と UDP バージョンのいずれでも利用できます。 UDP バージョンは返事のポートとして内部サービスに相当するポートを 要求されたとき、サービスを拒否します。 (これはループ攻撃に対する防護です。リモート IP アドレスは記録されます。) これらのサービスの詳細については適当な RFC ドキュメントを参照して下さい。

TCPMUX のデマルチプレクスサービスもまた内部サービスとして実装されています。 TCPMUX ベースのサービスを動作させるためには、以下の行を inetd.conf に含む必要があります:

    tcpmux	stream	tcp	nowait	root	internal

-l オプションが指定された場合、 inetd は接続を受け付けるたび、エントリを syslog に記録します。 この際、利用可能であれば、 選択されたサービスと要求を発したリモートの IP 番号を記録します。 設定ファイルで他に指定しておらず、 -W と -w のオプションを指定していないと、 inetd は “daemon” ファシリティに対してログ出力します。

SIGHUP を受けとると、 inetd ユーティリティは、設定ファイルを再度読み込みます。設定ファイルを 再読み込みするとき、サービスを追加、削除、変更できます。 デバッグモードで起動された場合をのぞき、 inetd は再設定を容易にするために、プロセス ID を /var/run/inetd.pid に記録します。

実装に関する注

  TCP Wrappers
-w オプションが指定されたとき、 “stream nowait” または “dgram” と指定さた全サービスのうち “内部” サービス以外を、 inetd はラッピングします (包みます)。 -W オプションが指定されると、 前述の条件の “内部” サービスがラッピングされます。 両方のオプションが指定された場合、 内部サービスと外部サービスの両方をラッピングするようになります。 どちらのラッピングオプションも、失敗した接続を “auth” syslog ファシリティでログします。 ラッピングオプションに -l フラグを追加すると、成功した接続も “auth” ファシリティへのログに含めるようになります。

“wait” サービスに対する要求は、 サービス要求に対するサーバが無い間のみ inetd はラッピングすることに注意してください。 このようなサービスに対してひとたび接続が許されると、 接続要求に対して listen するサーバが無くなるまで、 このサービスに対する後続の接続を inetd は制御できません。

ラッピングが有効にされた場合、この機能は組み込みであるため、 tcpd デーモンは不要です。

TCP Wrappers についての更なる情報は、関連する文書 (hosts_access(5)) を参照してください。 この文書を読むときには、 “内部” サービスに対しては、関連するデーモン名は無いことを覚えておいてください。 このような理由で、 “内部” サービスのデーモン名としては、 inetd.conf で指定されるサービス名を使用すべきです。

  TCPMUX
RFC 1078 は TCPMUX プロトコルについて述べています。 「 TCP クライアントは他のホストに TCP ポート番号 1 で接続します。 クライアントは、サービス名に <CRLF> を付加して送ります。 サービス名は大文字/小文字を区別しません。 サーバは、肯定 (+) もしくは否定 (-) を表す 1 文字を返します。 + あるいは - のすぐ後にメッセージが続く場合があります。 返答は <CRLF> で終わります。 もし返答が肯定であれば、選択されたプロトコルが開始されます。 そうでなければ接続は切られます。」 プログラムにはファイルディスクプリタ 0 と 1 で TCP コネクションが 渡されます。

TCPMUX サービス名が “+” で始まっているとき、 inetd は、プログラムに肯定返答 (+) を返します。 これによって、 特別なサーバコードを追加することなく 標準入出力を使うプログラムを起動することができます。

特別なサービス名である “help” により、 inetd は inetd.conf にある TCPMUX サービスの一覧を出力します。

  IPsec
本実装は、各ソケットに対する IPsec ポリシ設定のサポートのための ちょっとしたハックを含みます。 “#@” から開始する特別な形式のコメント行が、ポリシ指示子として解釈されます。 “#@” の後のすべてが、 ipsec_set_policy(3) に記述されているように、IPsec ポリシ文字列として使用されます。 各ポリシ指定子は、 inetd.conf 中で後続するすべての行に適用され、 これは次のポリシ指定子が登場するまで続きます。 空のポリシ指定子は、IPsec ポリシをリセットします。

不正な IPsec ポリシ文字列が inetd.conf にあると、 inetd は syslog(3) インタフェースを使用して エラーメッセージを残し、終了します。

  ドメインソケット
サービスを IP ソケット上で動作させることに加え、 inetd は UNIX ドメインソケットも扱えます。 このためには プロトコル に “unix” を指定し、 UNIX ドメインソケットを サービス名 として指定します。 サービスタイプ は “stream” か “dgram” のいずれかです。 ソケットの指定は、絶対パス名であることが必要であり、 :user:group:mode: の形式で所有者とモードを前に付けることが可能です。

    :news:daemon:220:/var/run/sock

という指定は、所有者が “news” でグループが “daemon” で所有者とグループのみに接続を許可するソケットを作成します。 デフォルトの所有者は、 inetd を実行しているユーザです。 デフォルトのモードは、 ソケットの所有者のみに接続を許可するというものです。

警告: UNIX ドメインソケットの作成中に、 inetd はソケットの所有者とパーミッションを変更する必要があります。 これが安全に行われるのは、 ソケットが作成されるディレクトリが root のみ書き込み可能な場合だけです。 inetd を使用して、 /tmp 等の誰でも書き込み可能なディレクトリにソケットを作成し ない でください。 代りに、 /var/run 等のディレクトリと使用してください。

内部サービスは、通常通り、 UNIX ドメインソケットでも実行可能です。 この場合、ソケットのパス名の最後の部分から内部サービス名が判定されます。

関連ファイル
/etc/inetd.conf
    設定ファイル
/etc/rpc
    サービス名を RPC プログラム番号に変換するテーブル
/etc/services
    サービス名をポート番号に変換するテーブル
/var/run/inetd.pid
    現在実行中の inetd の pid

使用例
次に、いくつかのサービスについて サービスエントリの 例を挙げておきます。

    ftp          stream  tcp   nowait root  /usr/libexec/ftpd        ftpd -l
    ntalk        dgram   udp   wait   root  /usr/libexec/ntalkd      ntalkd
    telnet       stream  tcp6  nowait root  /usr/libexec/telnetd  telnetd
    shell        stream  tcp46  nowait root  /usr/libexec/rshd rshd
    tcpmux/+date stream  tcp   nowait guest /bin/date                date
    tcpmux/phonebook stream tcp nowait guest /usr/local/bin/phonebook phonebook
    rstatd/1-3   dgram   rpc/udp wait root  /usr/libexec/rpc.rstatd  rpc.rstatd
    /var/run/echo stream unix  nowait root	internal
    #@ ipsec ah/require
    chargen      stream  tcp   nowait root  internal
    #@

エラーメッセージ
inetd サーバは、 syslog(3) を使ってエラーメッセージを記録します。 重要なエラーメッセージと その説明は以下の通りです。

service/protocol server failing (looping), service terminated. 直前の 1 分間に、そのサービスについての要求数が制限に達しました。 不完全なプログラムや悪意のあるユーザがシステムを ハングアップさせないために、このような制限が設けられています。 このメッセージが出力される理由はいくつかあります。

1.  短時間の間に多くのホストがこのサービスを要求している。

2.  不完全なクライアントプログラムがサービスを 頻繁に要求しすぎている。

3.  悪意あるユーザがあるプログラムを起動し、 サービスが '拒否' されるように攻撃している。

4.  起動されたサービスプログラムにエラーがあり、 クライアントがすぐにリトライを起こしてしまう。

-R rate オプションを使うと、制限を変えることができます。 制限に達したとき、10 分経つとサービスは自動的に 再許可されます。

service/protocol: such user user, service ignored

service/protocol: getpwnam: user: such user passwd(5) データベースに user のエントリがありません。 最初のメッセージは inetd が設定ファイルを (再度) 読み込むときに出されます。 2 つ目のメッセージは、サービスが呼び出されたときに 出されます。

service: can't set uid uid

service: can't set gid gid user フィールドのユーザ ID もしくは グループ IDが 無効です。

setsockopt(SO_PRIVSTATE): Operation not supported
inetd ユーティリティはそのソケットに設定されている特権状態を放棄しようとしましたが、 失敗しました。

関連項目
ipsec_set_policy(3), hosts_access(5), hosts_options(5), login.conf(5), passwd(5), rpc(5), services(5), comsat(8), fingerd(8), ftpd(8), rexecd(8), rlogind(8), rpcbind(8), rshd(8), telnetd(8), tftpd(8), Michael C. St. Johns, Identification Protocol, RFC1413.

歴史
inetd ユーティリティは 4.3BSD から登場しました。 TCPMUX は Mark Lottor によるコードとドキュメントを元にしています。 ONC RPC ベースのサービスのサポートは、 SunOS 4.1 が供給されてから、 それにならって作られました。 IPsec のハックは、1999 年に KAME プロジェクトが提供しました。 FreeBSD の TCP Wrappers サポートが最初に登場したのは FreeBSD 3.2 です。