IPv6 Crash Course For Linux


You might be used to working with IPv4 on Linux, but like it or not IPv6 is on its way in. Roll up your sleeves, spit on your palms, and get ready to go to work because this is your crash course in actually using IPv6. It hardly hurts at all. Linux has supported it since the 2.1 kernel, so you shouldn’t have to install anything. Make sure you have the ping6, ip, and ifconfig commands.

Let’s get my favorite nitpick out of the way right now — we do not have IPs, we have IP addresses. IP stands for Internet Protocol. As my wise grandmother used to say, sloppy speech equals sloppy habits, which equals a trip to hell in a handbasket.

IPv6 Advantages

What does IPv6 offer over IPv4? Well, aside from the fact that we’re more or less out of new IPv4 addresses, IPv6 has a number of additional advantages.

  • No more private address collisions.
  • Network address translation (NAT) is optional, rather than a necessity.
  • Simplified routing.
  • Say good-bye to DHCP.

One major drawback to IPv6 is unwieldy long hexadecimal addresses. IPv4 dotted quads are easy to remember. Eight clumps of hexadecimal numbers are a lot harder, at least for my old brain.

Does My Linux System Support IPv6?

How do you know if your system supports IPv6? Simple:

$ cat /proc/net/if_inet6
000000000000000000000000000000 01 01 80 10 80       lo
fe80000000000000020b6afffeef7e 8d 02 40 20 80     eth0

This means yes. Most modern distros should support IPv6 out of the box.

Pinging IPv6

If you want to ping IPv6 addresses, you’ll need the ping6 command. This pings localhost twice:

$ ping6 -c2 ::1
PING ::1(::1) 56 data bytes
64 bytes from ::1: icmp_seq=1 ttl=64 time=0.043 ms
64 bytes from ::1: icmp_seq=2 ttl=64 time=0.054 ms

--- ::1 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 999ms
rtt min/avg/max/mdev = 0.043/0.048/0.054/0.008 ms

::1 is shorthand for 0000:0000:0000:0000:0000:0000: 0000:0001. Any one unbroken sequence of consecutive zeros can be shortened to a pair of colons, and any quad of all zeroes can be condensed to a single zero, like

LAN Discovery

Want to find out if you have IPv6 neighbors on your LAN?

$ ping6 -c4 -I eth0 ff02::1
PING FF02:0:0:0:0:0:0:1(ff02::1) from fe80::20d:b9ff:fe05:25b4 eth0: 56 data bytes
64 bytes from fe80::20d:b9ff:fe05:25b4: icmp_seq=1 ttl=64 time=0.301 ms
64 bytes from fe80::20b:6aff:feef:7e8d: icmp_seq=1 ttl=64 time=3.69 ms (DUP!)
64 bytes from fe80::221:97ff:feed:ef01: icmp_seq=1 ttl=64 time=8.91 ms (DUP!)
[snip duplicate lines]

--- FF02:0:0:0:0:0:0:1 ping statistics ---
4 packets transmitted, 4 received, +6 duplicates, 0% packet loss, time 3000ms
rtt min/avg/max/mdev = 0.254/1.698/8.911/2.593 ms

The response shows that yes, there are two — fe80::20b:6aff:feef:7e8d and fe80::221:97ff:feed:ef01. Note that you must specify which network interface to use, even if you have only one. ff02::1 is short for ff02:0:0:0:0:0:0:1, which is a special link-local multicast address for discovering all link-local hosts.

Link-local addresses are all in the fe80::/10 address range. These are comparable to the address block in IPv4, the stateless address auto-configuration blocks. The IPv6 protocol requires link-local addresses, even if you are using other assigned addresses.

Now that you have connected to two LAN IPv6 hosts they are in the IPv6 neighbor table, which is just like the IPv4 ARP (address resolution protocol) table. You can read this table with the ip command:

$ ip -6 neigh show

fe80::221:97ff:feed:ef01 dev eth0 lladdr 00:21:97:ed:ef:01 nud reachable
fe80::20b:6aff:feef:7e8d dev eth0 lladdr 00:0b:6a:ef:7e:8d nud reachable

Here, nud reachable means the network unreachability detection status is reachable; the node(s) have been contacted and cached in the neighbor table. The neighbor table is temporary and entries disappear in a few minutes when there is no traffic to them.

You can ping these neighbors:

$ ping6 -c4 -I eth0  fe80::221:97ff:feed:ef01

Using Hostnames

We’ll get to the proper “leet” network administrator method of assigning hostnames in a future installment; for today let’s use good old reliable /etc/hosts. Let’s say you have three PCs in your little link-local LAN: fatfreddy, phineas, and franklin. You can use these fine hostnames over IPv6 as easy as pie. You’ll make identical entries in the /etc/hosts file of each PC, like this:

fe80::20b:6aff:feef:7e8d  fatfreddy
fe80::221:97ff:feed:ef01  phineas
fe80::3f1:4baf:a7dd:ba4f  franklin

Now you can ping6 by hostname:

$ ping6 -I eth0 phineas
PING phineas(phineas) from fe80::221:97ff:feed:ef01 eth0: 56 data bytes
64 bytes from phineas: icmp_seq=1 ttl=64 time=17.3 ms


SSH and SCP both speak IPv6. Warning: there are some syntax gotchas, so pay attention. You can log in and copy files on your ad-hoc IPv6 link-local network just like on your old-fashioned IPv4 network. If you have IPv6 name services set up then you don’t do anything differently. For example, you can login via ssh as a different user in the usual way, ssh user@remotehost. Copying a file is also exactly the same: scp filename user@remotehost:/home/username/directory/.

It gets tricky using your IPv6 link-local addresses. This is how you establish an SSH session:

ssh phineas@fe80::221:97ff:feed:ef01%eth0

Again, you must specify the network interface name on your PC, and you must do it as shown, appended with a percent sign and no spaces. scp has its own fiendish syntax quirks:

$ scp test.txt phineas@[fe80::221:97ff:feed:ef01%eth0]:
phineas@fe80::221:97ff:feed: ef01%eth0's password:
test.txt 100%   19     0.0KB/s   00:00 

The IPv6 address must be enclosed in square braces, including the interface name, and the braces must be escaped.

What is My IPv6 Address?

The ifconfig -a command displays complete information on all of your network interfaces, both physical and virtual. When you know which interface to query you can quickly narrow it down with grep:

$ ifconfig eth0 |grep "inet6 addr:"

          inet6 addr: fe80::20d:b9ff:fe05:25b4/64 Scope:Link

Venturing Forth Upon the Internet

Faffing around on your LAN is all right, but what about venturing forth into the great wide Internet via IPv6? For this you need an Internet service provider that offers native IPv6, which in the US is a sadly small number. I set up my first test IPv6 network in 2004. If you had told me back then that seven years later it would have been pretty much the same I would not have believed you. Well here we are in this glorious year 2011, a little bit advanced from 2004. In the meantime you can test the waters with IPv6-over-IPv4 tunnel brokers (just like in 2004!) such as SixXS or Hurricane Electric.

June 8, 2011 is World IPv6 Day, when Google, Comcast, Facebook, Yahoo!, Akamai and Limelight Networks and other providers will provide native IPv6 connectivity for 24 hours. Test your readiness and learn more at Test IPv6.

Just like IPv4, you need to receive an allocation of IPv6 addresses from your ISP. These are global unicast addresses, and they are in the 2000::/3 range. Let’s fake one up for practice and assign it to a network interface:

# ip -6 addr add 2001::1/64 dev eth0

Now let’s check our work:

$ ifconfig eth0 |grep "inet6 addr:"

          inet6 addr: 2001::1/64  Scope:Global
          inet6 addr: fe80::20b:6aff:feef:7e8d/64 Scope:Link

If you need to remove it, use the del command with the ip utility:

# ip -6 addr del 2001::1/64 dev eth0

In real life you’ll get a big block of addresses, like 256 or more, and you’ll set up a proper server for allocating them to your hosts. Come back in part two to learn how to do this both simulated and for real, some firewall rules for IPv6 so you don’t leave yourself open to sneak attacks, and how to manage name services.