20040112 - Information contained in this document is getting old and some of it is squarely obsolete. You have been warned.
20040112 - This document is back online. Servers had been shuffled around and this document had been overlooked by the administrators...
20030214 - About a thousand pageviews in 24 hours thanks to a couple of Slashdot comments. Quite thrilling considering this page usually takes only a couple dozen hits a day.


Table of Contents

1 Foreword

2 Links

3 Why ?

4 How ?

4.1 Getting Linux ready for IPv6

4.2 Connecting the router to the 6Bone

4.3 Testing IPv6 connectivity to the router

5 Understanding IPv6 addresses

5.1 Notation

5.2 Link-local vs. global unicast

5.3 Recognizing types of addresses

6 Communicating within the LAN

6.1 Setting up the router's LAN interface

6.1.1 Why set it up manually ?

6.1.2 Set the address

6.2 Setting up the stateless autoconfiguration server

6.2.1 What is stateless autoconfiguration ?

6.2.2 Setting up the advertisement daemon

6.2.3 How autoconfigured addresses are built

6.3 Getting the router to route

7 Observing the whole thing happen

8 Do something useful with your IPv6 connected hosts

9 Finding a better IPv6 provider

10 Contributors

11 Todo


Jim's insignificant LAN IPv6 global connectivity HOWTO



Dancing turtles for all !

Updated 20030101



Send comments, suggestions, criticism, money and death threats to Jean-Marc Liotier.



1 Foreword

Dancing turtles for all... Actually, it's swimming rather than dancing, but anyway here is a short guide to global IPv6 connectivity for all hosts on your LAN. It is heavily Debian biased, but I guess Debian users will consider that a bonus. Others will pardon the idiosyncrasies and adapt accordingly or switch to Debian.


2 Links


3 Why ?

Let's consider :

The only solution available to provide Internet access to the hosts on the LAN was to use a private non routable subnet and to masquerade it behind the edge router. NAT also allowed some of these hosts to expose services to the outside world. But this solution has a major drawback : it breaks end to end connectivity and thus complicates the offering of many services that the Internet was meant for. Used like that, NAT is an evil kludge.

IPv6 provides a way out. There certainly are many other advantages in the use of IPv6, but end to end connectivity for the masses is what I am primarily interested in.


4 How ?

Let's get on to the actual step by step guide. No guarantees, your mileage may vary. At least it worked for me.


4.1 Getting Linux ready for IPv6

Start with enabling the ipv6 option in the kernel. I found that I also had to enable netlink device emulation in order to use the tools in the iproute package.


4.2 Connecting the router to the 6Bone

apt-get install freenet6

Go to http://www.freenet6.net/register.shtml and create an account. Accounts are mandatory on Freenet6 if you want an authenticated tunnel or a /48 IPv6 prefix delegation – and you want both. The authenticated tunnel provides one single and permanent IPv6 address to a node in spite of Ipv4 address changes. The /48 IPv6 prefix delegation is how you get a bunch of addresses for those hosts inside your LAN.

Make sure that the values assigned to userid and passwd are the ones that you got by mail from Freenet6. Also add the following options :

host_type=router
prefixlen=48

sit1      Link encap:IPv6-in-IPv4  
          inet6 addr: 3ffe:b80:3:1a91::2/128 Scope:Global
          inet6 addr: fe80::a00:1/10 Scope:Link
          inet6 addr: fe80::c0a8:8b01/10 Scope:Link
          inet6 addr: fe80::3e04:1236/10 Scope:Link
          UP POINTOPOINT RUNNING NOARP  MTU:1472  Metric:1
          RX packets:4648 errors:0 dropped:0 overruns:0 frame:0
          TX packets:5403 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:1093435 (1.0 MiB)  TX bytes:660564 (645.0 KiB)

sit1 is the interface of the IPv6-in-IPv4 tunnel that runs between your edge node and the IPv6 connected node that provides you with connectivity. Congratulation, you have IPv6 connectivity !


4.3 Testing IPv6 connectivity to the router

apt-get install iputils-tracepath
apt-get install iputils-ping
ping6 -c 2 3ffe:b80:3:1a91::2
PING 3ffe:b80:3:1a91::2(3ffe:b80:3:1a91::2) 56 data bytes
64 bytes from 3ffe:b80:3:1a91::2: icmp_seq=1 ttl=64 time=0.079 ms
64 bytes from 3ffe:b80:3:1a91::2: icmp_seq=2 ttl=64 time=0.037 ms

--- 3ffe:b80:3:1a91::2 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1000ms
rtt min/avg/max/mdev = 0.037/0.058/0.079/0.021 ms


traceroute6 3ffe:4013:0:2::2
traceroute to 3ffe:4013:0:2::2 (3ffe:4013:0:2::2) from 3ffe:b80:3:1a91::2, 30 hops max, 16 byte packets
 1  3ffe:b80:3:1a91::1 (3ffe:b80:3:1a91::1)  263.556 ms  285.743 ms  197.612 ms
 2  inode-gw-parcr1.fr.ndsoftwarenet.net (3ffe:4013:f:3::2)  185.702 ms  181.589 ms  177.661 ms
 3  edt-viagenie.ipv6.edisontel.it (3ffe:8170:1:11::1)  335.552 ms  415.807 ms  319.105 ms
 4  tun61-0-parcr1.fr.ndsoftwarenet.net (2001:7a8:1:f004::2)  728.48 ms  394.493 ms  465.463 ms
 5  eth0-1-parcr2.fr.ndsoftwarenet.net (3ffe:4013:0:1::2)  518.149 ms  425.007 ms  441.383 ms

You can also test your IPv6 connectivity from one of the numerous Web interfaces to traceroute6, ping6 and friends. There is a list of sites with such tools at http://www.traceroute6.org/


5 Understanding IPv6 addresses

Before going any further, some degree of familiarity with IPv6 addresses is needed. Here is the skinny on them; if you want more information you can go read http://www.taclug.org/documents/ipv6/x444.htm


5.1 Notation

Leading zeros can be dropped and consecutive strings of zeros can be compressed. So :

        3ffe:ffff:0100:f101:0000:0000:0000:0001
becomes 3ffe:ffff:100:f101:0:0:0:1
or      3ffe:ffff:100:f101::1

The largest reduction is seen by the ipv6 localhost address :

localhost is 0000:0000:0000:0000:0000:0000:0000:0001 and becomes ::1

There is also a short for anyhost (the equivalent of 0.0.0.0 in ipv4) :

0000:0000:0000:0000:0000:0000:0000:0000 becomes ::

Like IPv4, IPv6 uses netmasks and the CIDR notation. Just remember there are 128 bits now instead of 32.


5.2 Link-local vs. global unicast

What you need to know right now is the difference between two types of addresses that will certainly confuse you. Take a look at this section of ifconfig's output :

eth1    Link encap:Ethernet  HWaddr 00:10:5A:66:DC:33  
        inet addr:192.168.139.1  Bcast:192.168.139.255  Mask:255.255.255.0
        inet6 addr: fe80::210:5aff:fe66:dc33/10 Scope:Link
        inet6 addr: 3ffe:b80:17e2::1/64 Scope:Global

eth1 obviously has two IPv6 addresses. But they don't have the same function. The last one has a global scope. It is the global unicast address and draws a direct parallel to the Ipv4 addresses you are certainly already familiar with. The other is a link-local and that is an IPv6 novelty : it is an administrative addresses that only requires an IPv6 enabled kernel to bring itself up. It is only used for administrative communications between neighbors. Link-Local addresses are for use during auto-configuration and for when no routers are present. Using it as a destination would never pass through a router. It is used for link communications such as “is anyone else here on this link ?” or “is anyone here with a special address” (looking for routers). So don't try to ping6 or traceroute6 nor connect to a link-local address because it will get you nowhere.

Link local addresses begin with fe8, fe9, fea, and feb; but you will probably only see examples beginning with fe8, such as the one above.


5.3 Recognizing types of addresses

The beginning of an address provides useful information. Apart from the link local prefixes, here are a few others :

If you encounter an address whose nature you wish to know more about, Peter Bieringer's ipv6calc will tell you everything. The Debian package's name is ipv6calc, you know the drill. Here is an example of ipv6calc showing the properties of a global unicast address that a LAN station set on its Ethernet interface after stateless autoconfiguration :

ipv6calc -i 3ffe:b80:17e2:0:210:5aff:fef1:e854
Address type:  unicast 6bone
Address type has SLA: 0000
Interface identifier: 0210:5aff:fef1:e854
Interface identifier is an EUI-64 generated from EUI-48 (MAC): 00:10:5a:f1:e8:54
MAC is a global unique one

And here is another example of ipv6calc giving information about the link-local address on the same node :

ipv6calc -i fe80::210:5aff:fef1:e854
Address type:  unicast link-local
Interface identifier: 0210:5aff:fef1:e854
Interface identifier is an EUI-64 generated from EUI-48 (MAC): 00:10:5a:f1:e8:54
MAC is a global unique one

No shell access or too lazy to install the package ? Point your IPv6 enabled browser to http://ipv6to4.aerasec.de/index2.html.en and you will see what ipv6calc has to say about your address.


6 Communicating within the LAN

It's all nice and dandy to have your router part of the IPv6 world, but what you really want is to bring this connectivity to your users on the LAN. Let's do it !


6.1 Setting up the router's LAN interface

6.1.1 Why set it up manually ?

To perform stateless autoconfiguration, a host needs a router running radvd. But the IPv6 network must be bootstrapped at some point. So routers must know their own address without the need for another host to tell them. That's why we must set the router's LAN interface's address by means other than autoconfiguration.

That does not mean that it can't be done automatically : on getting the delegated /48, Freenet6's scripts are supposed to be able to set your LAN interface's address for you. But I have not found out how to do that yet, and since setting the fixed address in /etc/network/interfaces once and for once is not much more complicated, that's the way I will show you how to do it. And doing it manually once in your life will bring you a little bit of understanding of how things actually happen, and that never hurts.

6.1.4 Set the address

Very easy : take the prefix you got from the IPv6 connectivity provider. In my case it is 3ffe:0b80:17e2::
and append a unique identifier. Simple. If you want to be absolutely sure that the identifier is unique to your prefix, you can use the same algorithm I describe for building an address during stateless autoconfiguration, but an arbitrary identifier should be OK in about all cases.

Since this host is my LAN's main router, I thought '1' would be a suitable identifier. Appended at the end of '3ffe:0b80:17e2::' it becomes '3ffe:b80:17e2::1' and that's going to be the router's LAN interface's address - global unicast of course. If you wanted to subnet your prefix, the the :: between the prefix and the identifer could be changed to whatever subnet you wanted to use. Remembering you have 16 bits for subnetting you can set it to anything from :: to :FFFF:

But for now I am content with just one big subnet so I added the following to /etc/network/interfaces :

iface eth1 inet6 static
        address 3ffe:b80:17e2::1
        netmask 64
        gateway 3ffe:b80:3:1a91::1

The gateway's address is the tunnel server's. In the output of 'grep type=\"ipv6\" /var/log/syslog' you will find something like “<server> <address type="ipv4">206.123.31.114</address> <address type="ipv6">3ffe:0b80:0003:1a91:0000:0000:0000:0001</address> </server>”. 3ffe:0b80:0003:1a91:0000:0000:0000:0001 is the IPv6 address of the tunnel server and that's your default gateway.


6.2 Setting up the stateless autoconfiguration server

6.2.1 What is stateless autoconfiguration ?

Hosts on a LAN have the capability to autoconfigure as defined in RFC2462 : they automatically create a unique link-local addresse for each LAN interface that appear to be Ethernet, and they use that address to receive router advertisement messages to automatically configure the following parameters :


6.2.2 Setting up the advertisement daemon

So now we need a router that advertises the needed parameters. Aboard the router, radvd (Router Advertisement Daemon) is the piece of software that provides this information to other hosts on the LAN. So first, install radvd :



apt-get install radvd

Then edit /etc/radvd.conf

Mine looks like that :

interface eth1 {
   AdvSendAdvert on;
   prefix 3ffe:0b80:17e2:: /64
   {
        AdvAutonomous on;
        AdvOnLink on;
        AdvRouterAddr on;
        };
};  

The critical part is the prefix that radvd advertises. You can find it in your logs, for exemple by trying the following command :

grep type=\"ipv6\" /var/log/syslog

The output will be something like :

Dec 18 21:35:54 Kisangani TSPClient:  ExtractPayload: 200 Undefined <tunnel action="info" type="v6v4"
 lifetime="129600">  <server>   <address type="ipv4">206.123.31.114</address>   <address
 type="ipv6">3ffe:0b80:0003:1a91:0000:0000:0000:0001</address>  </server>  <client>   <address
 type="ipv4">62.4.18.54</address>   <address type="ipv6">3ffe:0b80:0003:1a91:0000:0000:0000:0002</address>
 <address type="dn">ruwenzori.tsps1.freenet6.net</address>   <router>    <prefix
 length="48">3ffe:0b80:17e2:0000:0000:0000:0000:0000</prefix>   </router>  </client> </tunnel>

<prefix length="48">3ffe:0b80:17e2:0000:0000:0000:0000:0000</prefix> is the critical part : from that you know that the prefix given by Freenet6 is 3ffe:0b80:17e2:: /48. If you just want a single subnet, substitute /64 for the /48 and you have the prefix that radvd will advertise. But you could also cut your /48 in multiple /64 subnets by using the last 16 bits for subnetting. For example you could have 3ffe:0b80:17e2:1: /64, 3ffe:0b80:17e2:2: /64, 3ffe:0b80:17e2:3: /64 and so on : 16 bits give you up to 65536 /64 subnets (with 2^64 hosts each...). Configuring a few more subnets to which your router is connecter is probably just a matter of adding a few more interface ethx... stanzas in radvd.conf but I have never done it myself.

I just want one subnet, and my prefix is therefore 3ffe:0b80:17e2:: /64. So in radvd.conf the line that begins with “prefix” will be :

 prefix 3ffe:0b80:17e2:: /64

Execute '/etc/init.d/radvd restart' and radvd is ready to serve and the other hosts on the LAN will configure themselves at kernel boot time with no intervention from your part.

Freenet6 is supposed to take care of configuring radvd by writing radvd.conf for you and restarting radvd automatically. The problem is that Andreas Rottmann, the Debian maintainer of the radvd decided that it should not let Freenet6 rewrite the entire configuration file lest manual modifications by the administrator be overwritten. He asked if it would be possible to have a way for freenet6 to change the advertised prefix of radvd without rewriting the whole config file. But Nathan Lutchansky answered in substance that administrator who do not want to risk their modifications overwritten should handle radvd.conf manually. I believe it is true that configurations more complex than the simple automatically manageable case are indeed rare, but in typical Debian fashion Andreas Rottman probably believes he is better safe than sorry, and so he commented out the parts of /etc/freenet6/setup.sh that deal with rewriting radvd.conf. If you feel adventurous you can uncomment them, see what happen and tell me. Right now I'm happy with my manually configured radvd.conf and too lazy to try anything else...


6.2.3 How autoconfigured addresses are built

So you have a router that advertises your 48 bit prefix. You certainly wonder how the LAN host ends up with a 128 bit address. Read on and you shall soon know...

The last 64 bits of an IPv6 address are the interface identifier that is unique to the prefix. RFC2464 states that the interface identifier is based on the EUI-64 identifier. The IEEE EUI-64 address represents a new standard for network interface addressing. It supersedes the MAC addressing, also known as IEEE 802. The company ID is still 24-bits in length, but the extension ID is 40 bits instead of only 24 in the MAC address, creating a much larger address space for a network adapter manufacturer. So since the Ethernet adapter you most probably use on your computer use is certainly identified by a good old 48 bit MAC address, we'll need to map it to a 64 bit IEEE-64. And that's where the magic ingredient comes in : just add some padding. RFC2464 says “The fourth and fifth octets of the EUI are set to the fixed value FFFE hexadecimal.

So, to create an EUI-64 address from a MAC address, the 16 bits of 11111111 11111110 (0xFFFE) are inserted into the IEEE 802 address between the company ID and the extension ID. For example :

- The MAC address :
00:10:5a:66:dc:33
- The padding :
fffe
- The resulting almost EUI-64 address :
00:10:5a:ff:fe:66:dc:33

At this point you certainly wonder what the hell an "almost EUI-64 address" is. It simply means that from where we are we need to set the lowest order bit in the first octet (00 is the first octet of my example) from 0 to 1 for a globally unique IPv6 interface identifer. In my example, the first byte in binary form is 00000000. When the seventh bit is complemented, it becomes 00000010 (0x02). That gives us a first octet as 02 giving making the EUI-64 interface 0000:0210:5aff:fe66:dc33

Now, I have my prefix (3ffe:b80:17e2::) and a EUI-64 identifier (210:5aff:fe66:dc33). I concatenate the two... Lo and behold the 128 bit splendor : 3ffe:b80:17e2::210:5aff:fe66:dc33 is the LAN interface's IPv6 global unicast address.


6.3 Getting the router to route

Now boot a host on the LAN and you will see it get an IP address automatically. 'ip -6 route neigh show' will show you his neighbours. You can even touch the router. But not yet the outside world : the router and the outside node don't know where to send packets destined to the LAN. To tell the router that the subnet whose 48 bit prefix the IPv6 connectivity provider gave you lies on the inside LAN, you can use something like he following command :

ip -6 route add  3ffe:0b80:17e2::/48 dev eth1

That's where it pays to have enabled the netlink device emulation : the command fails without it. To manage the route automatically, you can add the following two lines to /etc/network/interfaces :

up ip -6 route add 3ffe:0b80:17e2::/48 dev eth1
down ip -6 route del 3ffe:0b80:17e2::/48 dev eth1

As a result, some section of your /etc/network/interfaces should look somewhat like that :

iface eth1 inet6 static
        address 3ffe:b80:17e2::1
        netmask 64
        gateway 3ffe:b80:2:adee::3e04:1236
        up ip -6 route add 3ffe:0b80:17e2::/48 dev eth1
        down ip -6 route del 3ffe:0b80:17e2::/48 dev eth1

Now, 'ip -6 route' should output something like that :

3ffe:b80:17e2:fffe::/64 dev eth1  proto kernel  metric 256  mtu 1500 advmss 1440
2000::/3 dev sit1  metric 1  mtu 1472 advmss 1412
fe80::/10 dev eth1  proto kernel  metric 256  mtu 1500 advmss 1440
fe80::/10 dev eth0  proto kernel  metric 256  mtu 1500 advmss 1440
fe80::/10 via :: dev sit1  proto kernel  metric 256  mtu 1472 advmss 1412
ff00::/8 dev eth1  proto kernel  metric 256  mtu 1500 advmss 1440
ff00::/8 dev eth0  proto kernel  metric 256  mtu 1500 advmss 1440
ff00::/8 dev sit1  proto kernel  metric 256  mtu 1472 advmss 1412
default dev sit1  metric 1  mtu 1472 advmss 1412
unreachable default dev lo  metric -1  error -101


7 Observing the whole thing happen

Your work has born its fruits : you can now inform your amazed users of the availability of the dancing turtle at http://www.kame.net/. Isn't IPv6 wonderful ? Of course only users of IPv6 enabled browsers such as Mozilla on IPv6 enabled hosts will enjoy the sight of the mythical animal. It may seem obvious, but when it comes to users, nothing is obvious.

If you want to have a look at the passing packets, ethereal is a good GUI choice. Enter 'ipv6' (without the quotes !) as a display filter and enjoy the view. If you prefer a simpler tool, tethereal works well in the console.


8 Do something useful with your IPv6 connected hosts

Connectivity is nice, but doing something useful with it is even better. So bring on the apps !

The standard Debian distribution comes with some degree of IPv6 support, but it is actually still patchy. IPv6 is a continuing goal of the Debian project, but a few hurdles make widespread IPv6 support throughout the distribution a non-trivial task. First, IPv6's specifications having long been a moving target does not make implementation particularily easy. Then even when IPv6 is implemented in the upstream package it is often disabled by the Debian package's maintainer. The reason is that enabling IPv6 by default seems to have often generated various breakages that convinced maintainers that a conservative configuration was preferable. Luckily you will find under the Debian-IPv6 banner a group of motivated individuals that are pushing IPv6 support in the distribution. Until the day when all their work is merged in the mainstream distribution, you can find their IPv6 enabled packages. Once the packages hit the main Debian archive they are removed from this archive.

The packages are provided in a central apt-getable repository. They provide a list of mirrors. Just keep in mind that those are experimental packages, so the usual warnings apply.


9 Finding a better IPv6 provider

A few Internet access providers now offer /48 subnets to their customers who can then enjoy radically lower latency for their IPv6 traffic. The long way across the tunnel to the endpoint and then to the destination and back the same way make for barely tolerable latency. An endpoint right across the DSL link will really make IPv6 usable for the common folk.

In France, Nerim http://www.nerim.net/ proposes such a service to subscribers for free, although it is not standard and you have to ask for it specifically. If you are a customer, send your polite request to ipv6@nerim.net.

There are certainly other providers with such offerings. Please notify me if you encounter one and I will list him here as an encouragement to the others.


10 Contributors

Jean-Marc Liotier is the original author and the current maintainer.
David Goodenough was the first to spot a typo in an example address. But the error was apparently much deeper than a typo and
Jeremy T. Bouse sent me a heavy erratum for former section 6.2 "Setting up the router's LAN interface". Turns out I had not understood correctly how to produce an address. As a result, I rewrote sections 6.1 "Setting up the router's LAN interface" and 6.2 "Setting up the stateless autoconfiguration server". Writing a howto is a good way to make sure you really understand the subject...


11 Todo


This is ruwenzori.net.