Tag Archives: IPv6

Code.DanYork.Com Now Back Available Over IPv6

worldIPv6launch-256pxAfter a Reddit thread started up that briefly referenced a 2011 post I wrote about adding IPv6 to Node.js apps, I was contacted by a Redditor who was surprised that my site wasn’t available over IPv6!

HUH???

I was surprised, too, because this site is hosted on a dual-stack server at Hurricane Electric and has been accessible over IPv6 since June 7, 2011, right before the World IPv6 Day event.

But in checking into it… there was no AAAA record in DNS for “code.danyork.com” that would point to the server, so the report was indeed accurate. For regular users this site was not available over IPv6.

It turned out to be one of those system administration issues that can bite you.  A month or two ago, TypePad, the provider I still use for my personal DanYork.com site, experienced a severe DDoS attack that took many sites offline.  They recovered but in doing so changed the way that sites were referenced a bit.  I had to switch to using a CNAME instead of an IP address as I had been doing.  The problem there is that due to the “no CNAME at zone apex” rule of DNS, I could no longer use just “http://danyork.com” – I would have to switch to using “http://www.danyork.com/”.

The episode highlighted to me, though, the need to be sure I have “Test over IPv6” in my list of things to check after making any major changes to any of my sites!

I didn’t want to switch and so I moved the DNS for “danyork.com” over to CloudFlare to make use of their “CNAME Flattening” so that I could still use “danyork.com”.

However, in moving the DNS info from my previous DNS hosting provider to CloudFlare, I messed up.  I didn’t bring across the AAAA record for code.danyork.com.  Also, very bizarrely, I didn’t have the “Automatic IPv6” setting enabled for danyork.com – even though it is now supposed to be on by default for all new domains.

So the fix was simple – I added the AAAA record for code.danyork.com, and I also flipped the switch on the Automatic IPv6 gateway.  Now both code.danyork.com and danyork.com are fully available over IPv6.

Code.DanYork.com Now Available Over IPv6 as of World IPv6 Day

Ipv6day 1Just in time for World IPv6 Day, I’m pleased to note that Code.DanYork.com is now available over IPv6!

This site runs on WordPress and while WordPress itself works fine with IPv6, the trick was to find a web hosting provider that provided solid IPv6 connectivity.

After much investigation, I finally set up a basic web hosting account with Hurricane Electric. They’ve been in a leader in IPv6 deployment and have great interconnections to other IPv6 networks. They are also the folks behind Tunnelbroker.net, the free service I use to get IPv6 connectivity into my home office (using a setup for IPv6 with an Apple TimeCapsule that I described in another blog post).

I had this site hosted at another webhost, but through the sheer beauty of WordPress’s export and import features I was able to move the entire contents of the site over to Hurricane Electric without any problem.

For those curious, I’m running the site in WordPress’ Multisite mode as I’m planning to move more of my sites over to HE’s hosting. I’m using the Domain Mapping plugin to let me map different domains to different blogs. It’s all working wonderfully.

Now, unlike Google and Facebook, I’m not removing the IPv6 connectivity for this site after the 24 hours of World IPv6 Day are up. This site is live with IPv6 and will stay set up with IPv6 for the foreseeable future. (But having said that, I have nowhere even remotely near the visitors of the larger sites… and I have the luxury of not having to deal with large numbers of people who may have challenges connecting to my site.)

Welcome to the new IPv6 Internet!

P.S. If you want to learn more about IPv6, and in particular IPv6 and VoIP/SIP, you can visit the IPv6 Resource Page I put together over on Voxeo’s site. I’ve got some HOWTOs, tutorials, videos, links and more…


As an aside, over on the right navigation bar you’ll see a little “IPv6 detector” box that will show you either your IPv6 address or your IPv4 address (and yes, I blacked my actual address out in the screenshot because I’m just naturally paranoid):


Ipv6detector

I’m using the “IPv6 detector” plugin for WordPress by Andres Altamirano, although I did alter it a bit. I shortened the text that was printed for an IPv6 address so that it would fit in my theme’s sidebar. I also removed the URL link and removed the extra links about IPv4 exhaustion.

Installation was a snap, though… I just installed it into WordPress and then went to the Widgets area of my theme and dragged it into the location where I wanted it.

How to use Node.js with IPv6

It turns out to be ridiculously simple. After my testing yesterday, I learned via a comment from Ryan Dahl, that:

all you do is have your Node.js app listen on the IPv6 address.

That’s it.

UPDATE 28 Jul 2014 – As a result of a Reddit thread I’ve seen traffic to this post.  Please do note that I wrote this post in early 2011 when I was experimenting with Node.js.  I’ve not kept up with the state of Node.js and so 3 years later there may be new or better ways to do what I’ve listed here.  Also, please see the comment from Simon Vetter indicating that you don’t need to start up two servers if you simply use “::” as the address. At some point I need to verify that and then update this post.

In a typical application using, say, the “http” module, you will have a line somewhere that says something like:

server.listen(80);

This will bind to your default network interface and address, which, for pretty much all of us, will be our IPv4 address.

To bind to an IPv6 address, you just need to supply the address as an argument to listen(). For example:

server.listen(80, "2001:db8:1111:2222:3333::51"]

So a very basic Node.js app using IPv6 would look like this:

var http = require('http');

var server = http.createServer(function (request, response) {
   response.writeHead(200, {"Content-Type":"text/plain"});
   response.end ("Hello World!n");
   console.log("Got a connection");
});

server.listen(80, "2001:db8:1111:2222:3333::51");

console.log("Server running on localhost at port 80");

Note that as a Node.js app like this will only bind to a single interface and address, this app only listens on the IPv6 address and not on the IPv4 address. To make the app work on both the IPv4 and IPv6 addresses, I need to refactor it a bit into a function that is then called by two different servers that attach to the two network interfaces:

var http = require('http');

var handler = function (request, response) {
   response.writeHead(200, {"Content-Type":"text/plain"});
   response.end ("Hello World!n");
   console.log("Got a connection");
};

var server6= http.createServer();
server6.addListener("request",handler);
server6.listen(80,"2001:db8:1111:2222:3333::51");

var server= http.createServer();
server.addListener("request",handler);
server.listen(80,"192.0.2.23");

console.log("Server running on localhost at port 80");

With that in place, it’s now answering on both the IPv4 and IPv6 addresses.

Now this is for the Node.js base modules… other modules may or may not “just work” for IPv6, too, depending upon what they rely on underneath. Regardless, it’s rather cool that it works so easily on IPv6. Kudos to the Node.js team for making it so simple!

Testing Node.js With IPv6 – First Step, Does It Work?

Given all the writing I’ve been doing lately about IPv6 and about Node.js, it was only natural for me to try combining them. I pay for a VPS over at RapidXen and upon request they will provide you with an IPv6 address block (for free). So I’ve been using it as a base for my IPv6 experiments.

I should note that my home network is set up with IPv6 via a IPv6-to-IPv4 tunnel from Tunnelbroker.net. I previously wrote up how I configured IPv6 this way using an Apple Time Capsule WiFi access point

Testing Apache First

After using IPv6-test.com to verify that I have HTTP connectivity over IPv6 from my system at home, I tested connectivity to my VPS running a stock CentOS 5.5 Apache server. Here was the IPv4 result (and yes, I cover up IP addresses… a certain degree of paranoia comes with the territory of being in the security space):

apachev4.jpg

Here was the same result with IPv6:

apacheipv6.jpg

(If you aren’t familiar with using IPv6 addresses in web browsers, you just enclose the IPv6 address in square brackets. The specific browser I’m using is Google Chrome on a Mac, but this should work in all browsers.)

Testing Node.js

The next step was to shut down Apache and start up Node.js. For this experiment, I’m purely using the HTTP module in Node.js and not getting into any of the frameworks. Here’s the very basic code I’m using (also on Github):

var http = require('http');

var server = http.createServer(function (request, response) {
   response.writeHead(200, {"Content-Type":"text/plain"});
   response.end ("Hello World!n");
   console.log("Got a connection");
});

server.listen(80);

console.log("Server running on localhost at port 80");

After firing it up, connecting to the site via IPv4 was no problem:

nodejsipv4.jpg

And this is shown in the console:

bash-3.2# node httpsample.js
Server running on localhost at port 80
Got a connection
Got a connection

Next I tried the IPv6 connection:

nodeipv6.jpg

Oops. Predictably, the console log also did not show a new connection. I duplicated the test to make sure there wasn’t anything else funky going on, but had the same issue. Node.js wasn’t accepting HTTP connections via IPv6.

UPDATE: See below for the answer…

Testing the ‘net’ module

I was curious to see if the issue might be with the “http” module or if it was a broader issue. So I fired up a really basic TCP server example:

var net = require("net");

var s = net.createServer( function(c) {
    c.addListener("connect", function () {
    console.log("Connection from " + c.remoteAddress);
    c.end("Hello Worldn");
});
});

s.listen(8000);

console.log("TCP server running on port 8000")

From my Mac, I then tried connecting via IPv4 and IPv6:

$ telnet 69.xxx.xxx.xxx 8000
Trying 69.xxx.xxx.xxx...
Connected to rapidxen.net.
Escape character is '^]'.
Hello World
Connection closed by foreign host.

$ telnet -6 2607:xxxx:xxxx:xxxx::2 8000
Trying 2607:xxxx:xxxx:xxxx::2...
telnet: connect to address 2607:xxxx:xxxx:xxxx::2: Connection refused
telnet: Unable to connect to remote host
$

and found that IPv6 connectivity wasn’t supported in the “net” module.

Just to verify my testing method, I restarted Apache on the VPS box and used the same “telnet -6” command to hit port 80 on the box. I was able to connect and issue HTTP commands without a problem.

In the end…

So it would seem that Node.js doesn’t work with IPv6, which is not terribly surprising given that (Node.js founder) Ryan Dahl indicated in the #node.js IRC chat yesterday that basically no IPv6 testing had been done. Looking in the Node.js ChangeLog, IPv6 support was added in some form back in June 2009:

2009.06.18, Version 0.0.5, 3a2b41de74b6c343b8464a68eff04c4bfd9aebea

Support for IPv6

But without looking at code diffs, it’s not clear to me what exactly was changed to support IPv6.

The next step is obviously to start digging around in code… given that I’m picturing it as a bigger task, I’m not sure when I’ll get the chance to do, but it would be a good excuse to take a look inside the Node.js code.

In the meantime, if anyone else reading this has some Node.js modules they’d like me to test with IPv6, or other ideas around this, I’m glad to help. Just drop me a note or hit me on Twitter.

THE ANSWER

UPDATE:The answer that I couldn’t find anywhere online came in a comment to this post from none other than Ryan Dahl… Node.js DOES work with IPv6, provided you give it the address!

All I had to do to make the original code work with IPv6 was add the IPv6 address to the “.listen(80)”, like this:

var http = require('http');

var server = http.createServer(function (request, response) {
   response.writeHead(200, {"Content-Type":"text/plain"});
   response.end ("Hello World!n");
   console.log("Got a connection");
});

server.listen(80, "2607:xxxx:xxxx:xxxx::2");

console.log("Server running on localhost at port 80");

But of course this only listens on the IPv6 address and not on the IPv4 address, so I needed to refactor the code a bit and run two servers:

var http = require('http');

var handler = function (request, response) {
   response.writeHead(200, {"Content-Type":"text/plain"});
   response.end ("Hello World!n");
   console.log("Got a connection");
};

var server6= http.createServer();
server6.addListener("request",handler);
server6.listen(80,"2607:xxxx:xxxx:xxxx::2");

var server= http.createServer();
server.addListener("request",handler);
server.listen(80,"69.xxx.xxx.xxx&");

console.log("Server running on localhost at port 80");

With that in place, it’s now answering on both the IPv4 and IPv6 addresses!

Many thanks, Ryan, for the answer!