In which we intrepid network administrators learn how to set up local IPv6 networks, and how to connect to public IPv6 networks with ease and panache.
In our previous two installments, we learned of the many benefits of using IPv6 beyond just having a larger pool of IP addresses, and how to read and understand IPv6 addresses. Now let's head to the network playground and have some fun.
Before we dive in, I must warn you that IPv6 in Linux is still rough around the edges. The core work is mostly done: your distribution should support it out of the box, and so should your networking applications. But don't be surprised if you bump into unexpected hassles and roadblocks — it's not your fault. Usually.
Your network interface cards should be getting IPv6 link-local addresses by default, so they're ready to go. This means you can bring a group of people together for a meeting and have instant connectivity without needing a router, or servers, or any kind of outside tools. Whether that connectivity will do you any good is a separate issue — it depends on what applications you want to use, and if they support IPv6.
To see if your Linux installation is IPv6-enabled, the ifconfig command shows all:
eth1 Link encap:Ethernet HWaddr 00:03:6D:00:83:CF
inet addr:192.168.1.10 Bcast:192.168.1.255 Mask:255.255.255.0
inet6 addr: fe80::203:6dff:fe00:83cf/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
We can ping both the loopback address and the link-local address. Ping loopback like this:
$ ping6 -c4 ::1
PING ::1(::1) 56 data bytes
64 bytes from ::1: icmp_seq=1 ttl=64 time=0.048 ms
64 bytes from ::1: icmp_seq=2 ttl=64 time=0.057 ms
64 bytes from ::1: icmp_seq=3 ttl=64 time=0.057 ms
64 bytes from ::1: icmp_seq=4 ttl=64 time=0.058 ms
--- ::1 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3000ms
rtt min/avg/max/mdev = 0.048/0.055/0.058/0.004 ms
Pinging IPv6 link-local addresses is trickier- you must specify the interface, like this:
$ ping6 -c4 -I eth1 fe80::203:6dff:fe00:83cf
PING fe80::203:6dff:fe00:83cf(fe80::203:6dff:fe00:83cf) from fe80::203:6dff:fe00:83cf eth1: 56 data bytes
64 bytes from fe80::203:6dff:fe00:83cf: icmp_seq=1 ttl=64 time=0.051 ms
64 bytes from fe80::203:6dff:fe00:83cf: icmp_seq=2 ttl=64 time=0.064 ms
64 bytes from fe80::203:6dff:fe00:83cf: icmp_seq=3 ttl=64 time=0.060 ms
64 bytes from fe80::203:6dff:fe00:83cf: icmp_seq=4 ttl=64 time=0.064 ms
--- fe80::203:6dff:fe00:83cf ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3003ms
rtt min/avg/max/mdev = 0.051/0.059/0.064/0.010 ms
Now let's discover the other IPv6 link-local hosts on the LAN by pinging the multicast address:
$ ping6 -I eth1 ff02::1
PING ff02::1(ff02::1) from fe80::203:6dff:fe00:83cf eth1: 56 data bytes
64 bytes from fe80::203:6dff:fe00:83cf: icmp_seq=1 ttl=64 time=0.058 ms
64 bytes from fe80::214:2aff:fe54:67d6: icmp_seq=1 ttl=64 time=1.27 ms (DUP!)
64 bytes from fe80::200:24ff:fec1:1df0: icmp_seq=1 ttl=64 time=14.5 ms (DUP!)
64 bytes from fe80::220:e0ff:fe8f:ea44: icmp_seq=1 ttl=64 time=17.8 ms (DUP!)
Stop with Ctrl+C when you start seeing the addresses repeated. This shows four hosts on the network with link-local IPv6 addresses. These can be pinged too:
$ ping6 -I eth1 fe80::214:2aff:fe54:67d6
You can have a pure IPv6 LAN with no IPv4 addresses at all. Your NICs need to be physically connected to the network, and they need a minimal configuration. On Debian, make /etc/network/interfaces look like this:
# never mess with lo! Always have
# these lines
iface lo inet loopback
# eth0 minimal config
iface eth0 inet manual
On Fedora (and Red Hat and all the RH clones), the eth0 configuration file is buried deeply within the file tree, at /etc/sysconfig/network-scripts/ifcfg-eth0:
On Debian it seems that the IPv6 interface comes up when networking starts, even though it's configured not to. On Fedora, run ifup [interface] to make it go. Run /sbin/ifdown and then /sbin/ifup if you encounter any interface sass.
SSH and SCP
You have connectivity and are ready to go. What do you do now? All of the fundamental Linux networking utilities support IPv6. Today we'll look at OpenSSH.
OpenSSH has great native IPv6 support, so you can log in to your LAN hosts and do SSH and scp things just like on IPv4. However, the scp man page neglects to mention that IPv6 addresses require special syntax. This example shows how to copy the local file "coolstuff" to a second PC:
$ scp coolstuff \[fe80::220:e0ff:fe8f:ea44%eth1\]:
I was darn near homicidal by the time I figured this out. The IPv6 address must be enclosed in square brackets, which must then be escaped with backslashes. And you still have to specify the local interface to use, delimited with a percent mark- which in this example is %eth1. This example shows how to log into a different remote user's account, and to rename the file at its destination:
$ scp coolstuff otheruser@\[fe80::220:e0ff:fe8f:ea44%eth1\]:coolstuff_copy
If you don't get this just right, scp will unhelpfully tell you
ssh: fe80: Name or service not known
SSH connections are established like this, without the goofy escape guff:
$ ssh fe80::20a:e4ff:fe40:8bfd%eth1
Or you can log in as a different user:
$ ssh admin@fe80::20a:e4ff:fe40:8bfd%eth1
Assigning Global IPs
These examples are just for practice, because your real ones come from a pool of IPv6 prefixes assigned to you by your Internet service provider. Do this on a test network that is not connected to the Internet, or shut off any routes to your Internet gateway, or you might find ping wandering all over the Internet. Use the ip command to assign new addresses:
# ip -6 addr add 2001:0db8:0:f101::1/64 dev eth1
You don't need to hassle with specifying interfaces or escaping brackets when you want to ping or ssh to a global unicast address:
# ping6 2001:0db8:0:f101::1
$ ssh 2001:0db8:0:f101::1
$ scp wordcount \[2001:0db8:0:f101::1\]:
Only scp is still persnickety.
Removing addresses is done with this command:
# ip -6 addr del 2001:0db8:0:f101::1/64 dev eth1
The /64 is not CIDR notation, but the length of the prefix. Even though we have a total of 128 bits to play with, we're not even coming close to using all of them. The portion of the address that is available for the interface is 64 bits, just like the prefix. Its uncompressed notation is 0000:0000:0000:0001, or, way more than the entire IPv4 address space, which is a puny 32 bits. The interface address itself uses up a whole four bits, so that leaves a bit of room for expansion. (See part 2 to learn about using ipv6calc to calculate IPv6 addresses.)
Global unicast address blocks will be allocated in varying sizes. If you're curious, visit Iana.org for complete information.
Want to add another address to the same interface, or to a different host? Easy as pie:
# ip -6 addr add 2001:0db8:0:f101::2/64 dev eth1
Just count up sequentially in hexadecimal- 01, 02, 03, 04, 05, 06, 07, 08, 09, 0a, 0b, 0c, 0d, 0e, 0f, 10, 11, and so on.
IPv6 Over the Internet
Nothing beats having real live IPv6 over the Internet for testing and practice. You might be lucky and have an IPv6-friendly ISP on a real IPv6 backbone. Another option is to get an account on one of the many free IPv6 Internet tunnel brokers, which will allow you to test every aspect of running services and running IPv6 and IPv4 side-by-side, which is how it's going to be for the foreseeable future.
SixXS list of IPv6 tunnel brokers
IPv6 & Linux - Current Status - Distributions
Current Status of IPv6 Support for Networking Applications
The excellent O'Reilly titles, "IPv6 Essentials" and "IPv6 Network Administration"