DNSサービス・プロバイダ
Java Naming Directory Interface (JNDI)

目次


はじめに

DNSサービス・プロバイダによって、JNDIアプリケーションが、インターネット・ドメイン・ネーム・システムに格納された情報にアクセスできるようになります。このプロバイダには、JNDIディレクトリ・コンテキストのツリーとしてのDNS名前空間と、JNDIの属性としてのDNSリソース・レコードが用意されています。

このドキュメントでは、DNSサービス・プロバイダの機能と、DNSがJNDIにマッピングされる方法の詳細について説明します。


適合性

DNSサービス・プロバイダは、RFC 1034RFC 1035に記述され、RFC 1123RFC 2181によって更新および明確化されているドメイン・ネーム・システムをサポートします。現在、次のリソース・レコードの型とクラスがサポートされています。

仕様
A RFC 1035
NS RFC 1035
CNAME RFC 1035
SOA RFC 1035
PTR RFC 1035
MX RFC 1035
TXT RFC 1035
HINFO RFC 1035
AAAA RFC 1886
NAPTR RFC 2915
SRV RFC 2782

それぞれのルックアップは、最初にUDPを使用して実行されます。応答が長すぎて、切り捨てないとUDPパケットに返すことができない場合は、TCPを使用してルックアップが繰り返されます。


環境プロパティ

DNSサービス・プロバイダでは、次のJNDI環境プロパティを使用します。初期コンテキスト・コンストラクタ、システム・プロパティ、アプレット・パラメータ、およびリソース・ファイルを使用してプロパティを初期化する方法については、JNDIのドキュメントを参照してください。

java.naming.authoritative

このプロパティは、すべての応答が権限を持っている必要があるかどうかを指定するために使用されます。この値が"true"の場合、権限のある応答のみをDNSサーバーから受け入れます。その他の場合は、すべての応答を受け入れます。このプロパティが設定されていない場合は、デフォルトで"false"になります。次に、すべての応答が権限を持っている必要があることを指定する例を示します。

env.put(Context.AUTHORITATIVE, "true");

DNSプロトコルでは権限のある情報を要求する方法が提供されないため、権限のある応答のみを返すように要求すると、一部の情報が使用できくなる可能性があることに注意してください。たとえば、DNSサービス・プロバイダがクエリーの結果として権限のないデータを取得したあと、権限のあるデータしか返せないため、それを強制的に破棄する可能性があります。

java.naming.factory.initial

このプロパティは、DNSサービス・プロバイダを初期コンテキストとして選択するために使用されます。プロバイダでは使用されません。プロバイダの初期コンテキスト・ファクトリのクラス名を指定し、次の例のように設定できます。

env.put(Context.INITIAL_CONTEXT_FACTORY, "com.example.jndi.dns.DnsContextFactory");
java.naming.factory.object

このプロパティには、DNSから読み取られたオブジェクトを変換するための、オブジェクト・ファクトリの完全指定クラス名のコロンで区切られたリストが含まれます。このメカニズムを使用して、アプリケーションでより使いやすい形式のオブジェクトに変換されます。詳細は、DirectoryManager.getObjectInstance()を参照してください。

java.naming.provider.url

このプロパティは、初期DNSコンテキストによって使用されるDNSサーバーのホスト名とポートや、初期コンテキストのドメイン名を指定します。URL形式の詳細は、下の「DNSの擬似URL」を参照してください。たとえば、

env.put(Context.PROVIDER_URL, "dns://server1.example.com/example.com");

プロバイダがserver1.example.comにあるDNSサーバーを使用するようにして、初期コンテキストのドメイン名をexample.comに設定します。このプロパティが設定されていない場合は、デフォルトで「dns:」になります(「DNSの擬似URL」で説明されているすべてのデフォルト値が使用されます)。

このプロパティをURLの空白で区切られたリストに設定することによって、複数のDNSサーバーを指定できます。サーバーの1つが応答するまで、各サーバーに順番に接続します。初期コンテキストには1つのドメイン名しか含まれていないため、複数のURLを指定する場合は、それぞれのドメイン部分が同じである必要があります。たとえば、

env.put(Context.PROVIDER_URL,
    "dns://server1.example.com/example.com dns://server2.example.com/example.com");
com.example.jndi.dns.lookup.attr

JNDIはDNSコンテキストでオブジェクト・ファクトリを呼び出す前に、デフォルトでは、そのコンテキストのすべてのインターネットTXT属性を読み取ってファクトリに渡します。このプロパティは、設定する場合は、使用する別の属性識別子を指定します。属性識別子の形式については、下の「DNSコンテンツのJNDIへのマッピング」を参照してください。

com.example.jndi.dns.recursion

このプロパティは、DNSクエリーで再帰が許可されないことを指定するために使用されます。このプロパティが設定されていない場合や、"true"に設定されている場合は、再帰が許可されます。それ以外の場合は、再帰が許可されません。次に、DNSクエリーで再帰が許可されないことを指定する例を示します。

env.put("com.example.jndi.dns.recursion", "false");
com.example.jndi.dns.timeout.initial
com.example.jndi.dns.timeout.retries

これらのプロパティは、DNSプロバイダがUDPクエリーを発行するときに使用するタイム・アウト関連のデフォルト値を変更するために使用されます。DNSプロバイダは、次の指数バックオフ・アルゴリズムを使用してUDPクエリーを発行します。プロバイダは、DNSサーバーにクエリーを発行して、タイム・アウト期間内(デフォルトでは1秒)に応答が到着するのを待機します。プロバイダにタイム・アウト期間内に応答が到着しなかった場合、プロバイダは次のサーバーにクエリーを発行し、応答を受け取るまで、これを繰り返します。どのサーバーからも応答を受信しなかった場合、プロバイダはタイム・アウト期間を2倍にして、最大の再試行回数(デフォルトでは4回)まで各サーバーにクエリーを発行するプロセスを繰り返します。

"com.example.jndi.dns.timeout.initial"プロパティは、設定されている場合、初期(つまり、2倍にする前の)タイムアウト期間として使用するミリ秒数を指定します。このプロパティが設定されていない場合、デフォルトの初期タイム・アウトは1000ミリ秒です。

"com.example.jndi.dns.timeout.retries"プロパティは、設定されている場合、前に説明した指数バックオフ・アルゴリズムを使用して各サーバーを再試行する回数を指定します。このプロパティが設定されていない場合、デフォルトの再試行回数は4です。

次の例では、タイム・アウトの合計の長さをあまり変えずに、初期タイム・アウト期間を2倍にしています。

env.put("com.example.jndi.dns.timeout.initial", "2000");
env.put("com.example.jndi.dns.timeout.retries", "3");

DNSコンテンツのJNDIへのマッピング

DNSサービス・プロバイダは、DNS名、ノード、およびリソース・レコードを、次のようにしてJNDIのデータ型にマッピングします。

名前

DNSドメイン名は、右から左にドットで区切られた構文で、エスケープ文字としてバックスラッシュ (\)を使用してJNDIの複合Nameオブジェクトで表現されます。また、\DDDの形式のエスケープ・シーケンスも使用できます。ここで、DDDは3桁の10進数値です。名前では大文字と小文字が区別されません。明示的なルート・ドメイン・ラベル(「.」)で終わる完全修飾名は、最上位の位置に空のコンポーネントを配置した複合Nameオブジェクトで表現されます。

ホスト名は、ドメイン名のサブセットです。ホスト名のラベルには、US-ASCII文字、数字、ハイフンのみが使用でき、先頭または末尾にハイフンは使用できません。これらの規則に従っていない名前はドメイン名として有効になる場合もありますが、一部のDNSアプリケーションで使用できないため、ほとんどの場合、このような名前の使用は避けるべきです。

DNSでは、US-ASCII以外の文字に使用するための(UTF-8などの)エンコーディングを指定していません。その結果、DNS名の文字がゼロ以外の高位のバイトを使用することはありません。ドメイン名の国際化の作業が終了した時点で、その作業に合わせてDNSサービス・プロバイダを更新できます。

ノードおよびリソース・レコード

DNSノードは、DirContextオブジェクトで表現されます。ノードのリソース・レコードは、コンテキストの属性で表現されます。たとえば、DNSノードexample.comにアドレスが192.0.2.33のAレコードと、データが「10 example.com」のMXレコードが含まれている場合、対応するJNDIコンテキストには識別子が「A」で文字列値が「192.0.2.33」の属性と、識別子が「MX」で文字列値が「10 example.com」の属性が含まれます。

同じ型の複数のレコードは、複数の値がある属性として表現されます。サポートされないレコード型は、数字の識別子およびバイト列の値で表現されます。

属性識別子

DNSリソース・レコードのクラス名と型名が、JNDI属性識別子にマッピングされます。レコードがインターネット・クラスの場合、対応する属性IDはレコードの型名です。サポートされない型の場合は、代わりに整数値が使用されます。レコードがインターネット・クラスでない場合は、クラス名(または整数のクラス値)が、空白文字で区切られて属性IDに付加されます。たとえば、属性識別子「AAAA」はIPv6アドレス・レコードを表現し、属性識別子「HS 97」はHesiodクラス内の97型のリソース・レコードを表現します。

また、スーパー・クラス属性識別子も定義されます。これらは、DirContext.getAttributes()メソッドを使用してレコードを問い合わせるときに役立つことがあります。属性名に型名(またはクラス名)の代わりに「*」が含まれている場合は、任意の型(またはクラス)のレコードであることを表します。たとえば、getAttributes()メソッドに属性識別子「IN *」を渡せば、インターネット・クラスのすべてのレコードを検索できます。属性識別子「* *」は、任意のクラスまたは型のレコードを表します。

属性識別子では、大文字と小文字は区別されません。


DNSの擬似URL

URLに似た記述を使用して、DNSサーバー、ポート、java.naming.provider.urlプロパティおよび初期コンテキストに渡されるURL名内のドメインを表します。この擬似URLの形式は、次のとおりです。
   dns:[//host[:port]][/domain]
「host」および「port」は、使用するDNSサーバーを示します。「host」のみが指定されている場合、ポートにはデフォルトの53が使用され、「port」のみが指定されている場合、ホストはデフォルトの「localhost」になります。どちらも指定されていない場合、プロバイダは基本プラットフォーム用に構成されたサーバーを判定して使用しようとし、成功した場合は、java.naming.provider.urlプロパティをそれらのサーバーを使用して構築されたURLの空白で区切られたリストに設定します(たとえば、SolarisまたはLinuxの場合、プロバイダは/etc/resolv.confファイルを読み取ります)。基本プラットフォームにDNSが構成されていない場合、ホストとポートはデフォルトの「localhost」と53になります。

このドメインはコンテキストのDNSドメイン名であり、必ずしもサーバーのドメインには関連していません。デフォルトでは「.」(ルート・ドメイン)です。


APIマッピング

DNSサービス・プロバイダは、DirContextインタフェースを実装します。メソッドがDNSの操作にマッピングされる方法は、次のとおりです。ここに挙げられていないメソッドはサポートされていません。
addToEnvironment()

新しいプロパティを環境に追加するか、既存のプロパティを変更します。

close()

内部データ構造を解放します。

composeName()

2つの名前を重ね合わせます。

getAttributes()

DNSリソース・レコードを表す属性を返します。

getEnvironment()

このコンテキストに関連する環境プロパティを返します。

getNameInNamespace()

このノードの完全修飾ドメイン名を返します。

getNameParser()

DNSドメイン名を解析するために、名前パーサーを返します。

lookup()
lookupLink()

指定されたノードを表すDirContextを返します。アプリケーションまたはユーザーがオブジェクト・ファクトリを指定していた場合は、返される前に、そのオブジェクトでDirectoryManager.getObjectInstance()メソッドが呼び出されます。

list()
listBindings()

DNS名前空間のリストはゾーン転送を使用して実装されるため、これらの操作が計算やネットワークを集中的に使用し、すべてのDNSインストールではサポートされない可能性があります。アプリケーションまたはユーザーがオブジェクト・ファクトリを指定していた場合は、返される前に、そのオブジェクトでDirectoryManager.getObjectInstance()メソッドが呼び出されます。属性は渡されません。

removeFromEnvironment()

環境からプロパティを削除します。


使用例

例1

この例では、example.comドメインを表す初期コンテキストを作成したあと、そのドメイン内の2つのホストのIPアドレス(Aレコード)を読み取ります。
Hashtable env = new Hashtable();
env.put("java.naming.factory.initial", "com.example.jndi.dns.DnsContextFactory");
env.put("java.naming.provider.url",    "dns://server1.example.com/example.com");

DirContext ictx = new InitialDirContext(env);
Attributes attrs1 = ictx.getAttributes("host1", new String[] {"A"});
Attributes attrs2 = ictx.getAttributes("host2", new String[] {"A"});

例2

プログラム例1のプロパティを使用しないで、デフォルトの初期コンテキストのメソッドにDNSの擬似URLを渡します。この例では、example.comドメイン内のホストのMXレコードを読み取ります。

DirContext ictx = new InitialDirContext();
Attributes attrs3 = ictx.getAttributes("dns://server1.example.com/host3.example.com",
                                       new String[] {"MX"});

セキュリティについて

セキュリティ・マネージャがインストールされていると、これを使用するDNSサービス・プロバイダとアプリケーションの両方に、次のアクセス権が許可されます。

permission java.net.SocketPermission "host[:port]", "connect,accept";

java.naming.provider.urlプロパティ、コンテキスト・メソッドに指定されているURL文字列名、およびオブジェクト参照で識別される各ホスト/ポート用のアクセス権です。


連合

DNSサービス・プロバイダでは、合成名は強く区分されているとみなされます。つまり、合成名の最初のコンポーネントをDNSドメイン名として処理し、残りのコンポーネントを次のネーミング・システム (nns)内の名前として処理します。暗示的な次のネーミング・システムは動的に決定されます。

たとえば、次の例では、次のネーミング・システムのルートのリストを出力しています。このネーミング・システムは、DNSコンテキストを超えて連合されています。次に、マルチコンポーネントの合成名を使用して名前が参照されます。

// List the root of the nns.
// Note the use of a trailing slash to indicate traversal into the nns.
NamingEnumeration enum = ctx.list("java.example.com/");

// A composite name lookup.
Object obj = ctx.lookup("example.com/some/x/y/z");
クラス 仕様
IN RFC 1035
HS RFC 1035

Copyright © 1993, 2020, Oracle and/or its affiliates. All rights reserved.