My IPv6 Day-after Day
To celebrate World IPv6 Day, I thought I would join the “festivities”—one day late, unfortunately—and enable IPv6 on my home network, with a total switch-over if possible. The three most common services on my network are OpenSSH on all three nodes, and NFS and HTTP on my central server running FreeBSD 8.1-RELEASE, so I wanted to make all three work over IPv6.
Most Linux distributions make IPv6 available in their stock kernels, either built-in or through the “ipv6″ module. I use my own home-built kernels, so I enable IPv6 via the configuration menu, Networking support -> Networking options -> The IPv6 protocol.
To see if IPv6 is already available on your system, simply run as root:
ifconfig lo | grep inet6
and you should see “::1″, the IPv6 localhost address. Another possibility is to test the existence of /proc/net/ipv6_route. If IPv6 doesn’t appear to be available yet, try running “modprobe ipv6″ as root, then re-run the “ifconfig” command above.
For a quick overview of IPv6 deployment, I recommend Carla Schroeder’s IPv6 Crash Course and its sequel. Don’t copy the 2001:db8 network ID directly for your own use, because it’s reserved for documentation purposes. Remember, examples are just examples!
For IPv4 addresses, I had used a 192.168.0 network, with the final octet being 100 or higher for mobile or testing systems, and less than 100 for desktops and servers. This was my chance to move away from that.
According to the Linux+IPv6 HOWTO, the fe80 prefix is standard for addresses on the same LAN, with the network card’s MAC address arranged into the host portion of the IPv6 address. This isn’t for direct host communication, but rather for neighbor discovery (replacing IPv4′s ARP) and router discovery.
So-called “site-local” addresses in the fecx-fefx block are deprecated, because the term “site-local” was so vaguely defined during IPv6′s initial definition. The fcxx and fdxx blocks are now standard for local unicast addresses. I filled out the remaining 40 bits using the arbitrary digits “97-72-48-47-12″ but this is not advised for general use. Local unicast networks should normally get their network ID’d from a dedicated generator; the Linux+IPv6-HOWTO mentions Goebel Consult’s createLULA for this purpose. Since my home network has no outside connectivity, at least for now, a network ID collision is impossible.
For the host ID, I decided to use just a hex digit corresponding to the first or second letter of the hostname.
All systems got the following added to their /etc/hosts files:
::1 localhost localhost.localdomain fd97:7248:4712::61 andrew6 fd97:7248:4712::65 peter6 fd97:7248:4712::6a james6 fd97:7248:4712::70 paul6
During the initial setup, I didn’t want to create any protocol conflicts between hostnames, so a simple “6″ added to each kept things safely separated. (“peter6″ is a Sparc32 NetBSD system which won’t get IPv6 for now. I’m short an Ethernet cable, and can’t test it.)
Slackware does not ship with support for scripted IPv6 configuration in /etc/rc.d/rc.inet1.conf. Because of this, I opted to delay all boot-time IPv6 configuration until /etc/rc.d/rc.local; hacks on /etc/rc.d/rc.inet1 would be lost in the next update of the network-scripts package. On the 32-bit netbook, I have the following before all other commands in /etc/rc.d/rc.local:
if [ ! -f /proc/net/ipv6_route ] ; then /sbin/modprobe -q ipv6 fi if [ -f /proc/net/ipv6_route ] ; then echo -n "Configuring IPv6" /sbin/ifconfig eth0 inet6 add fd97:7248:4712::6a/64 # /sbin/route -A inet6 add fd97:7248:4712::/64 eth0 echo " ... done" fi
Note the “route” command being commented out. I had added it initially, but later found it to be unnecessary.
After adding this code and saving /etc/rc.d/rc.local, I rebooted to test its robustness. The “Configuring IPv6″ message appeared, with no errors, and “ifconfig eth0″ reported the three correct addresses: the IPv4 address, the IPv6 link-local address starting with “fe80:”, and the IPv6 local unicast address starting with “fd97:”.
On my Linux desktop (64-bit), almost the same thing, except for the host address:
if [ ! -f /proc/net/ipv6_route ] ; then /sbin/modprobe -q ipv6 fi if [ -f /proc/net/ipv6_route ] ; then echo -n "Configuring IPv6" /sbin/ifconfig eth0 inet6 add fd97:7248:4712::70/64 # /sbin/route -A inet6 add fd97:7248:4712::/64 eth0 echo " ... done" fi
Again, a reboot and “ifconfig” showed the correct addresses.
Modern FreeBSD has full support for IPv6, needing just two options in /etc/rc.conf. Note that my Ethernet interface is called “rl0″:
ipv6_enable='YES' ipv6_ifconfig_rl0='fd97:7248:4712::61 prefixlen 64'
Because this system is headless, network stability is definitely an issue. Using the “andrew6″ name for IPv6 made sure not to interfere with remote access, in case the new configuration didn’t work as expected. Fortunately for me, it caused no problem during the reboot.
Once the systems had their new addresses, they had to be able to send data on the network. The “ping6″ program uses ICMPv6 to accomplish the same task that “ping” uses for IPv4 testing. I checked that all three systems could send echo-requests and respond with echo-replies. Success! I had set up a working IPv6 network at home!
The first service I tested against IPv6 was SSH, since it’s the one I invoke most often. This is also the service conversion I feared most. Following Carla Schroeder’s advice in her IPv6 Crash Course would lead only to hair-pulling, or shell aliases. After all, which of these is easiest on the brain?
alias sj6='ssh james6@fd97:7248:4712::6a%eth0' sj6
A test of the simplest first, was successful. Both X forwarding and “scp” copying worked with the simple “james6″ name.
Firefox was a different story. I knew that IPv6 was available on FreeBSD 8.1-RELEASE, but Firefox was simply not retrieving anything via the “andrew6″ name. It took me a day of not thinking about it, to figure out what I needed to do. More on that later.
NFS was going to provide the biggest challenge, because it’s the protocol I understand least. If it didn’t work over IPv6, I would have the least ability to research the low-level goings-on. Taking the same guess that I took with SSH, I tried:
mount -t nfs andrew6:/home/gus3/slackdir /home/gus3/slackdir
The result was an error message indicating “Temporary failure in name resolution”. Since the name should have come from /etc/hosts, it seemed odd that it couldn’t resolve the “andrew6″ name to an address. I re-ran the command, prefixed with “strace -f” to watch file and network accesses. Sure enough, the mount.nfs program was reading /etc/hosts, but it then proceeded to attempt a DNS lookup. I eventually found the answer in the nfs(5) man page, describing the “proto=” option:
If support for TI-RPC is built into the mount.nfs command, netid is a valid netid listed in /etc/netconfig. The value “rdma” may also be specified. If the mount.nfs command does not have TI-RPC support, then netid is one of “tcp,” “udp,” or “rdma,” and only IPv4 may be used.
Given that my Slackware systems don’t have a /etc/netconfig file, I think it’s safe to assume there is no TI-RPC support either. My NFS is stuck on IPv4. Drat.
After putting the task to rest for the night, I pondered what might be going on with Firefox. The next day, I searched for any compatibility issues with FF and IPv6, and turned up the gold nugget in a bug report for Seamonkey: check the “about:config” settings list. Sure enough, someone (myself?) had set “network.dns.disableIPv6″ to “true”. A double-click on that setting fixed it.
The other setting that may have interfered with things was not listing my IPv6 hostnames under “network.proxy.no_proxies_on”. Not having the IPv6 names listed under “no proxies”, Firefox was trying to send the requests through a proxy. The normal route for editing the No Proxies list is under Edit/Preferences, Advanced, Network, Settings, No Proxy For:. (My Firefox proxy settings are a remnant of a couple years ago.)
These changes still didn’t enable Firefox to retrieve the home page from my web server; it merely changed the error message on the screen. It went from a name lookup failure, to “connection refused”, so at least the attempt was being made. Checking the network status on the web server (“netstat -l -A inet6″) showed that THTTPD wasn’t listening for incoming connections on IPv6. And no wonder; I had specified “host=andrew” in the config file, so it was listening only on the IPv4 address. The simple fix was simply to comment out the “host=” line, to let THTTPD listen on all available local addresses.
Fixing the Intraweb setup took the most work, but it highlighted the central point of all network communications: one end must be talking to the other end, and the other end must be listening. This may seem elementary, but forgetting it is a prelude to feeling silly when you do remember it.
If not for my NFS client’s lack of IPv6 support, the next step would have been to switch the names around in the /etc/hosts files, to make IPv6 the default addressing for the regular hostnames. I’ll have to wait for that.
Enabling IPv6 wasn’t merely an exercise; I wanted to find out what a “real user” could expect to encounter during such a change-over. I hope my notes can help someone else during their own rollout of IPv6.