I was recently faced with a bit of a coding challenge whereby I needed to get LDAP authentication working via SSL/TLS using Node. Unfortunately for me Node.js is a relatively new language and a secure LDAP library is still on the wish list. When I was first given this task, I actually didn’t know where to start. I looked into creating a Node wrapper for some of the OpenLDAP libraries written in C. My project team was already using node-ldapauth, which utilizes OpenLDAP behind the scenes, so extending that was a possibility. I felt though that there must be an easier alternative, especially given how powerful node is with I/O. So I decided to implement a kind of TLS/SSL tunnel/port forward solution and use it in conjunction with node-ldapauth. Node v0.4.7 already has a built-in TLS connection library, so it was just a matter of constructing a ‘tunnel’ with a non-secure socket on one end, and a secure socket on the other.

Before trying anything too fancy, I thought I would prove the concept worked with a basic test. To do this I created three small apps:

  • A Server (Only accepts secure connections)
  • The Tunnel
  • A Client (Only makes non secure connections)

In order to make this a true SSL connection, I first needed to generate a certificate and a private server key. Thankfully OpenSSL makes this task a breeze:

openssl genrsa -out server.key 1024
openssl req -new -key server.key -out csr.pem
openssl x509 -req -in csr.pem -signkey server.key -out cert.pem

Here is the code for each of the apps:


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

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

sys.puts("TLS server started.");

tls.createServer(options, function (socket) {
    sys.puts("TLS connection established");
    socket.addListener("data", function (data) {
         sys.puts("Data received: " + data);



var tls = require('tls'), fs = require('fs'), sys = require('sys'), net = require('net');

var options = {
    cert: fs.readFileSync('cert.pem'),
    ca: fs.readFileSync('cert.pem')

sys.puts("Tunnel started.");
var client = this;

// try to connect to the server
client.socket = tls.connect(8000, options, function() {
    if (client.socket.authorized) {
        sys.puts("Auth success, connected to TLS server");
    } else {
        //Something may be wrong with your certificates
        sys.puts("Failed to auth TLS connection: ");

client.socket.addListener("data", function (data) {
    sys.puts("Data received from server: " + data);

var server = net.createServer(function (socket) {
    socket.addListener("connect", function () {
        sys.puts("Connection from " + socket.remoteAddress);
        //sync the file descriptors, so that the socket data structures are the same
        client.socket.fd = socket.fd;
        //pipe the incoming data from the client directly onto the server
        //and the response from the server back to the client

    socket.addListener("data", function (data) {
        sys.puts("Data received from client: " + data);

    socket.addListener("close", function () {
        //close the tunnel when the client finishes the connection.



var net = require('net'), sys = require('sys');

var msg = "Hello from net client!";

client = net.createConnection(7000, function() {
    sys.puts("Sending data: " + msg);

client.addListener("data", function (data) {
    sys.puts("Received: " + data);

Make sure the certificate and key files are in the same directory as the server/tunnel/client and then start them up in different terminals in the following order:

  1. node server.js
  2. node tunnel.js
  3. node client.js

If all goes well you should see the text: “Hello from client!” across all terminals.

To get this working with our existing LDAP library, I wrapped the tunnel code in a method ‘connect’ with a callback function, which then invokes the LDAP authenticate code:

tunnel.connect(ldap_port, ldap_host, ssloptions, function() {
    ldap.authenticate(tunnel.port, etc...)

The LDAP authenticate call is configured to point to the tunnel, and the tunnel points to the actual LDAP server on the TLS port (636).

I love how easy this task was made, simply by using Node. It’s a powerful language and I look forward to using it in the future.


    1. That’s a moot point. There’s a reason why people use the term “ECMAScript” instead of JavaScript all the time. JavaScript written for the browser isn’t necessarily compatible for Node.js, or for vanilla V8 for that matter.

      Hence why Node.js is considered a different programming language by many, simply because it adds to the standard ECMAScript features. It doesn’t add much, other than a few objects not defined in the ECMAScript specification, such as the “require” function, or the “process” object, to name a few.

      And the debate will go on about whether or not those added objects really add much to the ECMAScript standard. Or is it merely a set of libraries injected by the V8 runtime that supposedly is so compatible with the ECMAScript language. Can we turn those off, or are the integral to Node.js? Again, it’s up for debate.

      Not that I’m disagreeing with you. I’m just trying to point out why many call Node.js a language.

  1. If you want to keep your files more secure and don’t want it to be get haeckd by anyone or to have more control than the host then you should move on to a dedicated server.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s