Node.js v0.6.21 マニュアル & ドキュメンテーション
Table of Contents
- TLS (SSL)
- Client-initiated renegotiation attack mitigation
- NPN and SNI
- tls.createServer(options, [secureConnectionListener])
- tls.connect(port, [host], [options], [secureConnectListener])
- tls.createSecurePair([credentials], [isServer], [requestCert], [rejectUnauthorized])
- Class: SecurePair
- Class: tls.Server
- Class: tls.CleartextStream
TLS (SSL)#
Stability: 3 - Stable
require('tls') でこのモジュールにアクセスします。
tls モジュールは OpenSSL を使用することで Transport Layer Security および
Secure Socket Layer: 暗号化されたストリーム通信を提供します。
TLS/SSL は公開/秘密鍵を基礎とします。 どのクライアントとサーバも秘密鍵が必要です。 秘密鍵は次のように作成します
openssl genrsa -out ryans-key.pem 1024
全てのサーバと一部のクライアントは証明書を必要とします。 証明書は認証局の公開鍵または自身によって署名されます。 証明書を作成する最初のステップは「証明書署名要求 (CSR)」ファイルです。 次のようにします:
openssl req -new -key ryans-key.pem -out ryans-csr.pem
CSR から自己署名証明書を作成するには次のようにします:
openssl x509 -req -in ryans-csr.pem -signkey ryans-key.pem -out ryans-cert.pem
他に CSR を認証局に送って署名してもらうこともできます。
(TODO: CA を作るドキュメント、現在は興味あるユーザは Node のソースコードから
test/fixtures/keys/Makefile を見る必要がある)
.pfx または .p12 を作成するには、次のようにします。
openssl pkcs12 -export -in agent5-cert.pem -inkey agent5-key.pem \
-certfile ca-cert.pem -out agent5.pfx
in: 証明書inkey: 秘密鍵certfile: 全ての認証局が含まれた、次のようなファイル。cat ca1-cert.pem ca2-cert.pem > ca-cert.pem
Client-initiated renegotiation attack mitigation#
TLS では、クライアントから TLS セッションの再ネゴシエーションが可能です。
残念なことに、セッションの再ネゴシエーションは過度な量のサーバサイドリソースを 要求し、それは潜在的にサービスを強制停止する攻撃となります。
これを緩和するために、再ネゴシエーションは 10 分あたり 3 回までに
制限されています。この閾値を超えると、CleartextStream
のインスタンスで 'error' が生成されます。
この制限はコンフィグレーション可能です:
tls.CLIENT_RENEG_LIMIT: 再ネゴシエーションの上限、デフォルトは 3 です。tls.CLIENT_RENEG_WINDOW: 再ネゴシエーションのウィンドウサイズ (秒単位)、 デフォルトは 10 分です。
あなたが何をしたいのか理解していない限り、デフォルトを変更しないでください。
サーバをテストするために、openssl s_client -connect address:port で
接続して R<CR> (これは R の後に復帰改行を続けます)
を、数回試すことができます。
NPN and SNI#
NPN (Next Protocol Negotitation) と SNI (Server Name Indication) は TLS の拡張で、以下を可能にします。
- NPN - 一つの TLS サーバで複数のプロトコル (HTTP、SPDY) を使用。
- SNI - 一つの TLS サーバでホスト名の異なる複数の証明書を使用。
tls.createServer(options, [secureConnectionListener])#
新しい tls.Server を作成します。
connectionListener は secureConnection
イベントのリスナとして自動的に登録されます。
options は以下を持つことができます:
pfx: サーバの秘密鍵、証明書、および認証局を含む、PFX または PKCS12 フォーマットの文字列またはBufferです。 (key、certおよびcaオプションとは相互排他です)。key: PEM フォーマットによるサーバの秘密鍵を表す文字列またはBufferです (必須)。passphrase: 秘密鍵のパスフレーズを表す文字列です。cert: PEM フォーマットによる証明書の鍵を表す文字列またはBufferです (必須)。ca: 信頼できる証明書の文字列またはBufferの配列です。 省略された場合、ベリサインなどのよく知られた「ルート」認証局が使われます。 これらはコネクションの認証に使われます。ciphers: 使用または除外する暗号を記述した文字列。 詳細は http://www.openssl.org/docs/apps/ciphers.html#CIPHER_LIST_FORMAT を参照してください。requestCert:trueの場合、サーバは接続しようとするクライアントからの 証明書を要求します。デフォルトはfalseです。rejectUnauthorized:trueの場合、サーバは提供された認証局の リストによって認証されていないコネクションを破棄します. このオプションはrequestCertがtrueの場合だけ効果があります。 デフォルトはfalseです。NPNProtocols: NPN プロトコルで使用可能な文字列またはBufferの配列 (プロトコルはその優先度に応じて並んでいる必要があります)。SNICallback: クライアントが TLS 拡張の SNI をサポートしている場合に 呼び出される関数です。servernameが唯一の引数として渡されます。SNICallbackは SecureContext のインスタンスを返す必要があります (SecureContext を取得するためにcrypto.createCredentials(...).contextを使用することができます)。SNICallbackが渡されなかった場合は、デフォルトのコールバックとして 後述する高水準 API が使用されます。sessionIdContext: セッション再開のための識別子となる文字列です。requestCedrtがtrueの場合、デフォルトはコマンドライン引数から 生成された MD5 ハッシュ値となります。 そうでない場合はデフォルトは提供されません。
これはシンプルはエコーサーバの例です:
var tls = require('tls');
var fs = require('fs');
var options = {
pfx: fs.readFileSync('server.pfx'),
var tls = require('tls');
var fs = require('fs');
var options = {
key: fs.readFileSync('server-key.pem'),
cert: fs.readFileSync('server-cert.pem'),
// これはクライアント証明書を用いた認証を行う場合だけ必要です
requestCert: true,
// これは自己署名のクライアント証明書を認証する場合だけ必要です
ca: [ fs.readFileSync('client-cert.pem') ]
};
var server = tls.createServer(options, function(cleartextStream) {
console.log('server connected',
cleartextStream.authorized ? 'authorized' : 'unauthorized');
cleartextStream.write("welcome!\n");
cleartextStream.setEncoding('utf8');
cleartextStream.pipe(cleartextStream);
});
server.listen(8000, function() {
console.log('server bound');
});
または
var tls = require('tls');
var fs = require('fs');
var options = {
pfx: fs.readFileSync('server.pfx'),
// これはクライアント証明書を用いた認証を行う場合だけ必要です
requestCert: true,
};
var server = tls.createServer(options, function(cleartextStream) {
console.log('server connected',
cleartextStream.authorized ? 'authorized' : 'unauthorized');
cleartextStream.write("welcome!\n");
cleartextStream.setEncoding('utf8');
cleartextStream.pipe(cleartextStream);
});
server.listen(8000, function() {
console.log('server bound');
});
openssl s_client を使用してこのサーバに接続するテストを行うことができます。
openssl s_client -connect 127.0.0.1:8000
tls.connect(port, [host], [options], [secureConnectListener])#
与えられた port と host で新しいクライアントコネクションを作成します
(host のデフォルトは localhost です)。
options は以下を指定したオブジェクトです。
pfx: サーバの秘密鍵、証明書、および認証局を含む、PFX または PKCS12 フォーマットの文字列またはBufferです。key: PEM フォーマットによるサーバの秘密鍵を表す文字列またはBufferです。passphrase: 秘密鍵または pfx のパスフレーズを表す文字列です。cert: PEM フォーマットによる証明書の鍵を表す文字列またはBufferです。ca: 信頼できる証明書の文字列またはBufferの配列です。 省略された場合、ベリサインなどのよく知られた「ルート」認証局が使われます。 これらはコネクションの認証に使われます。NPNProtocols: サポートする NPN プロトコルの文字列またはBufferの配列です。Bufferは次のような形式です:0x05hello0x5world最初のバイトは次のプロトコル名の長さです (通常、配列を渡す方がシンプルです:['hello', 'world'])。servername: TLS 拡張である SNI (Server Name Indication) のサーバ名です。socket: 新しいソケットを生成するのではなく、与えられたソケット上で セキュアな接続を確立します。 このオプションが指定された場合、hostおよびportは無視されます。 これは内部的な利用のみを意図しています。他のアンドキュメンテッドな API と同様、これを使用すべきではありません。
secureConnectLister 引数は 'secureConnect'
イベントのリスナとして加えられます。
tls.connect() は CleartextStream
オブジェクトを返します。
これは前述のエコーサーバに接続するクライアントの例です:
var tls = require('tls');
var fs = require('fs');
var options = {
// これらはクライアント証明書による認証を行う場合だけ必要ですn
key: fs.readFileSync('client-key.pem'),
cert: fs.readFileSync('client-cert.pem'),
// これはサーバが自己署名証明書を使う場合だけ必要です
ca: [ fs.readFileSync('server-cert.pem') ]
};
var cleartextStream = tls.connect(8000, options, function() {
console.log('client connected',
cleartextStream.authorized ? 'authorized' : 'unauthorized');
process.stdin.pipe(cleartextStream);
process.stdin.resume();
});
cleartextStream.setEncoding('utf8');
cleartextStream.on('data', function(data) {
console.log(data);
});
cleartextStream.on('end', function() {
server.close();
});
または
var tls = require('tls');
var fs = require('fs');
var options = {
pfx: fs.readFileSync('client.pfx')
};
var cleartextStream = tls.connect(8000, options, function() {
console.log('client connected',
cleartextStream.authorized ? 'authorized' : 'unauthorized');
process.stdin.pipe(cleartextStream);
process.stdin.resume();
});
cleartextStream.setEncoding('utf8');
cleartextStream.on('data', function(data) {
console.log(data);
});
cleartextStream.on('end', function() {
server.close();
});
tls.createSecurePair([credentials], [isServer], [requestCert], [rejectUnauthorized])#
二つのストリームを持つセキュアペアオブジェクトを作成します。 一つは暗号化されたデータを読み書きし、もう一つは平文のデータを読み書きします。 通常、暗号化されたストリームに外部からの暗号化されたデータが連結され、 暗号化されたストリームの代わりに平文のストリームが使われます。
credentials:crypto.createCredentials( ... )で作成された 証明書オブジェクト。isServer: この TLS コネクションをサーバとしてオープンするかどうかを示す ブーリアン値。requestCert: クライアントからの接続に対して、サーバがクライアントに 証明書を要求するかどうかを示すブーリアン値。 サーバコネクションにのみ適用されます。rejectUnauthorized: クライアント認証が不正だった場合に、 自動的にクライアントを破棄するかどうかを示すブーリアン値。requestCertが有効なサーバにのみ適用されます。
tls.createSequrePair() は、cleartext と encrypted
をプロパティとして持つ SecurePair オブジェクトを返します。
Class: SecurePair#
Returned by tls.createSecurePair.
Event: 'secure'#
SecurePair オブジェクトのペアが安全な接続を確立した場合に発生します。
サーバの 'secureConnection' イベントと同様に、
pari.cleartext.authorized によって接続相手の証明書を承認できたかどうかを
チェックすることができます。
Class: tls.Server#
このクラスは net.Server のサブクラスで、同じメソッドを持っています。
生の TCP コネクションを受け入れる代わりに、
TLS または SSL を使った暗号化されたコネクションを受け付けます。
Event: 'secureConnection'#
function (cleartextStream) {}
このイベントは、新しい接続のハンドシェークが成功した場合に生成されます。 引数は CleartextStream のインスタンスです。 これはストリームに共通する全てのメソッドとイベントを持っています。
cleartextStream.authorized は提供された認証局のいずれかによって認証されたかを示す boolean 値です。
cleartextStream.authorized が false の場合、
cleartextStream.authorizationError にはどのように認証が失敗したのかが設定されます。
暗黙的ですが言及する価値のあること:
TLS サーバの設定に依存しますが、認証されていないコネクションも受け入れられることがあります。
cleartextStream.npnProtocol は、選択された NPN プロトコルを持つ文字列です。
cleartextStream.servername は、SNI でリクエストされたサーバ名を持つ
文字列です。
Event: 'clientError'#
function (exception) { }
セキュアコネクションが確立される前にクライアントコネクションが
'error' イベントを発した場合 - ここに転送されます。
server.listen(port, [host], [callback])#
指定の port と host で接続の受け入れを開始します。
host が省略されると、サーバはどんな IPv4 アドレスからのコネクションも受け入れます (INADDR_ANY)。
この関数は非同期です。
最後の引数 callback はサーバがバインドされると呼び出されます。
より詳細は net.Server を参照してください。
server.close()#
サーバが新しい接続を受け入れることを終了します。
この関数は非同期で、サーバが最終的にクローズされるとサーバは 'close' イベントを生成します。
server.address()#
オペレーティングシステムから報告された、 サーバにバインドされたアドレスとポートを返します。 より詳しくは net.Server.address() を参照してください。
server.addContext(hostname, credentials)#
クライアントが要求してきた SNI ホスト名と hostname (ワイルドカードを使用可能)
がマッチした場合のセキュリティコンテキストを追加します。
credentials は key、cert、そして ca を含むことができます。
server.maxConnections#
このプロパティを設定すると、サーバの接続数がこれを越えた場合に接続を破棄します。
server.connections#
サーバの並行コネクションの数です。
Class: tls.CleartextStream#
暗号化されたストリーム上で、暗号化されたデータを平文のデータとして 読み書きすることができるストリームです。
このインスタンスは双方向の Stream インタフェースを 実装します。 ストリームに共通な全てのメソッドとイベントを持ちます。
ClearText ストリームは SecurePair オブジェクトの clear メンバです。
Event: 'secureConnect'#
新しいコネクションの TLS/SSL ハンドシェークが成功すると生成されます。
リスナはサーバの証明書が認証されたかどうかに関わらず呼び出されます。
サーバ証明書が指定した認証局に承認されたかチェックするために
cleartextStream.authorized を確認するかはユーザ次第です。
cleartextStream.authorized === falseの場合、
cleartextStream.authorizationError からエラーを見つけることができます。
同様に NPN が使われている場合は cleartextStream.npnProtocol
から合意されたプロトコルをチェックすることが出来ます。
cleartextStream.authorized#
接続相手の証明書が CA の一つによって署名されていれば true、
そうでなければ false です。
cleartextStream.authorizationError#
接続相手の証明書が認証されなかった理由です。
このプロパティは cleartextStream.authorized === false
の場合だけ利用可能になります。
cleartextStream.getPeerCertificate()#
接続相手の証明書を表現するオブジェクトを返します。 返されるオブジェクトは証明書のフィールドに対応するプロパティを持ちます。
例:
{ subject:
{ C: 'UK',
ST: 'Acknack Ltd',
L: 'Rhys Jones',
O: 'node.js',
OU: 'Test TLS Certificate',
CN: 'localhost' },
issuer:
{ C: 'UK',
ST: 'Acknack Ltd',
L: 'Rhys Jones',
O: 'node.js',
OU: 'Test TLS Certificate',
CN: 'localhost' },
valid_from: 'Nov 11 09:52:22 2009 GMT',
valid_to: 'Nov 6 09:52:22 2029 GMT',
fingerprint: '2A:7A:C2:DD:E5:F9:CC:53:72:35:99:7A:02:5A:71:38:52:EC:8A:DF' }
接続相手が証明書を提供しなかった場合は、
null または空のオブジェクトを返します。
cleartextStream.address()#
オペレーティングシステムから報告された、
ソケットにバインドされたアドレスとポートを返します。
返されるオブジェクトは二つのプロパティを持ちます。
例えば、{"address":"192.168.57.1", "port":62053}
cleartextStream.remoteAddress#
リモートの IP アドレスを表現する文字列です。
例えば、'74.125.127.100' あるいは '2001:4860:a005::68'。
cleartextStream.remotePort#
リモートポートの数値表現です。
例えば、443。