You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

327 lines
12 KiB

## TLS (SSL)
Use `require('tls')` to access this module.
The `tls` module uses OpenSSL to provide Transport Layer Security and/or
Secure Socket Layer: encrypted stream communication.
TLS/SSL is a public/private key infrastructure. Each client and each
server must have a private key. A private key is created like this
openssl genrsa -out ryans-key.pem 1024
All severs and some clients need to have a certificate. Certificates are public
keys signed by a Certificate Authority or self-signed. The first step to
getting a certificate is to create a "Certificate Signing Request" (CSR)
file. This is done with:
openssl req -new -key ryans-key.pem -out ryans-csr.pem
To create a self-signed certificate with the CSR, do this:
openssl x509 -req -in ryans-csr.pem -signkey ryans-key.pem -out ryans-cert.pem
Alternatively you can send the CSR to a Certificate Authority for signing.
(TODO: docs on creating a CA, for now interested users should just look at
`test/fixtures/keys/Makefile` in the Node source code)
#### tls.createServer(options, secureConnectionListener)
Creates a new [tls.Server](#tls.Server).
The `connectionListener` argument is automatically set as a listener for the
[secureConnection](#event_secureConnection_) event.
The `options` object has these possibilities:
- `key`: A string or `Buffer` containing the private key of the server in
PEM format. (Required)
- `cert`: A string or `Buffer` containing the certificate key of the server in
PEM format. (Required)
- `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.
- `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`: An array or `Buffer` of possible NPN protocols. (Protocols
should be ordered by their priority).
- `SNICallback`: A function that will be called if client supports SNI TLS
extension. Only one argument will be passed to it: `servername`. And
`SNICallback` should return 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).
- `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.
Here is a simple example echo server:
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(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');
});
You can test this server by connecting to it with `openssl s_client`:
openssl s_client -connect 127.0.0.1:8000
#### tls.connect(port, [host], [options], secureConnectListener)
Creates a new client connection to the given `port` and `host`. (If `host`
defaults to `localhost`.) `options` should be an object which specifies
- `key`: A string or `Buffer` containing the private key of the client in
PEM format. (Required)
- `cert`: A string or `Buffer` containing the certificate key of the client in
PEM format.
- `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.
- `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 simplier: `['hello', 'world']`.)
- `servername`: Servername for SNI (Server Name Indication) TLS extension.
The `secureConnectListener` parameter will be added as a listener for the
['secureConnect'](#event_secureConnect_) event.
`tls.connect()` returns a [CleartextStream](#tls.CleartextStream) object.
Here is an example of a client of echo server as described previously:
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 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();
});
### STARTTLS
In the v0.4 branch no function exists for starting a TLS session on an
already existing TCP connection. This is possible it just requires a bit of
work. The technique is to use `tls.createSecurePair()` which returns two
streams: an encrypted stream and a cleartext stream. The encrypted stream is
then piped to the socket, the cleartext stream is what the user interacts with
thereafter.
[Here is some code that does it.](http://gist.github.com/848444)
### NPN and SNI
NPN (Next Protocol Negotitation) and SNI (Server Name Indication) are TLS
handshake extensions allowing you:
* NPN - to use one TLS server for multiple protocols (HTTP, SPDY)
* SNI - to use one TLS server for multiple hostnames with different SSL
certificates.
### pair = tls.createSecurePair([credentials], [isServer], [requestCert], [rejectUnauthorized])
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`: A credentials object from 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](#tls.CleartextStream) and `encrypted` stream properties.
#### Event: '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.
#### Event: 'secureConnection'
`function (cleartextStream) {}`
This event is emitted after a new connection has been successfully
handshaked. The argument is a instance of
[CleartextStream](#tls.CleartextStream). It has all the common stream methods
and events.
`cleartextStream.authorized` is a boolean value which indicates if the
14 years ago
client has verified by one of the supplied certificate authorities for the
server. If `cleartextStream.authorized` is false, then
`cleartextStream.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.
`cleartextStream.npnProtocol` is a string containing selected NPN protocol.
`cleartextStream.servername` is a string containing servername requested with
SNI.
#### 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.
See `net.Server` for more information.
#### 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.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
The number of concurrent connections on the server.
### tls.CleartextStream
This is a stream on top of the *Encrypted* stream that makes it possible to
read/write an encrypted data as a cleartext data.
This instance implements a duplex [Stream](streams.html#streams) interfaces.
It has all the common stream methods and events.
#### Event: 'secureConnect'
`function () {}`
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 `cleartextStream.authorized`
to see if the server certificate was signed by one of the specified CAs.
If `cleartextStream.authorized === false` then the error can be found in
`cleartextStream.authorizationError`. Also if NPN was used - you can check
`cleartextStream.npnProtocol` for negotiated protocol.
#### cleartextStream.authorized
A boolean that is `true` if the peer certificate was signed by one of the
specified CAs, otherwise `false`
#### cleartextStream.authorizationError
The reason why the peer's certificate has not been verified. This property
becomes available only when `cleartextStream.authorized === false`.
#### cleartextStream.getPeerCertificate()
Returns an object representing the peer's certicicate. The returned object has
some properties corresponding to the field of the certificate.
Example:
{ 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' }
If the peer does not provide a certificate, it returns `null` or an empty
object.