Node.js v0.11.11 マニュアル & ドキュメンテーション


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: certificate
  • inkey: private key
  • certfile: all CA certs concatenated in one file like cat ca1-cert.pem ca2-cert.pem > ca-cert.pem

Client-initiated renegotiation attack mitigation#

TLS プロトコルでは、クライアントに TLS セッションの再ネゴシエーションを 許します。

残念ながら、セッション再ネゴシエーション要求はサーバサイドに過度なリソースを 要求するため、それは潜在的なサーバ強制停止攻撃となります。

これを軽減するために、再ネゴシエーションは 10 分当たり 3 回までに 制限されています。この制限を超えると、tls.TLSSocket のインスタンス上でエラーが生成されます。この制限は変更可能です:

  • 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 サーバでホスト名の異なる複数の証明書を使用。

Perfect Forward Secrecy#

用語 "Forward Secrecy" あるいは "Perfect Forward Secrecy" とは、 鍵を合意 (すなわち鍵交換) する方法の特徴を説明します。 実際のところ、それは (あなたの) サーバの秘密鍵が漏洩しても、 盗聴者によって解読される通信は、特定の各セッション毎に生成される 鍵のペアを取得したものに限られることを意味します。

これは、ハンドシェークの度にランダムに生成される鍵のペアによって 鍵合意することで達成されます (全てのセッションで同じ鍵を使うのとは対照的です)。 Perfect Forward Secrecy を提供するこの方法の実装は、 「一時的 (ephemeral)」と呼ばれます。

現在の所、Perfect Forward Secrecyとして2つの方法が一般的に使われています (従来の省略形に文字 "E" が負荷されていることに注意してください):

  • DHE - ディフィー・ヘルマン鍵合意プロトコルの「一時的」版です。
  • ECDHE - 楕円曲線ディフィー・ヘルマン鍵合意プロトコルの「一時的」版です。

鍵の生成は高価な処理であるため、「一時的」な方法はパフォーマンスの面で 不利かもしれません。

tls.getCiphers()#

サポートされている SSL 暗号名の配列を返します。

例:

var ciphers = tls.getCiphers();
console.log(ciphers); // ['AES128-SHA', 'AES256-SHA', ...]

tls.createServer(options, [secureConnectionListener])#

新しい tls.Server を作成します。 connectionListenersecureConnection イベントのリスナとして 自動的に登録されます。 options は以下を持つことができます:

  • pfx : PFX または PKCS12 でエンコードされた秘密鍵、証明書、および CA の 証明書を含む文字列またはバッファ (keycert、および ca オプションとは相互に排他的です)。

  • key: PEM フォーマットによるサーバの秘密鍵を持つ文字列または Buffer です (必須)。

  • passphrase: 秘密鍵または pfx のパスフレーズを表す文字列です。

  • cert: PEM フォーマットによる証明書の鍵を持つ文字列または Buffer です (必須)。

  • ca: PEM フォーマットによる信頼できる証明書の文字列または Buffer の配列です。 省略された場合、ベリサインなどのよく知られた「ルート」認証局が使われます。 これらはコネクションの認証に使われます。

  • crl : PEM でエンコードされた CRL (Certificate Revocation List、 失効した証明書の一覧) の文字列または文字列の配列。

  • ciphers: 使用または除外する暗号を記述した文字列です。

    BEAST 攻撃を抑制するために、このオプションと以下に示す honorCipherOrder を共に使って、非 CBC 暗号を優先することを推奨します。

    デフォルトは ECDHE-RSA-AES128-SHA256:AES128-GCM-SHA256:RC4:HIGH:!MD5:!aNULL:!EDH です。 詳細は OpenSSL 暗号リストフォーマットのドキュメント を参照してください。

    ECDHE-RSA-AES128-SHA256AES128-GCM-SHA256 は TLS v1.2 の暗号で、 Node.js が (バンドルされているバージョンなどの) OpenSSL 1.0.1 以降と リンクされている場合に使われます。 honorCipherOrder が有効でない限り、TLS v1.2 を使用していても クライアントはより弱い暗号を要求出来ることに注意してください。

    RC4 は、クライアントがより古いバージョンの TLS プロトコルを喋る場合に フォールバックとして使われます。 RC4 は近年疑いをもたれており、真に繊細なものに対しては 漏洩を考慮すべきです。 国家レベルの何者かがそれを破る力を持っていると推測されています。

    注意: 以前のバージョンのこのセクションは AES256-SHA を 受け入れ可能な暗号であるかのように示していました。 残念ながら、AES256-SHA は CBC 暗号であり、したがって BEAST 攻撃 には弱いです。 使わない でください。

  • ecdhCurve: ECDH 鍵合意で使用する曲線を説明する名前、または全ての ECDH を無効にする false

    デフォルトは prime256v1 です。より詳細は RFC 4492 を参照してください。

  • handshakeTimeout: SSL/TLS ハンドシェークがこの時間 (ミリ秒) 以内に終了しなかった場合は接続をアボートします。 デフォルトは 120 秒です。

    ハンドシェークがタイムアウトすると、tls.Server オブジェクトで 'clientError' イベントが生成されます。

  • honorCipherOrder : 暗号を選択する際に、クライアントではなくサーバの設定を使用します。

    このオプションはデフォルトでは無効ですが、BEAST 攻撃を抑制するために ciphers オプションと共に使用することを 推奨 します。

    注意: SSLv2 が使われる場合は、サーバは設定のリストをクライアントに送信し、 クライアントが暗号を選択します。 SSLv2 のサポートは、node.js が ./configure --with-sslv2 によって 構成されない限り無効です。

  • requestCert: true の場合、サーバは接続しようとするクライアントからの 証明書を要求します。デフォルトは false です。

  • rejectUnauthorized: true の場合、サーバは提供された認証局の リストによって認証されていないコネクションを破棄します. このオプションは requestCerttrue の場合だけ効果があります。 デフォルトは false です。

  • NPNProtocols: NPN プロトコルで使用可能な文字列または Buffer の配列 (プロトコルはその優先度に応じて並んでいる必要があります)。

  • SNICallback(servername, cb): クライアントが TLS 拡張の SNI を サポートしている場合に呼び出される関数です。 二つの引数、servernamecb が渡されます。 SNICallback は、cb(null, ctx) を呼び出す必要があります。 ctx はSecureContext のインスタンスです (SecureContext を取得するために crypto.createCredentials(...).context を使用することができます)。 SNICallback が渡されなかった場合は、デフォルトのコールバックとして 後述する高水準 API が使用されます。

  • sessionTimeout: サーバによって作成された TLS セッション識別子および TLS セッションチケットがタイムアウトするまでの秒数を指定する整数値です。 より詳細は SSL_CTX_set_timeout を参照してください。

  • sessionIdContext: セッション再開のための識別子となる文字列です。 requestCedrttrue の場合、デフォルトはコマンドライン引数から 生成された MD5 ハッシュ値となります。 そうでない場合はデフォルトは提供されません。

  • secureProtocol: 使用する SSL メソッド、たとえば SSLv3_method は SSL version 3 の使用を強制します。可能な値は使用する OpenSSL によって 定義される SSL_METHODS 定数に依存します。

これはシンプルはエコーサーバの例です:

var tls = require('tls');
var fs = require('fs');

var options = {
  key: fs.readFileSync('server-key.pem'),
  cert: fs.readFileSync('server-cert.pem'),

  // This is necessary only if using the client certificate authentication.
  requestCert: true,

  // This is necessary only if the client uses the self-signed certificate.
  ca: [ fs.readFileSync('client-cert.pem') ]
};

var server = tls.createServer(options, function(socket) {
  console.log('server connected',
              socket.authorized ? 'authorized' : 'unauthorized');
  socket.write("welcome!\n");
  socket.setEncoding('utf8');
  socket.pipe(socket);
});
server.listen(8000, function() {
  console.log('server bound');
});

あるいは:

var tls = require('tls');
var fs = require('fs');

var options = {
  pfx: fs.readFileSync('server.pfx'),

  // This is necessary only if using the client certificate authentication.
  requestCert: true,

};

var server = tls.createServer(options, function(socket) {
  console.log('server connected',
              socket.authorized ? 'authorized' : 'unauthorized');
  socket.write("welcome!\n");
  socket.setEncoding('utf8');
  socket.pipe(socket);
});
server.listen(8000, function() {
  console.log('server bound');
});

openssl s_client を使用してこのサーバに接続するテストを行うことができます。

openssl s_client -connect 127.0.0.1:8000

tls.connect(options, [callback])#

tls.connect(port, [host], [options], [callback])#

与えられた porthost (旧 API) または options.portoptions.host で新しいクライアントコネクションを作成します (host が省略された場合、デフォルトは localhost です)。 options は以下を指定したオブジェクトです:

  • host: クライアントが接続するホスト。

  • port: クライアントが接続するポート番号。

  • socket: 新しいソケットを生成するのではなく、与えられたソケット上で セキュアな接続を確立します。 このオプションが指定された場合、host および port は無視されます。

  • pfx : PFX または PKCS12 でエンコードされた秘密鍵、証明書、 およびサーバに対する CA の証明書を含む文字列またはバッファ。

  • key: PEM フォーマットによるサーバの秘密鍵を持つ文字列または Buffer です。

  • passphrase: 秘密鍵または pfx のパスフレーズを表す文字列です。

  • cert: PEM フォーマットによる証明書の鍵を持つ文字列または Buffer です。

  • secureProtocol: The SSL method to use, e.g. SSLv3_method to force SSL version 3. The possible values depend on your installation of OpenSSL and are defined in the constant SSL_METHODS.

  • ca: PEM フォーマットによる信頼できる証明書の文字列または Buffer の配列です。 省略された場合、ベリサインなどのよく知られた「ルート」認証局が使われます。 これらはコネクションの認証に使われます。

  • rejectUnauthorized: true の場合、サーバ証明書は提供された認証局の リストによって検証されます。 認証されなかった場合は 'error' イベントが生成されます; err.code は OpenSSL のエラーコードを含みます。 デフォルトは true です。

  • NPNProtocols: サポートする NPN プロトコルの文字列または Buffer の配列です。 Buffer は次のような形式です: 0x05hello0x5world 最初のバイトは次のプロトコル名の長さです (通常、配列を渡す方がシンプルです: ['hello', 'world'])。

  • servername: TLS 拡張である SNI (Server Name Indication) のサーバ名です。

  • secureProtocol: 使用する SSL メソッド、たとえば SSLv3_method は SSL version 3 の使用を強制します。可能な値は使用する OpenSSL によって 定義される SSL_METHODS 定数に依存します。

callback 引数は 'secureConnect' イベントのリスナとして 加えられます。

tls.connect()tls.TLSSocket オブジェクトを返します。

これは前述のエコーサーバに接続するクライアントの例です:

var tls = require('tls');
var fs = require('fs');

var options = {
  // These are necessary only if using the client certificate authentication
  key: fs.readFileSync('client-key.pem'),
  cert: fs.readFileSync('client-cert.pem'),

  // This is necessary only if the server uses the self-signed certificate
  ca: [ fs.readFileSync('server-cert.pem') ]
};

var socket = tls.connect(8000, options, function() {
  console.log('client connected',
              socket.authorized ? 'authorized' : 'unauthorized');
  process.stdin.pipe(socket);
  process.stdin.resume();
});
socket.setEncoding('utf8');
socket.on('data', function(data) {
  console.log(data);
});
socket.on('end', function() {
  server.close();
});

または:

var tls = require('tls');
var fs = require('fs');

var options = {
  pfx: fs.readFileSync('client.pfx')
};

var socket = tls.connect(8000, options, function() {
  console.log('client connected',
              socket.authorized ? 'authorized' : 'unauthorized');
  process.stdin.pipe(socket);
  process.stdin.resume();
});
socket.setEncoding('utf8');
socket.on('data', function(data) {
  console.log(data);
});
socket.on('end', function() {
  server.close();
});

Class: tls.TLSSocket#

net.Socket のラッパーです。内部的なソケットの read/write 処理を、 入出力データを透過的に暗号化/復号化するように置き換えます。

new tls.TLSSocket(socket, options)#

既存の TCP ソケットから新しい TLSSocket オブジェクトを構築します。

socketnet.Socket のインスタンスです。

options は以下のプロパティを持つことができるオブジェクトです。

  • credentials: crypto.createCredentials( ... ) から得られる オプションの認証情報

  • isServer: もし true なら、TLS ソケットはサーバも土で作成されます

  • server: オプションの net.Server インスタンス

  • requestCert: オプション、tls.createSecurePair を参照

  • rejectUnauthorized: オプション、tls.createSecurePair を参照

  • NPNProtocols: オプション、tls.createServer を参照

  • SNICallback: オプション、tls.createServer を参照

tls.createSecurePair([credentials], [isServer], [requestCert], [rejectUnauthorized])#

Stability: 0 - Deprecated. Use tls.TLSSocket instead.

二つのストリームを持つセキュアペアオブジェクトを作成します。 一つは暗号化されたデータを読み書きし、もう一つは平文のデータを読み書きします。 通常、暗号化されたストリームに外部からの暗号化されたデータが連結され、 暗号化されたストリームの代わりに平文のストリームが使われます。

  • credentials: crypto.createCredentials( ... ) で作成された 証明書オブジェクト。

  • isServer: この TLS コネクションをサーバとしてオープンするかどうかを示す ブーリアン値。

  • requestCert: クライアントからの接続に対して、サーバがクライアントに 証明書を要求するかどうかを示すブーリアン値。 サーバコネクションにのみ適用されます。

  • rejectUnauthorized: クライアント認証が不正だった場合に、 自動的にクライアントを破棄するかどうかを示すブーリアン値。 requestCert が有効なサーバにのみ適用されます。

tls.createSequrePair() は、cleartextencrypted ストリームを プロパティとして持つ SecurePair オブジェクトを返します。

注意: cleartexttls.TLSSocket API と同じです。

Class: SecurePair#

tls.createSecurePair から返されます。

Event: 'secure'#

SecurePair オブジェクトのペアが安全な接続を確立した場合に発生します。

サーバの 'secureConnection' イベントと同様に、 pari.cleartext.authorized によって接続相手の証明書を承認できたかどうかを チェックすることができます。

Class: tls.Server#

このクラスは net.Server のサブクラスで、同じメソッドを持っています。 生の TCP コネクションを受け入れる代わりに、 TLS または SSL を使った暗号化されたコネクションを受け付けます。

Event: 'secureConnection'#

function (tlsSocket) {}

このイベントは、新しい接続のハンドシェークが成功した場合に生成されます。 引数は tls.TLSSocket のインスタンスです。 これはストリームに共通する全てのメソッドとイベントを持っています。

socket.authorized は提供された認証局のいずれかによって 認証されたかを示す boolean 値です。 socket.authorized が false の場合、socket.authorizationError には どのように認証が失敗したのかが設定されます。 暗黙的ですが言及する価値のあること: TLS サーバの設定に依存しますが、 認証されていないコネクションも受け入れられることがあります。 socket.npnProtocol は、選択された NPN プロトコルを持つ文字列です。 socket.servername は、SNI でリクエストされたサーバ名を持つ文字列です。

Event: 'clientError'#

function (exception, tlsSocket) { }

セキュアコネクションが確立される前にクライアントコネクションが 'error' イベントを発した場合 - ここに転送されます。

tlsSocket はエラーが発生した tls.TLSSocket です。

Event: 'newSession'#

function (sessionId, sessionData) { }

TLS セッションが作成された場合に生成されます。 セッションを外部ストレージに保存する場合に使えるでしょう。

注意: このイベントリスナの追加は、イベントリスナが追加された後に確立される 接続に対してのみ効果があります。

Event: 'resumeSession'#

function (sessionId, callback) { }

クライアントが以前の TLS セッションを再開を要求した場合に生成されます。 イベントリスナは与えられた sessionId を使用して外部ストレージから セッションを見つけた場合、callback(null, sessionData) を一度呼び出すことが できます。 セッションを再開できない場合 (すなわち、ストレージに存在しない場合)、 callback(null, null) を呼ぶことができます。 callback(err) を呼び出すと接続を終了し、ソケットを破棄します。

NOTE: adding this event listener will have an effect only on connections established after addition of event listener.

server.listen(port, [host], [callback])#

指定の porthost で接続の受け入れを開始します。 host が省略されると、サーバはどんな IPv4 アドレスからのコネクションも受け入れます (INADDR_ANY)。

この関数は非同期です。 最後の引数 callback はサーバがバインドされると呼び出されます。

より詳細は net.Server を参照してください。

server.close()#

サーバが新しい接続を受け入れることを終了します。 この関数は非同期で、サーバが最終的にクローズされるとサーバは 'close' イベントを生成します。

server.address()#

オペレーティングシステムから報告された、サーバにバインドされたアドレスと アドレスファミリ名、ポートを返します。 より詳しくは net.Server.address() を参照してください。

server.addContext(hostname, credentials)#

クライアントが要求してきた SNI ホスト名と hostname (ワイルドカードを使用可能) がマッチした場合のセキュリティコンテキストを追加します。 credentialskeycert、そして ca を含むことができます。

server.maxConnections#

このプロパティを設定すると、サーバの接続数がこれを越えた場合に接続を破棄します。

server.connections#

サーバの並行コネクションの数です。

Class: CryptoStream#

Stability: 0 - Deprecated. Use tls.TLSSocket instead.

これは暗号化されたストリームです。

cryptoStream.bytesWritten#

下層にあるソケットの bytesWritten にアクセスするプロキシで、 TLS のオーバーヘッドを含めて ソケットに書き込まれたトータルのバイト数を 返します。

Class: tls.TLSSocket#

これは暗号化されたデータの透過的な書き込みなど、 TLS ネゴシエーションによって 要求される全てを行う net.Socket のラップされたバージョンです。

このインスタンスは双方向の Stream インタフェースを実装します。 ストリームに共通な全てのメソッドとイベントを持ちます。

Event: 'secureConnect'#

新しいコネクションの TLS/SSL ハンドシェークが成功すると生成されます。 リスナはサーバの証明書が認証されたかどうかに関わらず呼び出されます。 サーバ証明書が指定した認証局に承認されたかチェックするために tlsSocket.authorized を確認するかはユーザ次第です。 tlsSocket.authorized === falseの場合、 tlsSocket.authorizationError からエラーを見つけることができます。 同様に NPN が使われている場合は tlsSocket.npnProtocol から合意されたプロトコルをチェックすることが出来ます。

tlsSocket.encrypted#

静的な論理値で、常に true です。 TLS ソケットを通常のソケットと区別したい場合に使うことが出来ます。

tlsSocket.authorized#

接続相手の証明書が CA の一つによって署名されていれば true、 そうでなければ false です。

tlsSocket.authorizationError#

接続相手の証明書が認証されなかった理由です。 このプロパティは tlsSocket.authorized === false の場合だけ利用可能になります。

tlsSocket.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',
  serialNumber: 'B9B0D332A1AA5635' }

接続相手が証明書を提供しなかった場合は、 null または空のオブジェクトを返します。

tlsSocket.getCipher()#

現在の接続における暗号と SSL/TLS プロトコルのバージョンを表現する オブジェクトを返します。

例:

{ name: 'AES256-SHA', version: 'TLSv1/SSLv3' }

詳細は http://www.openssl.org/docs/ssl/ssl.html#DEALING_WITH_CIPHERSSSL_CIPHER_get_name() および SSL_CIPHER_get_version() を 参照してください。

tlsSocket.renegotiate(options, callback)#

TLSの再ネゴシエーションを開始します。 optionsは以下のフィールドを含むことが出来ます: rejectUnauthorizedrequestCert (詳細は tls.createServer 参照)。 callback(err) は再ネゴシエーションが成功で完了すると、errnull で 実行されます。

注意: 相手側の証明書は、セキュアな接続が確立された後で利用可能になります。

更に注意: サーバとして実行される場合、handshakeTimeout 時間が経過した後、 ソケットはエラーと共に破棄されます。

tlsSocket.setMaxSendFragment(size)#

最大の TLS フラグメントサイズを設定します (デフォルトおよび最大の値は 16384、 最少は 512)。 成功すれば true、そうでなければ false を返します。

小さなフラグメントサイズは、クライアントでのバッファリングの遅延を減少します: 大きなフラグメントは、全てのフラグメントが受信されてその完全性が確かめられるまで TLS 層によってバッファリングされます; 大きなフラグメントは複数のラウンドトリップに分割され、 パケットの喪失や並べ替えにより遅延が発生することがあります。 しかしながら、小さなフラグメントは余分な TLS フレームのバイトと CPU のオーバーヘッドを加えるため、全体としてサーバのスループットを 低下させるでしょう。

tlsSocket.address()#

オペレーティングシステムから報告された、ソケットにバインドされたアドレスと アドレスファミリ名、ポートを返します。 返されるオブジェクトは二つのプロパティを持ちます。例: { port: 12346, family: 'IPv4', address: '127.0.0.1' }

tlsSocket.remoteAddress#

リモートの IP アドレスを表現する文字列です。 例えば、'74.125.127.100' あるいは '2001:4860:a005::68'

tlsSocket.remotePort#

リモートポートの数値表現です。 例えば、443

tlsSocket.localAddress#

文字列表現によるローカル IP アドレスです。

tlsSocket.localPort#

数値表現によるローカルポートです。