Friday, June 1, 2012

IPv6 Hello World!

ipv6 world launch

After a little set up for surfing with IPv6 is time for a "IPv6 Hello World!". Ingredients: AWS EC2 instance, EC2 ELB and a Apache HTTP server.

First, deploy one EC2 instance. I always use the default Amazon Linux 64bits AMI. I'm used to RedHat and CentOS Linux and this AMI is basically the same. Then install your favourite web server flavour. This instance will have an IPv4 address and that's all we need. The magic for IPv6 is at the ELB public side. There's no way (and and no need now) to get an IPv6 attached to your instance.

Once that is done, deploy an ELB and attach the instance to it. Notice on the ELB "Description" tab that you have 3 DNS records for it.

aws elb dns a aaaa dualstack record


In may case:

domenech-1821931935.us-east-1.elb.amazonaws.com (A Record)
ipv6.domenech-1821931935.us-east-1.elb.amazonaws.com (AAAA Record)
dualstack.domenech-1821931935.us-east-1.elb.amazonaws.com (A or AAAA Record)

Let's give a detailed look to it. The first DNS record (A Record) is the typical IPv4 record where you usually point the CNAME to.

# host domenech-1821931935.us-east-1.elb.amazonaws.com
domenech-1821931935.us-east-1.elb.amazonaws.com has address 23.21.124.217
root@juan-ubuntu:~# host ipv6.domenech-1821931935.us-east-1.elb.amazonaws.com
ipv6.domenech-1821931935.us-east-1.elb.amazonaws.com has IPv6 address 2406:da00:ff00::1715:7cd9

So, if we resolve the A Record we get a IPv4 (23.21.124.217 in my example) and with the AAAA Record we get the IPv6 (2406:da00:ff00::1715:7cd9). They are there waiting for us to use them. No more configuration needed.

Searching this IP in this BGP AS database we get that it belongs to the Autonomous System AS16509 prefix 2406:da00::/32 from Amazon.com. In other words, part of the AWS IPv6 infrastructure. Those 32 bits prefix mean that are 96 bits of IP addresses available (IPv6=128bits) into that prefix and that is 79,228,162,510,000,000,000,000,000,000 IPs. Nice!

Another interesting thing is that the AAAA Record "implies" the A Record. An IPv6 is formed by 8 "hexquads" 16 bit long each one separated by colons and written in lower case hexadecimal. Double colon (::) means "full of zeros". In my example, the IPv6 2406:da00:ff00::1715:7cd9 translates to 2406:da00:ff00:0000:0000:0000:1715:7cd9. If we take the last 8 hexadecimal elements grouped by 2 and convert to decimal:
17 = 23
15 = 21
7c = 124
d9 = 217
And this is 23.22.124.217. The IPv4 address that this ELB also provides.

Now we have just to create our CNAME record for our domain pointing to the AWS ELB. We can either choose the AAAA Record or the "dualstack" (A and AAAA) Record. Basically the Dual Stack record answers a IPv4 IP if our DNS call asks for a A Record or a AAAA Record in that case.

Dig for A Record:
# dig ipv6.domenech.org A @2001:4860:4860::8888
; <<>> DiG 9.8.1-P1 <<>> ipv6.domenech.org A @2001:4860:4860::8888
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 56239
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;ipv6.domenech.org.        IN    A
;; ANSWER SECTION:
ipv6.domenech.org.    60    IN    CNAME    dualstack.domenech-1821931935.us-east-1.elb.amazonaws.com.
dualstack.domenech-1821931935.us-east-1.elb.amazonaws.com. 60 IN A 23.21.124.217
;; Query time: 216 msec
;; SERVER: 2001:4860:4860::8888#53(2001:4860:4860::8888)
;; WHEN: Tue Jun  5 11:58:20 2012
;; MSG SIZE  rcvd: 122

Dig for AAAA Record:
# dig ipv6.domenech.org AAAA @2001:4860:4860::8888
; <<>> DiG 9.8.1-P1 <<>> ipv6.domenech.org AAAA @2001:4860:4860::8888
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 56671
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;ipv6.domenech.org.        IN    AAAA
;; ANSWER SECTION:
ipv6.domenech.org.    57    IN    CNAME    dualstack.domenech-1821931935.us-east-1.elb.amazonaws.com.
dualstack.domenech-1821931935.us-east-1.elb.amazonaws.com. 60 IN AAAA 2406:da00:ff00::1715:7cd9
;; Query time: 123 msec
;; SERVER: 2001:4860:4860::8888#53(2001:
4860:4860::8888)
;; WHEN: Tue Jun  5 11:58:23 2012
;; MSG SIZE  rcvd: 134

Note: 2001:4860:4860::8888 is a Google IPv6 DNS Server.

This duality is something we have to keep in mind when testing IPv6. We have to be certain whether our browser will ask for a IPv6 Record or not.
And basically that's it. With the EC2 instance up, the web site up and our CNAME ready in our DNS server (I used http://ipv6.domenech.org) you just need to open a browser and type the URL.

Ta-raaaaa!
ipv6.domenech.org


Appendix.
IP Source: Do not expect to read IPv6 in your Apache log files. All the communication between the ELB and EC2 is IPv4. By default all your connections to your instance will come from the ELB internal IP (something like 10.28.x.x) and this is what you will get at the logs. To reflect your clients IP in your log files instead the ELB IP you need to change the default Apache configuration adding %{X-Forwarded-For}i  to your LogFormat. And to make present this information at your application you need to read the HTTP_X_FORWARDED_FOR header provided by the ELB. The best way to start dealing with headers is to create a PHP test page and read all the headers that come with every request. Don't forget to delete this page when is no longer needed to avoid giving away too much information.