/node-dtls

JavaScript DTLS implementation for Node.js

Primary LanguageJavaScriptISC LicenseISC

node-dtls

DTLS implementation in JavaScript (Work in progress)

Travis build Test Coverage Code Climate

No Maintenance Intended

This repository contains an unfinished DTLS implementation written in JavaScript. The implementation was an attempt to give Node.js DTLS support while waiting for nodejs/node#2398 to get resolved.

DTLS handshake and packet communication has been implemented. The largest missing things are re-negotiation, other cipher suites, respecting configuration options and handling the DTLS alerts.

The primary goal of the project was to "support" DTLS in the sense that Node.js could communicate with services that require DTLS. The code should not be relied on for any actual security.

Datagram Transport Layer Security (DTLS) Protocol implementation for Node.js written in JavaScript.

While Node.js still lacks support for DTLS protocol, this library attempts to fix the issue. This is in no way a security implementation as it's main goal is to allow using protocols that require DTLS. While the library implements the proper DTLS encryption and validation, there has been no effort to protect it against well known TLS attacks.

Example

Server
var dtls = require( 'dtls' );
var fs = require( 'fs' );

var pem = fs.readFileSync( 'server.pem' );

var server = dtls.createServer({ type: 'udp4', key: pem, cert: pem });
server.bind( 4433 );

server.on( 'secureConnection', function( socket ) {

  console.log( 'New connection from ' +
    [ socket.rinfo.address, socket.rinfo.port ].join(':') );

  socket.on( 'message', function( message ) {
    
    // Echo the message back
    socket.send( message );
  });
});
Client
var dtls = require( '../' );

dtls.setLogLevel( dtls.logLevel.FINE );

var client = dtls.connect( 4433, 'example.org', 'udp4', function() {
    client.send( new Buffer( 'foo\n' ) );
});

client.on( 'message', function( msg ) {
    console.log( msg );
});

Current state

  • DTLS 1.2 handshake in server role
  • DTLS 1.2 handshake in client role
    • Still some problems when it comes to receiving messages. Not very confident.
  • Handle application data
  • Proper API to handle sessions/messages outside the node-dtls internals.
  • DTLS 1.0 handshake in server role
    • There shouldn't be too many changes. Main one is propably the PRF hash.
  • Handle renegotiation
  • Robustness
    • Handshake reassembly/buffering/reordering
    • Retransmission
    • Handle alert-messages
    • Validate handshake state and expected messages

API

dtls.setLogLevel( level )

  • level - logg log level. For convenience possible log levels are also available in dtls.logLevel.*

Sets the global node-dtls logging level.

node-dtls uses /logg/ for logging and tracing various dtls events. This function can be used to alter the amount of information that is logged during the DTLS handshake/session. In future logging will most likely be disabled by default, but for now the default log level (FINE) is quite verbose.


dtls.createServer(options[, callback])

  • options - Server options, see below.
  • callback - Optional callback registered to the secureConnect event.

Creates a dtls.DtlsServer.

Mimics the Node.js tls.createServer function. Although given DTLS is a datagram protocol, the actual network object is created with dgram.createSocket().

options object is a rough combination of the option objects of tls.createServer() and dgram.createSocket(). DTLS-specific options are parsed by the dtls.DtlsServer and the dgram-options are passed directly to dgram.createSocket().

  • type - Required. dgram socket type. Passed to dgram.createSocket().
  • key - Required. The server private key in PEM format.
  • cert - Required. The server certificate in PEM format.
Example
var dtls = require( 'dtls' );
var fs = require( 'fs' );
    
var pem = fs.readFileSync( 'server.pem' );
    
var server = dtls.createServer({ type: 'udp4', cert: pem, key: pem });
server.bind( 4433 );
    
server.on( 'secureConnection', function( socket ) {
  console.log( 'New secure connection: ' +
    [ socket.rinfo.address, socket.rinfo.port ].join( ':' ) );
});

The server.pem certificate can be created with

openssl req -x509 -nodes -newkey rsa:2048 -keyout server.pem -out server.pem

dtls.connect( port, address, type, callback )

  • port - Remote port to connect to.
  • address - Remote address to connect to.
  • type - Datagram socket type: udp4 or udp6. Ssee dgram for full explanation.
  • callback - Callback for when the handshake is ready.

Initiates a connection to a remote server and returns the dtls.DtlsSocket.

Example
var dtls = require( 'dtls' );

var client = dtls.connect( 4433, 'example.org', 'udp4', function() {
    client.send( new Buffer( 'foo\n' ) );
});

client.on( 'message', function( msg ) {
    console.log( msg );
});

Class: dtls.DtlsServer

Server accepting DTLS connections. Created with dtls.createServer


Event: 'secureConnection'

  • socket - dtls.DtlsSocket

Emitted after the DtlsSocket has finished handshaking a connection and is ready for use.


server.bind();

  • port - UDP port to listen to. This is passed over to socket.bind() of the underlying dgram.Socket

Starts listening to the defined port. Delegated to dgram.Socket#bind()



Class: dtls.DtlsSocket

A single DTLS session between a local and remote endpoints. Acquired through the server::secureConnection event.


Event: 'secureConnect'

Emitted after the DtlsSocket has finished handshaking a connection.

This method is emitted after the server sends the Finished handshake message. As datagram protocols aren't reliable transports, the handshake might still be in progress if that last handshake message was lost. It is recommended that the client initiates the actual application communication as the client gets confirmation on when the handshake has been completed.

Note: that usually it is impossible to catch this event as it is raised before the user has a reference to the socket. Use server::secureConnection event instead.


Event: 'message'

  • buffer - Application data within a Buffer.

Emitted when the socket has received and decrypted application data from the remote endpoint.

Example
var server = dtls.createServer({
    type: 'udp4',
    key: pem,
    cert: pem
});
server.bind( 4433 );

server.on( 'secureConnection', function( socket ) {
  socket.on( 'message', function( message ) {
    console.log( 'In: ' + message.toString( 'ascii' ) );
  });
});

socket.send( buffer[, offset][, length][, callback] )

  • buffer - Buffer object to send.
  • offset - Offset in the buffer where the message starts. Optional.
  • length - Number of bytes in the message. Optional.
  • calback - called when the message has been sent. Optional.

Sends application data to the remote endpoint.

Example
var server = dtls.createServer({
    type: 'udp4',
    key: pem,
    cert: pem
});
server.bind( 4433 );

server.on( 'secureConnection', function( socket ) {
  socket.send( new Buffer( 'Hello!\n', 'ascii' ) );
});

References

[Datagram Transport Layer Security Version 1.2, RFC 6347] (https://tools.ietf.org/html/rfc6347)

[The Transport Layer Security (TLS) Protocol Version 1.2, RFC 5246] (https://tools.ietf.org/html/rfc5246)