Skip to content
This repository has been archived by the owner on Jun 4, 2021. It is now read-only.

Commit

Permalink
Update documentation, CHANGELOG and example
Browse files Browse the repository at this point in the history
  • Loading branch information
mildsunrise committed Jun 2, 2019
1 parent c8389b6 commit 545a989
Show file tree
Hide file tree
Showing 3 changed files with 173 additions and 31 deletions.
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
# Changelog
All notable changes will be documented in this file.

## next

- use SSLKEYLOGFILE env var as default
- replace `update_log`/`get_session_key` with new `hook*` API
- TLSv1.3 support + implement polyfill for keylog API introduced in Node 12.3
- add compatibility with Node 10.0-10.7 and 12+
- native module no longer built for Node 12.3+
- some refactoring and changes to the build process and C++
- minor API improvements, rename to camel case

## [0.1.1] - 2018-11-23

- testing npm release with Travis-CI
184 changes: 158 additions & 26 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,130 @@

[![NPM](https://nodei.co/npm/sslkeylog.png)](https://nodei.co/npm/sslkeylog/)

**sslkeylog** is a Node.js module for generating SSLKEYLOG, which can be used later by Wireshark to decrypt SSL connections. This method works with any TLS cipher suite including elliptic curves crypto.
**sslkeylog** is a module for easy generation of SSLKEYLOG files, which can be used later by Wireshark to decrypt SSL connections. This method works with any TLS cipher suite including elliptic curves crypto, and works regardless of the TLS version.

**sslkeylog** also allows one to use the [keylog API](https://nodejs.org/docs/latest/api/tls.html#tls_event_keylog_1) introduced in Node.JS 12.3.0, in earlier versions of Node (up to v10). See [use as a polyfill](#use-as-a-polyfill).

Further reading about SSLKEYLOG:

* [SSL/TLS Decryption: uncovering secrets](https://sharkfesteurope.wireshark.org/assets/presentations17eu/15.pdf) (PDF, SharkFest'17)
* [Decrypting TLS browser traffic with Wireshark: the easy way](https://jimshaver.net/2015/02/11/decrypting-tls-browser-traffic-with-wireshark-the-easy-way/)

### Installation
[Node.js](https://nodejs.org/) v10+ is **required**. Tested on v10 (LTS) and v11 (CURRENT), OS X and Linux.


## Usage

### Getting started

Install the module:

~~~ bash
npm install -g sslkeylog
~~~

Set the `SSLKEYLOGFILE` environment variable as usual:

~~~ bash
export SSLKEYLOGFILE=/tmp/keys.log
~~~

Then in your code, call the `hookAll` function at startup:

~~~ js
require('sslkeylog').hookAll();
~~~

That's it! Run your code and decryption keys will be logged to the specified file.

### Setting log file

If you don't want to use `SSLKEYLOGFILE` or want to override it, you can use `setLog`:

~~~ js
sslkeylog.setLog('/tmp/otherkeys.log').hookAll();
~~~

### Logging specific connections

`hookAll` will log decryption keys for *every TLS connection initiated or received by the Node.JS process*. This is okay for quick debugging, but is bad practice and may fail (because it patches Node.JS internals) or may be inconvenient if you have lots of connections.

Instead of calling `hookAll`, you may use (a combination of) other functions to log only certain connections:

#### Incoming connections to a server

To log all incoming connections to a `tls.Server` (or derivates such as `https.Server`
or `http2.Server`), use `hookServer`:

~~~ js
const myServer = https.createServer(...);

// ...

myServer.listen(...);
sslkeylog.hookServer(myServer);
~~~

#### HTTPS requests

To log outgoing connections for HTTPS requests made by your code, use `hookAgent`:

~~~ js
sslkeylog.hookAgent();
~~~

This will only work for requests that use the default agent. If the requests you're interested in specify a custom `agent`, you must hook this agent instead:

~~~ js
const myAgent = new Agent(...);
sslkeylog.hookAgent(myAgent);

// ...

https.request({ ..., agent: myAgent, ... })

// ...
~~~

#### Specific connections

For more advanced use cases where you want to log a particular connection,
you can pass the created `TLSSocket` to `hookSocket`. For example, with `tls.connect`:

~~~ js
const mySocket = tls.connect(...);
sslkeylog.hookSocket(mySocket);

// ...
~~~

[Node.js](https://nodejs.org/) v10+ is required. Tested on v10 (LTS) and v11 (CURRENT), OS X and Linux.
With `http2.connect`:

~~~ js
const http2Session = http2.connect(...);
sslkeylog.hookSocket(http2Session.socket);

// ...
~~~

Note that you **must** call `hookSocket` as soon as the `TLSSocket` is created (in
the same loop tick), otherwise keys may not be logged properly.

### Use as a polyfill

For more advanced use cases, you can use the [keylog API](https://nodejs.org/docs/latest/api/tls.html#tls_event_keylog_1) directly:

- If you are using Node.JS 12.3.0 or earlier, you don't need this module at all.
- If you are using an earlier version of Node.JS, just doing `require('sslkeylog')` will activate the polyfill. Then you can use the API as usual.


## Installation

If you are using Node 12.2.x or earlier, make sure usual compiling tools (`make`, `g++`, etc.) are installed; on Ubuntu / Debian, `sudo apt-get install build-essentials` should suffice.

To use in your project, install as usual:

```$ npm install sslkeylog```
```$ npm install --save-dev sslkeylog```

...or add to `package.json` and use npm/yarn to do the work.

Expand All @@ -31,28 +141,6 @@ $ npm install
$ cd examples
```

### Usage

When you have connected `TLSSocket`, you may call `get_sesion_key()` to get session key for this connection:

```javascript
let server = https.createServer({key, cert});
server.on('secureConnection', tls_socket=>{
const {client_random, master_key} = sslkeylog.get_session_key(tls_socket);
const hex1 = client_random.toString('hex');
const hex2 = master_key.toString('hex');
fs.appendFileSync('/tmp/sslkeylog.txt', `CLIENT_RANDOM ${hex1} ${hex2}\n`);
};
```
Or just use `set_log()` and `update_log()` to do exactly the same:
```javascript
sslkeylog.set_log('sslkeylog.txt');
server = https.createServer({key, cert});
server.on('secureConnection', sslkeylog.update_log);
```
### Demo

Clone the repository, build with `npm install` and go to `examples/` subdir. Open few terminal tabs or tmux/screen windows.
Expand All @@ -70,6 +158,50 @@ Now you can see decrypted packets:

![wireshark screenshot](https://cdn.jsdelivr.net/gh/kolontsov/node-sslkeylog/wireshark.png)


## API reference

### setLog(filename)

- `filename` (String): Set filename at which (future) decryption keys will be logged.

Sets the log filename.
Returns the module object.

### hookSocket(socket)

- `socket` (`tls.TLSSocket`): Socket to log decryption keys for.

Log keys for a particular socket. This method must be called after creating
the socket (i.e. at the same event loop tick) to guarantee that all keys are
logged. Logging the same socket multiple times has no effect.

Returns the passed socket.

### hookServer(server)

- `server` (`tls.Server`): Server to log decryption keys for.

Log keys for all (future) incoming connections to the passed server.
Returns the passed server.

### hookAgent(agent)

- `agent` (`https.Agent | undefined`): Agent to log decryption keys for.

Log keys for all (future) outgoing connections created by the passed agent.
If no agent is passed, `https.globalAgent` will be used.
Returns the patched agent.

### hookAll()

Log every TLS socket that is created. This relies on patching `TLSSocket#_init`,
so it may break and is not guaranteed to remain compatible with future Node.JS releases.
Calling this method multiple times has no effect.


## Project status

### TODO

- windows support?
Expand Down
10 changes: 5 additions & 5 deletions examples/server.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const https = require('https');
const fs = require('fs');
const sslkeylog = require('../index.js');
const sslkeylog = require('..');
const port = 8000;
const test_dir = `${__dirname}/../test`;
const ssl_opt = {
Expand All @@ -14,8 +14,8 @@ const req_handler = (req, res)=>{
res.end('Hello from SSL server\n');
};

sslkeylog.set_log('sslkeylog.txt');
sslkeylog.setLog('sslkeylog.txt');

https.createServer(ssl_opt, req_handler)
.on('secureConnection', sock=>sslkeylog.update_log(sock))
.listen(port, ()=>console.log(`Started on port ${port}`));
const server = https.createServer(ssl_opt, req_handler);
sslkeylog.hookServer(server);
server.listen(port, ()=>console.log(`Started on port ${port}`));

0 comments on commit 545a989

Please sign in to comment.