HOSTS_ACCESS(5)

名称
hosts_access - ホストアクセス制御ファイルの書式

解説
本マニュアルページは、 クライアント (ホストの名前/アドレス、ユーザ名) と サーバ (プロセス名、ホストの名前/アドレス) のパターンをベースとする、 単純なアクセス制御言語を解説します。 最後に使用例を示しています。 我慢できない方は、てっとり早い導入のために、使用例の節へ進んでください。

拡張バージョンのアクセス制御言語は、 hosts_options(5) 文書で解説しています。 プログラム構築時に -DPROCESS_OPTIONS 付きで構築することにより、 拡張機能はオンになります。

以降の文章においては、 daemon はネットワークデーモンプロセスのプロセス名であり、 client はサービスを要求しているホストの名前やアドレスです。 ネットワークデーモンプロセスの名前は、inetd 設定ファイルにおいて指定されます。

アクセス制御ファイル
アクセス制御ソフトウェアは、2 つのファイルを参照します。 検索は、最初のマッチで終了します。つまり、

•   (daemon,client) の組が /etc/hosts.allow ファイルのエントリにマッチするとき、 アクセスは許可されます。

•   そうでない場合、(daemon,client) の組が /etc/hosts.deny ファイルのエントリにマッチするとき、 アクセスは拒否されます。

•   そうでない場合、アクセスは許可されます。

存在しないアクセス制御ファイルは、そのファイルが空であるものとして扱われます。 よって、アクセス制御ファイルをなにも用意しないことにより、 アクセス制御をオフにすることが可能です。

アクセス制御ルール
各アクセス制御ファイルは、0 個以上のテキスト行を持ちます。 これらの行は、出現順に処理されます。 マッチが検出されたときに、検索が終了します。

•   改行文字は、前にバックスラッシュ文字がある場合、無視されます。 これにより、長い行の分割が可能となり、編集が容易になります。

•   空行または `#' 文字で開始する行は無視されます。 これにより、コメントや空白の挿入が可能となり、表が読み易くなります。

•   他のすべての行は、次の書式を満たす必要があります。[] の間のものは 省略可能です。

    daemon_list : client_list [ : shell_command ]

daemon_list は、1 個以上のデーモンプロセス名 (argv[0] 値) またはワイルドカード (後述) からなるリストです。

client_list は、1 個以上のホスト名、ホストアドレス、 パターン、またはワイルドカード (後述) からなるリストです。 これが、クライアントホストの名前またはアドレスに対してマッチされます。

より複雑な形式である、daemon@host と user@host は、 それぞれサーバ終点パターンとクライアントユーザ名検索の節で 説明します。

リストの要素は、空白やコンマで区切ります。

すべてのアクセス制御チェックは大文字小文字の違いは影響ありません。 ただし、NIS (YP) の netgroup の検索は例外です。

パターン
アクセス制御言語は、次のパターンを実装しています。

•   `.' 文字で開始する文字列。 ホスト名は、その最後の部分が指定されたパターンにマッチする場合、マッチします。 例えば、パターン `.tue.nl' は、ホスト名 `wzv.win.tue.nl' にマッチします。

•   `.' 文字で終了する文字列。 ホストアドレスは、 その最初の数値フィールドが指定された文字列にマッチする場合、マッチします。 例えば、パターン `131.155.' は、 Eindhoven University ネットワーク (131.155.x.x) の (ほぼ) すべてのホストのアドレスにマッチします。

•   `@' 文字で開始する文字列は、NIS (以前の YP) の netgroup 名として扱われます。 ホスト名は、指定された netgroup のメンバである場合、マッチします。 デーモンプロセス名およびクライアントユーザ名では、 netgroup のマッチはサポートされていません。

•   `n.n.n.n/m.m.m.m' 書式の表現は、`net/mask' ペアとして解釈されます。 `net' が、アドレスと `mask' とをビットごとに AND したものに等しい場合、 ホストアドレスはマッチします。 例えば、net/mask パターン `131.155.72.0/255.255.254.0' は、 `131.155.72.0' から `131.155.73.255' までの範囲の すべてのアドレスにマッチします。

•   `[n:n:n:n:n:n:n:n]/m' 書式の表現は `[net]/prefixlen' ペアとして解釈されます。 `net' の `prefixlen' ビットが、アドレスの `prefixlen' ビットと等しい場合、 IPv6 ホストアドレスはマッチします。 例えば [net]/prefixlen パターン `[3ffe:505:2:1::]/64' は、 `3ffe:505:2:1::' から `3ffe:505:2:1:ffff:ffff:ffff:ffff' までの範囲の すべてのアドレスにマッチします。

•   文字 `/' で開始する文字列はファイル名として扱われます。 ホスト名またはアドレスは、 指定されたファイル中のホスト名またはアドレスのパターンのいずれかに マッチするとき、マッチします。 ファイルの書式は、ホスト名またはアドレスのパターンを 空白で区切って 0 個以上指定した行が、0 個以上存在するというものです。 ファイル名パターンは、 ホスト名またはアドレスのパターンを使用可能な場所であればどこでも使用可能です。

ワイルドカード
アクセス制御言語は、明示的なワイルドカードをサポートします。

ALL 普遍的なワイルドカードであり、常にマッチします。

LOCAL
    名前にドット文字を含まない、すべてのホストにマッチします。

UNKNOWN
    名前が未知のすべてのユーザにマッチします。 また、名前 または アドレスの いずれか一方でも 未知である すべてのホストにマッチします。 このパターンの使用には注意してください。というのは、 一時的なネームサーバの問題により、ホスト名を得られなくなる場合が あるからです。また、 どのタイプのネットワークに対して話しているのかをソフトウェアが 分っていない場合、 ネットワークアドレスを得られなくなるからです。

KNOWN
    名前が既知のすべてのユーザにマッチします。 また、名前 および アドレスが ともに 既知のすべてのホストに マッチします。 このパターンの使用には注意してください。というのは、 一時的なネームサーバの問題により、ホスト名を得られなくなる場合が あるからです。また、 どのタイプのネットワークに対して話しているのかソフトウェアが 分かっていない場合、 ネットワークアドレスを得られなくなるからです。

PARANOID
    名前がアドレスにマッチしないすべてのホストにマッチします。 tcpd が -DPARANOID (デフォルトモードです) 付きで構築された場合、 アクセス制御表を検索する前に、 このようなクライアントからの要求を落とします。 このような要求に対して更に制御を行いたい場合、 -DPARANOID なしで構築してください。

オペレータ

EXCEPT
    `list_1 EXCEPT list_2' という形式で使用することを意図しています。 list_1 にマッチするもので、 list_2 にマッチしないものに、この構造はマッチします。 EXCEPT オペレータは、daemon_lists と client_lists で使用可能です。 EXCEPT オペレータは、入れ子 (ネスト) にすることが可能です。これは、 仮に制御言語が括弧の使用を許すとして表記するならば、 `a EXCEPT b EXCEPT c' は `(a EXCEPT (b EXCEPT c))' のように解釈されます。

シェルコマンド
最初にマッチしたアクセス制御ルールがシェルコマンドを含む場合、 このコマンドは %<letter> 置換 (次節参照) の対象になります。 置換結果は、標準入出力とエラー出力が /dev/null に接続される /bin/sh 子プロセスにより実行されます。 実行完了を待ちたくない場合、コマンドの最後に `&' を指定してください。

シェルコマンドは inetd の PATH の設定に依存してはなりません。 かわりに、絶対パス名を使用するか、 明示的な PATH=whatever という文で開始すべきです。

シェルコマンドフィールドを、これとは異なる互換性のない方法で扱う 別の言語については、 hosts_options(5) 文書に解説してあります。

% の展開
シェルコマンド中で、次の展開を使用可能です。

%a (%A)
    クライアント (サーバ) のホストアドレス。

%c  クライアントの情報。これは、 user@host か、user@address か、ホスト名か、単にアドレスかのいずれかです。 このうちのどれが使えるかは、得られる情報量に依存します。

%d  デーモンプロセスの名前 (argv[0] 値)。

%h (%H)
    クライアント (サーバ) ホストの名前、 または名前が得られない場合アドレス。

%n (%N)
    クライアント (サーバ) ホストの名前 (または "unknown" または "paranoid")。

%p  デーモンプロセス id。

%s  サーバの情報。これは、 daemon@host か、daemon@address か、単にデーモン名かのいずれかです。 このうちのどれが使えるかは、得られる情報量に依存します。

%u  クライアントユーザの名前 (または "unknown")。

%%  単一の `%' 文字に展開されます。

% 展開中の文字でシェルを混乱させ得るものは、アンダスコアに置き換えられます。

サーバ終点パターン
クライアントの区別のために、 クライアントが接続しているネットワークアドレスを使用するには、 次の形式のパターンを使用します。

process_name@host_pattern : client_list ...

異なったインターネットアドレスに異なったインターネットホスト名を マシンが持つ場合、 このようなパターンを使用可能です。 サービス提供者がこの機構を使用することにより、 複数のインターネットの名前を使用して、 FTP, GOPHER, WWW といったアーカイブを提供可能です。 この場合、インターネットの名前は、異なった組織に属することも可能です。 hosts_options(5) 文書の `twist' オプションも参照してください。 単一の物理インタフェースに 1 個以上のインターネットアドレスを 持てるシステムがあります (Solaris や FreeBSD)。 他のシステムでは、 専用のネットワークアドレス空間で、 SLIP や PPP といった擬似インタフェースを使用する必要があるかもしれません。

host_pattern は、client_list の文脈における ホストの名前およびアドレスのものと同じ文法ルールに従います。 通常、サーバ終点情報は、コネクション指向の (connection-oriented) サービスに おいてのみ使用可能です。

クライアントユーザ名検索
クライアントホストが RFC 931 プロトコルまたはその後継 (TAP, IDENT, RFC 1413) をサポートする場合、 コネクションの所有者に関する追加の情報を、ラッパプログラムが 引き出せるようになります。 クライアントのユーザ名情報が得られると、 クライアントホスト名とともに記録され、 次のようなパターンマッチに使用可能です。

daemon_list : ... user_pattern@host_pattern ...

ルールにもとづいてユーザ名を検索 (デフォルト) するか、 常にクライアントホストに問い合わせるかの設定は、 デーモンラッパのコンパイル時に設定可能です。 ルールにもとづいてユーザ名を検索する場合、 前述のルールがユーザ名検索を行うのは、 daemon_list と host_pattern がともにマッチする場合のみです。

ユーザパターンは、デーモンプロセスパターンと同じ文法であり、 同じワイルドカードが使用可能です (netgroup のメンバはサポートされません)。 しかし、ユーザ名検索に夢中になって理性を失ってはなりません。

•   クライアントのユーザ名情報がもっとも必要とされるとき、 すなわちクライアントシステムが危なくなっているときこそ、 クライアントのユーザ名情報は信用できません。 一般的には、ALL と (UN)KNOWN のみが意味のあるユーザ名パターンです。

•   TCP ベースのサービスにおいてのみ、 かつクライアントホストが適切なデーモンを実行しているときのみ、 ユーザ名検索を使用可能です。 他の場合には、結果は "unknown" になります。

•   ユーザ名検索がファイアウォールにブロックされると、 UNIX カーネルの良く知られた (well-known) バグにより、 サービスを失うことがあります。 カーネルにこのバグがあるかを判断するための手順は、 ラッパの README 文書に解説しています。

•   ユーザ名検索により、非 UNIX ユーザに対する顕著な遅延を生じることが あります。 ユーザ名検索のデフォルトのタイムアウトは 10 秒です。これは、 遅いネットワークに対しては短か過ぎますが、 PC ユーザをいらいらさせるには十分長いです。

最後の問題は、選択的なユーザ名検索により、緩和可能です。 例えば、次のようにします。

daemon_list : @pcnetgroup ALL@ALL

これは、ユーザ名検索を行わずに、pc netgroup のメンバにマッチします。 しかし、他のシステムに対しては、ユーザ名検索を行います。

アドレス詐称攻撃の検知
多くの TCP/IP 実装にあるシーケンス番号生成器の欠陥により、 侵入者が信頼されたホストになりすました上で、 例えばリモートシェルサービスを介して侵入することができます。 IDENT (RFC931 等) のサービスを使用することにより、 このような攻撃や別のホストアドレス詐称攻撃を検知可能となります。

クライアントの要求を受け付ける前に、 ラッパが IDENT サービスを使用することにより、 そのクライアントが要求をまったく送っていなかったことを検知可能です。 クライアントホストが IDENT サービスを提供している場合、 否定的な IDENT 検索結果 (クライアントが `UNKNOWN@host' にマッチ) は、 ホスト詐称攻撃の有力な証拠となります。

肯定的な IDENT 検索結果 (クライアントが `KNOWN@host' にマッチ) は、 これより信頼性が低いです。 クライアントの接続のみを詐称するよりは難しいですが、 侵入者がクライアントの接続と IDENT 検索の両方を詐称することが可能です。 クライアントの IDENT サーバが嘘をついている可能性もあります。

注: IDENT 検索は、UDP サービスでは動作しません。

使用例
この言語は十分柔軟性があるので、 ほとんど手間もかけずに、異なったタイプのアクセス制御方針を表現可能です。 またこの言語は 2 つのアクセス制御表を使用しますが、 一方の表は単純にしつつ、場合によっては空にしても、 一般的な方針のほとんどを実装可能です。

次に示す使用例を読むときには、 許可表が拒否表の前にスキャンされること、 検索はマッチが検出されたときに終了すること、 マッチが検出されない場合にはアクセスが許可されることを認識することが 重要です。

使用例では、ホストとドメインの名前を使用します。 アドレスや network/netmask の情報を含めることにより、これらの例を改良して、 一時的なネームサーバの検索失敗による影響を減じることが可能となります。

ほとんど閉じている状態
この場合、デフォルトではアクセスは拒否されます。 明示的に権限を与えられたホストのみが、アクセスを許可されます。

デフォルトの方針 (アクセスを拒否) は、簡単な拒否ファイルにより実装されます:

/etc/hosts.deny:
ALL: ALL

これにより、全ホストに対する全サービスが拒否されます。 ただし、許可ファイルのエントリにより許可されたアクセスである場合は例外です。

明示的に権限を与えられるホストは、許可ファイルにリストします。 例えば次のようにします:

/etc/hosts.allow:
ALL: LOCAL @some_netgroup
ALL: .foobar.edu EXCEPT terminalserver.foobar.edu

最初のルールは、 ローカルドメインの (ホスト名に `.' を含まない) ホストからのアクセスと、 some_netgroup のメンバからのアクセスを、許可します。 2 番目のルールは、 foobar.edu ドメイン (先頭のドットに注意) の全ホストからのアクセスを、 許可します。ただし、terminalserver.foobar.edu は例外です。

ほとんど開いている状態
今度は、デフォルトではアクセスは許可されます。 明示的に指定されたホストのみが、サービスを拒否されます。

デフォルトの方針 (アクセスを許可) では許可ファイルは冗長であり、省略可能です。 明示的に権限を与えられないホストは、拒否ファイルにリストします。 例えば次のようにします:

/etc/hosts.deny:
ALL: some.host.name, .some.domain
ALL EXCEPT in.fingerd: other.host.name, .other.domain

最初のルールは、あるホストとあるドメインに対する全サービスを拒否します。 2 番目のルールは、別のホストと別のドメインからの finger 要求は許可しています。

ブービートラップ
次の使用例は、 ローカルドメイン (先頭のドットに注意) からの tftp 要求を許可します。 他のホストからの要求は拒否されます。 要求されたファイルの代りに、 finger プローブが攻撃元ホストに対して送られます。 結果はスーパユーザに対してメールされます。

/etc/hosts.allow:
in.tftpd: LOCAL, .my.domain

/etc/hosts.deny:
in.tftpd: ALL: (/some/where/safe_finger -l @%h | \
	/usr/ucb/mail -s %d-%h root) &

safe_finger は back-finger での使用を意図しており、 適切な場所にインストールすべきです。 これは、 リモートの finger サーバから送られるデータに起因して発生し得るダメージを 限定します。 通常の finger コマンドよりも、より良い防御となります。

%h (クライアントホスト) と %d (サービス名) のシーケンスの展開については、 シェルコマンドの節に記述してあります。

警告: 自己の finger デーモンをブービートラップにかけないでください。 かけてしまうと、finger の無限ループになります。

ネットワークファイアウォールシステムでは、 このトリックをさらに幅広く活用できます。 典型的なネットワークファイアウォールでは、 外部の世界に対して限定されたサービスのみを提供します。 他の全サービスは、前述の tftp の使用例と同様の方法で「監視」可能です。 その結果、素晴しい早期警戒システムができます。

診断
次の場合、エラーが報告されます。 ホストアクセス制御ルールに文法エラーがある場合、 アクセス制御ルールが内部バッファの容量を越えた場合、 アクセス制御ルールが改行文字で終端されなかった場合、 %<letter> の展開結果が内部バッファを溢れさせた場合、 失敗すべきでないシステムコールが失敗した場合です。 すべての問題は、syslog デーモンを介して報告されます。

実装に関する注
オペレーティングシステムによっては、 TCP Wrappers を基本システムの一部として配布されているものがあります。 このようなシステムでは、 ネットワークユーティリティにラッピング機能を組み込むのが一般的です。 特に、システムによっては、 tcpd(8) が不要な inetd(8) を提供しているものがあります。 詳細については、システムの文書を確認してください。

関連ファイル
/etc/hosts.allow, アクセスを許可された (daemon,client) のペア。
/etc/hosts.deny, アクセスを拒否された (daemon,client) のペア。

関連項目
tcpd(8) tcp/ip デーモンラッパプログラム。
tcpdchk(8), tcpdmatch(8), テストプログラム。

バグ
ネームサーバの検索がタイムアウトすると、 ホスト名が登録されていたとしても、 アクセス制御ソフトウェアはホスト名を使用できなくなります。

ドメインネームサーバの検索は大文字小文字を区別しません。一方、 NIS (以前の YP) の netgroup の検索は大文字小文字を区別します。

作者
Wietse Venema (wietse@wzv.win.tue.nl)
Department of Mathematics and Computing Science
Eindhoven University of Technology
Den Dolech 2, P.O. Box 513,
5600 MB Eindhoven, The Netherlands