# TLS (SSL)
~~~
穩(wěn)定度: 3 - 穩(wěn)定
~~~
使用 `require('tls')` 來訪問此模塊。
`tls` 模塊使用 OpenSSL 來提供傳輸層安全協(xié)議(Transport Layer Security)和/或安全套接層(Secure Socket Layer):加密過的流通訊。
TLS/SSL 是一種公鑰/私鑰架構(gòu)。每個(gè)客戶端和服務(wù)器都必有一個(gè)私鑰。一個(gè)私鑰使用類似的方式創(chuàng)建:
~~~
openssl genrsa -out ryans-key.pem 1024
~~~
所有服務(wù)器和某些客戶端需要具備證書。證書是證書辦法機(jī)構(gòu)簽發(fā)或自簽發(fā)的公鑰。獲取證書的第一步是創(chuàng)建一個(gè)“證書簽發(fā)申請”(CSR)文件。使用這條命令完成:
~~~
openssl req -new -key ryans-key.pem -out ryans-csr.pem
~~~
像這樣使用 CSR 創(chuàng)建一個(gè)自簽名證書:
~~~
openssl x509 -req -in ryans-csr.pem -signkey ryans-key.pem -out ryans-cert.pem
~~~
又或者你可以將 CSR 發(fā)送給一個(gè)數(shù)字證書認(rèn)證機(jī)構(gòu)請求簽名。
(TODO: 對于創(chuàng)建一個(gè)CA文檔, 感興趣的用戶暫時(shí)只能看Node的源代碼`test/fixtures/keys/Makefile`
像這樣創(chuàng)建 .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`
### 客戶端初始化的對緩解攻擊的重新協(xié)商
TLS協(xié)議會(huì)令客戶端可以重新協(xié)商TLS會(huì)話的某些方面。但是,會(huì)話的重新協(xié)商是需要相應(yīng)量的服務(wù)器端資源的,所以導(dǎo)致其變成一個(gè)阻斷服務(wù)攻擊(denial-of-service)的潛在媒介。
為了減低這種情況的發(fā)生,重新協(xié)商被限制在每10分鐘三次。如果超過這個(gè)數(shù)目,那么在[tls.TLSSocket](#)實(shí)例上就會(huì)分發(fā)一個(gè)錯(cuò)誤。這個(gè)限制是可設(shè)置的:
- `tls.CLIENT_RENEG_LIMIT`: 重新協(xié)商的次數(shù)限制,默認(rèn)為3。
- `tls.CLIENT_RENEG_WINDOW`: 重新協(xié)商窗口的秒數(shù),默認(rèn)為600(10分鐘)。
除非你完全理解整個(gè)機(jī)制和清楚自己要干什么,否則不要改變這個(gè)默認(rèn)值。
要測試你的服務(wù)器的話,用命令 `openssl s_client -connect 地址:端口`連接上服務(wù)器,然后敲擊`R<CR>`(字母鍵`R`加回車鍵)幾次。
### NPN 和 SNI
NPN (Next Protocol Negotiation,下一個(gè)協(xié)議的協(xié)商)和SNI (Server Name Indication,服務(wù)器名稱指示)是TLS握手?jǐn)U展,它們允許你:
- NPN - 同一個(gè)TLS服務(wù)器使用多種協(xié)議 (HTTP, SPDY)
- SNI - 同一個(gè)TLS服務(wù)器使用多個(gè)主機(jī)名,與其相應(yīng)的SSL證書。
### tls.getCiphers()
返回一個(gè)數(shù)組,其中包含了所支持的SSL加密器的名字。
實(shí)例:
~~~
var ciphers = tls.getCiphers();
console.log(ciphers); // ['AES128-SHA', 'AES256-SHA', ...]
~~~
### tls.createServer(options, [secureConnectionListener])
新建一個(gè)新的 [tls.Server](#). The `connectionListener` 參數(shù)會(huì)自動(dòng)設(shè)置為 [secureConnection](#) 事件的監(jiān)聽器. 這個(gè) `options` 對象有這些可能性:
- `pfx`: 一個(gè)String 或`Buffer`包含了私鑰, 證書和CA certs, 一般是 PFX 或者 PKCS12 格式. (Mutually exclusive with the `key`, `cert` and `ca` options.)
- `key`: 一個(gè)字符串或 `Buffer`對象,其中包含了PEF格式的服務(wù)器的私鑰。 (必需)
- `passphrase`: 私鑰或pfx密碼的字符串。
- `cert`: 字符串或者 `Buffer`,包含PEM格式的服務(wù)器證書密碼。(必選)
- `ca`: An array of strings or `Buffer`s of trusted certificates. If this is omitted several well known "root" CAs will be used, like VeriSign. These are used to authorize connections.
- `crl` : Either a string or list of strings of PEM encoded CRLs (Certificate Revocation List)
- `ciphers`: 一個(gè)字符串,描述了使用或排除的cipher。
~~~
**NOTE**: Previous revisions of this section suggested `AES256-SHA` as an
acceptable cipher. Unfortunately, `AES256-SHA` is a CBC cipher and therefore
susceptible to BEAST attacks. Do *not* use it.
~~~
- `handshakeTimeout`: Abort the connection if the SSL/TLS handshake does not finish in this many milliseconds. The default is 120 seconds.
~~~
`tls.Server`對象在握手超時(shí)時(shí),總會(huì)觸發(fā)`'clientError'`事件。
~~~
- `honorCipherOrder` : 當(dāng)選擇cipher時(shí),使用服務(wù)器設(shè)置,而不是客戶端設(shè)置。
~~~
Although, this option is disabled by default, it is *recommended* that you
use this option in conjunction with the `ciphers` option to mitigate
BEAST attacks.
~~~
- `requestCert`: If `true` the server will request a certificate from clients that connect and attempt to verify that certificate. Default: `false`.
- `rejectUnauthorized`: If `true` the server will reject any connection which is not authorized with the list of supplied CAs. This option only has an effect if `requestCert` is `true`. Default: `false`.
- `NPNProtocols`: 一個(gè)數(shù)組或 `Buffer`,包含了可能的 NPN 協(xié)議。(協(xié)議應(yīng)根據(jù)優(yōu)先級排序)
- `SNICallback(servername, cb)`: A function that will be called if client supports SNI TLS extension. Two argument will be passed to it: `servername`, and `cb`. `SNICallback` should invoke `cb(null, ctx)`, where `ctx` is a SecureContext instance. (You can use `crypto.createCredentials(...).context` to get proper SecureContext). If `SNICallback` wasn't provided - default callback with high-level API will be used (see below).
- `sessionTimeout`: An integer specifying the seconds after which TLS session identifiers and TLS session tickets created by the server are timed out. See [SSL_CTX_set_timeout](http://www.openssl.org/docs/ssl/SSL_CTX_set_timeout.html) for more details.
- `sessionIdContext`: A string containing a opaque identifier for session resumption. If `requestCert` is `true`, the default is MD5 hash value generated from command-line. Otherwise, the default is not provided.
- `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](http://www.openssl.org/docs/ssl/ssl.html#DEALING_WITH_PROTOCOL_METHODS).
這是一個(gè)簡單的應(yīng)答服務(wù)器例子:
~~~
var server = tls.createServer(options, function(socket) {
console.log('服務(wù)器已連接',
socket.authorized ? '已授權(quán)' : '未授權(quán)');
socket.write("歡迎!\n");
socket.setEncoding('utf8');
socket.pipe(socket);
});
server.listen(8000, function() {
console.log('server bound');
});
~~~
或者
~~~
};
~~~
~~~
var server = tls.createServer(options, function(socket) {
console.log('服務(wù)器已連接',
socket.authorized ? '已授權(quán)' : '未授權(quán)');
socket.write("歡迎!\n");
socket.setEncoding('utf8');
socket.pipe(socket);
});
server.listen(8000, function() {
console.log('服務(wù)器已綁定');
});
~~~
您可以使用 `openssl s_client` 連接這個(gè)服務(wù)器來測試:
~~~
openssl s_client -connect 127.0.0.1:8000
~~~
### tls.connect(options, [callback])
### tls.connect(port, [host], [options], [callback])
Creates a new client connection to the given `port` and `host` (old API) or `options.port` and `options.host`. (If `host` is omitted, it defaults to `localhost`.) `options` should be an object which specifies:
- `host`: 客戶端應(yīng)連接到的主機(jī)
- `port`: 客戶端應(yīng)連接到的端口
- `socket`: Establish secure connection on a given socket rather than creating a new socket. If this option is specified, `host` and `port` are ignored.
- `pfx`: 字符串或者 `Buffer`,包含 PFX 或 PKCS12 格式的服務(wù)器私鑰、證書和CA證書。
- `key`: 字符串或 `Buffer`,包含 PEM 格式的客戶端私鑰。
- `passphrase`: 私鑰或pfx密碼的字符串。
- `cert`: 字符串或 `Buffer`,包含PEM格式的客戶端證書密碼。
- `ca`: An array of strings or `Buffer`s of trusted certificates. If this is omitted several well known "root" CAs will be used, like VeriSign. These are used to authorize connections.
- `rejectUnauthorized`: If `true`, the server certificate is verified against the list of supplied CAs. An `'error'` event is emitted if verification fails. Default: `true`.
- `NPNProtocols`: An array of string or `Buffer` containing supported NPN protocols. `Buffer` should have following format: `0x05hello0x05world`, where first byte is next protocol name's length. (Passing array should usually be much simpler: `['hello', 'world']`.)
- `servername`: SNI (Server Name Indication) TLS 擴(kuò)展的服務(wù)器名。
- `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](http://www.openssl.org/docs/ssl/ssl.html#DEALING_WITH_PROTOCOL_METHODS).
`callback`參數(shù)會(huì)被作為監(jiān)聽器添加到['secureConnect'](#)事件。
`tls.connect()`返回一個(gè)[tls.TLSSocket](#)對象。
下面是一個(gè)上述應(yīng)答服務(wù)器的客戶端的例子:
~~~
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 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
Wrapper for instance of [net.Socket](#), replaces internal socket read/write routines to perform transparent encryption/decryption of incoming/outgoing data.
### new tls.TLSSocket(socket, options)
Construct a new TLSSocket object from existing TCP socket.
`socket`是一個(gè)[net.Socket](#)示例。
`options`是一個(gè)可能包含以下屬性的對象:
- `credentials`: 可選的,通過`crypto.createCredentials( ... )`得到的資格對象。
- `isServer`: 如果為真——TLS套接字將在服務(wù)器模式下實(shí)例化。
- `server`: 一個(gè)可選的[net.Server](#)實(shí)例
- `requestCert`: 可選的,見[tls.createSecurePair](#)
- `rejectUnauthorized`: 可選的,見[tls.createSecurePair](#)
- `NPNProtocols`: 可選的,見[tls.createServer](#)
- `SNICallback`: 可選的,見[tls.createServer](#)
### tls.createSecurePair([credentials], [isServer], [requestCert], [rejectUnauthorized])
~~~
穩(wěn)定性: 0 - 已廢棄。使用 tls.TLSSocket 替代。
~~~
Creates a new secure pair object with two streams, one of which reads/writes encrypted data, and one reads/writes cleartext data. Generally the encrypted one is piped to/from an incoming encrypted data stream, and the cleartext one is used as a replacement for the initial encrypted stream.
- `credentials`: 通過`crypto.createCredentials( ... )`得到的資格對象
- `isServer`: A boolean indicating whether this tls connection should be opened as a server or a client.
- `requestCert`: A boolean indicating whether a server should request a certificate from a connecting client. Only applies to server connections.
- `rejectUnauthorized`: A boolean indicating whether a server should automatically reject clients with invalid certificates. Only applies to servers with `requestCert` enabled.
`tls.createSecurePair()` returns a SecurePair object with `cleartext` and `encrypted` stream properties.
NOTE: `cleartext` has the same APIs as [tls.TLSSocket](#)
### 類: SecurePair
由tls.createSecurePair返回。
### 事件: 'secure'
The event is emitted from the SecurePair once the pair has successfully established a secure connection.
Similarly to the checking for the server 'secureConnection' event, pair.cleartext.authorized should be checked to confirm whether the certificate used properly authorized.
### 類: tls.Server
This class is a subclass of `net.Server` and has the same methods on it. Instead of accepting just raw TCP connections, this accepts encrypted connections using TLS or SSL.
### 事件: 'secureConnection'
`function (tlsSocket) {}`
This event is emitted after a new connection has been successfully handshaked. The argument is a instance of [tls.TLSSocket](#). It has all the common stream methods and events.
`socket.authorized` is a boolean value which indicates if the client has verified by one of the supplied certificate authorities for the server. If `socket.authorized` is false, then `socket.authorizationError` is set to describe how authorization failed. Implied but worth mentioning: depending on the settings of the TLS server, you unauthorized connections may be accepted. `socket.npnProtocol` is a string containing selected NPN protocol. `socket.servername` is a string containing servername requested with SNI.
### Event: 'clientError'
`function (exception, tlsSocket) { }`
When a client connection emits an 'error' event before secure connection is established - it will be forwarded here.
`tlsSocket`就是`[tls.TLSSocket][]`,錯(cuò)誤產(chǎn)生的地方。
### 事件: 'newSession'
`function (sessionId, sessionData) { }`
Emitted on creation of TLS session. May be used to store sessions in external storage.
NOTE: adding this event listener will have an effect only on connections established after addition of event listener.
### 事件: 'resumeSession'
`function (sessionId, callback) { }`
Emitted when client wants to resume previous TLS session. Event listener may perform lookup in external storage using given `sessionId`, and invoke `callback(null, sessionData)` once finished. If session can't be resumed (i.e. doesn't exist in storage) one may call `callback(null, null)`. Calling `callback(err)` will terminate incoming connection and destroy socket.
NOTE: adding this event listener will have an effect only on connections established after addition of event listener.
### server.listen(port, [host], [callback])
Begin accepting connections on the specified `port` and `host`. If the `host` is omitted, the server will accept connections directed to any IPv4 address (`INADDR_ANY`).
This function is asynchronous. The last parameter `callback` will be called when the server has been bound.
更多信息見`net.Server`。
### server.close()
Stops the server from accepting new connections. This function is asynchronous, the server is finally closed when the server emits a `'close'` event.
### server.address()
Returns the bound address, the address family name and port of the server as reported by the operating system. See [net.Server.address()](#) for more information.
### server.addContext(hostname, credentials)
Add secure context that will be used if client request's SNI hostname is matching passed `hostname` (wildcards can be used). `credentials` can contain `key`, `cert` and `ca`.
### server.maxConnections
Set this property to reject connections when the server's connection count gets high.
### server.connections
服務(wù)器的并發(fā)連接數(shù).
### 類: CryptoStream
~~~
穩(wěn)定性: 0 - 已廢棄。使用 tls.TLSSocket 替代。
~~~
這是一個(gè)被加密的流。
### cryptoStream.bytesWritten
A proxy to the underlying socket's bytesWritten accessor, this will return the total bytes written to the socket, *including the TLS overhead*.
### Class: tls.TLSSocket
This is a wrapped version of [net.Socket](#) that does transparent encryption of written data and all required TLS negotiation.
This instance implements a duplex [Stream](#) interfaces. It has all the common stream methods and events.
### 事件: 'secureConnect'
This event is emitted after a new connection has been successfully handshaked. The listener will be called no matter if the server's certificate was authorized or not. It is up to the user to test `tlsSocket.authorized` to see if the server certificate was signed by one of the specified CAs. If `tlsSocket.authorized === false` then the error can be found in `tlsSocket.authorizationError`. Also if NPN was used - you can check `tlsSocket.npnProtocol` for negotiated protocol.
### tlsSocket.authorized
A boolean that is `true` if the peer certificate was signed by one of the specified CAs, otherwise `false`
### tlsSocket.authorizationError
The reason why the peer's certificate has not been verified. This property becomes available only when `tlsSocket.authorized === false`.
### tlsSocket.getPeerCertificate()
Returns an object representing the peer's certificate. The returned object has some properties corresponding to the field of the certificate.
實(shí)例:
~~~
{ 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' }
~~~
如果節(jié)點(diǎn)沒有提供證書, 它將返回 `null` 或者一個(gè)空對象.
### tlsSocket.getCipher()
返回一個(gè)對象,表示了當(dāng)前連接的cipher名與SSL/TLS協(xié)議版本。
Example: { name: 'AES256-SHA', version: 'TLSv1/SSLv3' }
See SSL_CIPHER_get_name() and SSL_CIPHER_get_version() in [http://www.openssl.org/docs/ssl/ssl.html#DEALING_WITH_CIPHERS](http://www.openssl.org/docs/ssl/ssl.html#DEALING_WITH_CIPHERS) for more information.
### tlsSocket.renegotiate(options, callback)
Initiate TLS renegotiation process. The `options` may contain the following fields: `rejectUnauthorized`, `requestCert` (See [tls.createServer](#) for details). `callback(err)` will be executed with `null` as `err`, once the renegotiation is successfully completed.
NOTE: Can be used to request peer's certificate after the secure connection has been established.
ANOTHER NOTE: When running as the server, socket will be destroyed with an error after `handshakeTimeout` timeout.
### tlsSocket.address()
Returns the bound address, the address family name and port of the underlying socket as reported by the operating system. Returns an object with three properties, e.g. `{ port: 12346, family: 'IPv4', address: '127.0.0.1' }`
### tlsSocket.remoteAddress
遠(yuǎn)程IP地址的字符串表示。例如,`'74.125.127.100'`或 `'2001:4860:a005::68'`。
### tlsSocket.remotePort
遠(yuǎn)程端口的數(shù)值表示。例如, `443`。
### tlsSocket.localAddress
本地IP地址的字符串表達(dá)。
### tlsSocket.localPort
本地端口的數(shù)值表示。
- 關(guān)于本文檔
- 概述
- 斷言 (assert)
- Buffer
- Addons插件
- 子進(jìn)程
- 集群
- 控制臺
- 加密(Crypto)
- 調(diào)試器
- DNS
- 域
- 事件 (Events)
- File System
- 全局對象
- HTTP
- HTTPS
- Modules
- net
- 操作系統(tǒng)
- 路徑 (Path)
- process
- punycode
- Query String
- Readline
- REPL
- Smalloc
- 流
- 字符串解碼器
- 定時(shí)器
- TLS (SSL)
- TTY
- UDP / 數(shù)據(jù)報(bào)套接字
- URL
- utils
- 執(zhí)行 JavaScript
- Zlib
- 進(jìn)度
- 感謝
