Dynamic DNS IP updating with node.js

By Matt | Filed in Home Server

My situation isn’t an unusual one – I’ve got a server at home that I want to expose to the internet, but my ISP provides me with a dynamic IP address that changes every time my router reconnects. This doesn’t happen often (maybe once a month or so), but if it does change I still want to be able to access my machine remotely.

The usual course of action is to use a free service such as DynDNS – you choose a subdomain on one of the many domain names they have, and using any one of a number of software tools, you ping them whenever your IP changes. This works pretty well – in fact, my router (like many) has built-in support for DynDNS so the router itself will notify DynDNS when the IP address changes.

So why am I doing something different? Well, I’ve actually been using DynDNS for a few years, and there are a couple of downsides (all of these apply to their free service, and I’m sure you can remove these limitations by paying, but I’m too tight to do that):

  1. You have to use one of their subdomains, and then CNAME your DNS to it – actually there’s not much wrong with this, but I’d rather not have their subdomain in my DNS resolution track;
  2. You can’t ping them too frequently or they get sad (and cut you off), so you need to be sure you can tell when your IP has changed;
  3. If you don’t ping them often enough, you risk your account being suspended until you manually log in and reactivating it – this happened to me recently when my IP hadn’t changed for a few months.

But actually, none of the things I’ve just listed are persuasive enough to not use it. So again, why am I doing something different?

  1. I want my server, not my router, to be in charge of updating the DNS – no concrete reason for this, other than that I feel it’s logic that ought to be on my server where I can track/monitor/etc it more easily;
  2. I run my own DNS service on my VPS anyway, so I want to have control over all of it, not just all except the dynamic IP bit;
  3. Because I can.

And that’s pretty much the main reason – simply because I can. I just fancy having a go at it myself. Oh, and it’s another excuse to use node.js.

So, let’s set the scene:

  • Both my home server and VPS run node.js and nginx;
  • My VPS is using named/bind9 for DNS;
  • I want my home server to use a subdomain of the VPS domain, but with its own zone file so it can have “sub-subdomains” (e.g. *.home.matt-knight.co.uk).

There are loads of ways to do this, but I’ve been meaning to have a play around with is SSL client certificates, so I’m going to use them for this. I’ve looked at using SSL client certification for API authentication in the past, but never got round it it. Basically, when a client makes an HTTPS request, it provides a certificate and key to identify (authenticate and authorize) itself.

The plan is as follows:

  1. Create an SSL CA certificate, a server certificate and a client key;
  2. Set up a new SSL host in nginx on the VPS using the aforementioned SSL certificate;
  3. Enable (and enforce) client SSL certificate authentication in nginx;
  4. Expose a node.js app on the VPS running an HTTP server which will update the bind zone file and reload it;
  5. Write a node.js app to run on my home server and ping the VPS SSL endpoint at regular intervals – for example, once a minute.

As I say, there are probably certainly easier ways to do this (well, ultimately just use DynDNS!) but this should be fun! We’ll start with the SSL certificates.

SSL Certificates & Keys

A quick search on Google found Nathan Good’s web page: Client Side Certificate Auth in Nginx

Combining that with the nginx documentation on the HTTP SSL module, I created my certificates and removed the passphrase (this is important, otherwise you’ll have to enter the passphrase every time nginx is started). The code snippets below are copied from Nathan’s site, but also include extra steps to remove the passphrases – I also changed the signing to last for 10 years (3650 days) not 1 year (365 days) because it’s fine in this case.

Note, when you’re creating the server certificate, you should set the Common Name (CN) to the SSL host you’re going to use in nginx (e.g. dnsping.example.com). When you’re creating the client certificate, you should set the Common Name (CN) to the hostname you want to set an IP for (e.g. home.matt-knight.co.uk in my case) – you’ll see why later on.

# Create the CA Key and Certificate for signing Client Certs
openssl genrsa -des3 -out ca.key 4096
openssl req -new -x509 -days 365 -key ca.key -out ca.crt

# Remove the passphrase from the CA key
cp ca.key ca.key.org
openssl rsa -in ca.key.org -out ca.key
unlink ca.key.org

# Create the Server Key, CSR, and Certificate
openssl genrsa -des3 -out server.key 1024
openssl req -new -key server.key -out server.csr

# Remove the passphrase from the server key
cp server.key server.key.org
openssl rsa -in server.key.org -out server.key
unlink server.key.org

# Self-sign the server certificate
openssl x509 -req -days 3650 -in server.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out server.crt

# Create the Client Key and CSR
openssl genrsa -des3 -out client.key 1024
openssl req -new -key client.key -out client.csr

# Remove the passphrase from the client key
cp client.key client.key.org
openssl rsa -in client.key.org -out client.key
unlink client.key.org

# Sign the client certificate with our CA cert.  Unlike signing our own server cert, this is what we want to do.
openssl x509 -req -days 365 -in client.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out client.crt

Now we’ve got our certificates and keys. The client certificate/key need to be on my home server, and the server certificate/key and CA certificate need to be on my VPS. Obviously all of the keys need to be kept safe. Next, it’s time to set up nginx.

Configuring nginx

All we really need to do here is to create a new SSL host.

upstream dnsping {
    server unix:/tmp/dnsping.socket; # our node.js app will listen on this socket - /tmp/dnsping.socket is just an example
}

server {
    listen 443 ssl;

    server_name dnsping.example.com; # change this to your real hostname

    access_log /var/log/nginx/access.log; # change this to wherever you want to store access logs
    error_log /var/log/nginx/error.log;   # change this to wherever you want to store error logs

    ssl_certificate        /etc/nginx/ssl/server.crt;
    ssl_certificate_key    /etc/nginx/ssl/server.key;
    ssl_client_certificate /etc/nginx/ssl/ca.crt;
    ssl_verify_client      on; 

    location / {
        include proxy_params;

        proxy_pass http://dnsping/; # this references the upstream defined above

        proxy_set_header X-Verified $ssl_client_verify;
        proxy_set_header X-DN $ssl_client_s_dn;
    }
}

You can run nginx -t to make sure it is all valid, and then tell nginx to reload the config:

kill -HUP `cat /var/run/nginx.pid`

So, what is nginx going to do?

  1. It will listen for requests to https://dnsping.example.com;
  2. It will check for the presence of a valid SSL client certificate and reject the request if not found;
  3. It will set a header of X-Verified: SUCCESS if all is good;
  4. It will set the SSL Distinguished Name (DN) into a X-DN header;
  5. It will then forward the request to a UNIX socket at /tmp/dnsping.socket

That wasn’t too hard was it! Now onto the node.js app that will run on the VPS and listen to /tmp/dnsping.socket.

Next time….

Be the first to comment
Tags: , , ,
del.icio.us this! Digg this! Share on Facebook! Share on LinkedIn! Stumble Upon this! Tweet this! Share on Reddit! RSS 2.0 TOP

Graphite, nginx and supervisord

By Matt | Filed in Home Server

In case you haven’t met it before, Graphite is a really nice real-time graphing tool. It’s simple to add data into it, and it has a nice web-interface for viewing the graphs. Think Cacti, but 10x easier to use and prettier. Graphite uses a custom data store called Whisper (rather than RRDTool which Cacti is based on) which makes it really easy to just push data into it whenever you want. Installation it is also fairly easy – just follow the (recently much improved) documentation on the Graphite site.

It comes with a development server that you can use to play around with the web interface, although it is stressed in the documentation that it is only a development server, and you really should be using Apache and mod_python. And that’s a bit annoying, because I wanted to use nginx for some other things on my system, so I don’t want Apache stealing port 80.

Read the remainder of this entry »

Be the first to comment
del.icio.us this! Digg this! Share on Facebook! Share on LinkedIn! Stumble Upon this! Tweet this! Share on Reddit! RSS 2.0 TOP

Eos is Born

By Matt | Filed in Home Server

Having been thinking about doing it for a number of years but never getting round to it, I’ve finally gone and bought myself a home server – an HP ProLiant Microserver. For £250 (and then £100 cashback from HP as well), the specification is pretty good:

  • Dual Core AMD Turion II Neo N40L @ 1.5 GHz
  • 2GB RAM
  • 250GB Seagate Barracuda HDD
  • 3 free 3.5″ S-ATA bays
  • 1 free 5.25″ optical bay

I’ve put 2 Samsung Spinpoint F3 1TB drives in it (just over £100 each), in a RAID 1 (mirrored) array. My plan was to put an DVD drive from an old machine into it, but it turns out that it doesn’t have an IDE connector for an optical drive – an oversight on my part there! I installed the 64-bit version of Ubuntu Server 11.10 from a USB drive and that was all I really planned to use the DVD drive for anyway.

I hadn’t really thought about a name for it, but my naming convention for boxes so far has been Roman or Greek deities. I fancied something quite grand for this one, since I hope it will become the computing-cornerstone in my house. I decided to call  it Eos, the Titan goddess of the dawn – seems quite fitting for a new server. So in the style of Mark Evans, Eos is born!

Read the remainder of this entry »

Be the first to comment
del.icio.us this! Digg this! Share on Facebook! Share on LinkedIn! Stumble Upon this! Tweet this! Share on Reddit! RSS 2.0 TOP

Optimising Zend_Config

By Matt | Filed in Technology

Zend Framework is a popular MVC framework written in PHP. There has been substantial development on it over the past couple of years, and it is now often used in enterprise environments to power websites belonging to large blue chip companies. However, as a site grows in terms of size, complexity and traffic, the limitations of Zend become increasingly apparent.

One such limitation that I’ve recently seen is the performance of Zend_Config. This class underpins the mechanism by which developers provide configuration to the application, and all this config is passed around in the form of Zend_Config objects. Read the remainder of this entry »

10 Comments so far. Join the Conversation
del.icio.us this! Digg this! Share on Facebook! Share on LinkedIn! Stumble Upon this! Tweet this! Share on Reddit! RSS 2.0 TOP

Recursive Closures in PHP

By Matt | Filed in Technology

Here’s a useful trick I came across a while back for using closures in PHP. For those people who aren’t aware of this, starting from PHP 5.3, it is possible to create an anonymous function and assign it to a variable – we call this a closure. Read the remainder of this entry »

Be the first to comment
del.icio.us this! Digg this! Share on Facebook! Share on LinkedIn! Stumble Upon this! Tweet this! Share on Reddit! RSS 2.0 TOP

Migrating from lighttpd to nginx

By Matt | Filed in Technology

This site currently runs from a relatively low-spec VPS running Ubuntu 10.04 LTS. With just 1GB memory, it is running several websites as well as various other servers – mail, database, VCS, etc.

I set it up over a year ago, and opted for lighttpd over Apache for reasons of performance – I didn’t need all the features that Apache offers on this server. Being a little short on memory, a single-process web server with a small memory and CPU footprint was an attractive option.

Read the remainder of this entry »

2 Comments so far. Join the Conversation
del.icio.us this! Digg this! Share on Facebook! Share on LinkedIn! Stumble Upon this! Tweet this! Share on Reddit! RSS 2.0 TOP

In the last article, we saw that when it comes to maths, node.js was nearly 50x faster than PHP. This time, we’re going to look at JSON – a data format at the core of several modern technologies such as node.js and MongoDB.

You might expect node.js to be incredibly efficient at JSON encoding/decoding, whereas PHP has only had native JSON support since version 5.2.0. In this article, we’ll just look at decoding JSON.

Read the remainder of this entry »

Be the first to comment
del.icio.us this! Digg this! Share on Facebook! Share on LinkedIn! Stumble Upon this! Tweet this! Share on Reddit! RSS 2.0 TOP

Node.js vs PHP Performance – Maths

By Matt | Filed in Technology

Node.js has a reputation of being a very efficient framework, and most of the discussions around this focus on its event-driven nature, rather than the engine itself. I think it’s pretty obvious to most that when written properly, an event-driven application can be more efficient.

However, what’s not so often discussed is how the JavaScript powering node.js (and specifically the V8 engine under the bonnet) compares to other languages on simple, like-for-like tasks. With this in mind, I’m going to benchmark node.js against PHP with some very simple tasks. Read the remainder of this entry »

2 Comments so far. Join the Conversation
del.icio.us this! Digg this! Share on Facebook! Share on LinkedIn! Stumble Upon this! Tweet this! Share on Reddit! RSS 2.0 TOP

Concurrent PHP Sessions

By Matt | Filed in Technology

Sessions in PHP are handled by the $_SESSION superglobal and several session_*() functions. One thing you may not realise about PHP sessions though, is that natively they are blocking to make them thread-safe. What this means is that once a PHP session is started, nothing else can work with that session until it is closed. That sounds sensible, as it maintains the integrity of the session, however it does cause some problems – particularly with those dynamic, AJAX requests your fancy new site has on, since they can’t happen in parallel.

Read the remainder of this entry »

Be the first to comment
del.icio.us this! Digg this! Share on Facebook! Share on LinkedIn! Stumble Upon this! Tweet this! Share on Reddit! RSS 2.0 TOP

So far, in my investigation of node.js and Service-Oriented Architecture, I have shown that node.js can be successfully used to consume messages from a queue as part of a wider service.

However, one of the potential limitations of node.js is that it is entirely single-threaded. So is my title a little misleading when it talks about multi-threaded node.js consumers? Not really, because as explained on the node.js home page, we can fork new processes:

But what about multiple-processor concurrency? Aren’t threads necessary to scale programs to multi-core computers? Processes are necessary to scale to multi-core computers, not memory-sharing threads. The fundamentals of scalable systems are fast networking and non-blocking design—the rest is message passing. In future versions, Node will be able to fork new processes (using the Web Workers API ) which fits well into the current design.

Note the phrase “the rest is message passing” – it’s no coincidence that we’re looking at scaling in relation to message queues. Read the remainder of this entry »

1 Comment. Join the Conversation
del.icio.us this! Digg this! Share on Facebook! Share on LinkedIn! Stumble Upon this! Tweet this! Share on Reddit! RSS 2.0 TOP