So you’ve heard about Internet Protocol Version 6 (IPv6), the latest and greatest Internet Protocol address strategy. You’ve heard that it will solve the looming shortage of IP addresses, that it changes the format of IP addresses, and even that some sites are using IPv6 now. You might be wondering if your Linux system is IPv6-ready, whether you can use IPv6 now, and whether you can set up your Apache Web server to use it. For some versions of Linux the answers to these pressing questions are yes, yes, and yes.
But wait! Don’t run off and log on as root yet! While IPv6 is largely defined and some Linux kernels support it, a variety of issues remain unresolved and some features are not yet implemented. IPv6 is not ready for prime-time yet. Having said that, it’s still very worthwhile to look at the next generation of Internet addressing.
Let’s take a closer look at how IPv6 differs from its predecessor, IPv4, walk through the process of enabling IPv6 on your Linux system, and configure an Apache Web server to recognize the new IP address formats.
From IPv4 to IPv6
An Internet Protocol (IP) address uniquely identifies a single device connected to the Internet. In Internet Protocol Version 4 (IPv4) an IP address is 32 bits long and is represented visually by separating the address into four octets — four groups of eight bits represented in decimal notation — separated by dots. Familiar IP addresses, such as 127.0.0.1, are based on the IPv4 specification.
Since the late 1970s, when IPv4 was designed, the number of computers connected to the Internet increased from 213 (in August 1981) to 125 million (in June 2001).
IPv6 (sometimes called “IP next generation” or IPng) has been in development since 1990 and offers several substantial improvements over IPv4. Briefly, it supports roaming between different networks (necessary for mobile devices), authentication, and encryption and compression of IP traffic. It allows devices to calculate an IP address automatically (yes, you’ll never have to manually assign IP addresses again).
Of course, IPv6 also provides a much larger set of IP addresses. In fact, when adopted, IPv6 will allow every connected device to have a unique and directly addressable IP address. Network Address Translation will be gone for good.
To provide that many unique addresses, IPv6 increases IP address size to 128 bits from 32 bits. A 128-bit IPv6 address looks like this:
3ffe:ffff:0100:0000:0000:0000:0000:0001
IPv6 switches from decimal to hexadecimal notation, uses groups of 16 bits instead of 8 bits, and uses a colon rather than a dot as a separator.
The example address shown above contains a lot of zeroes. You can drop leading zeroes in any block, so the address above simplifies to:
To further simplify things, one (and only one) sequence of blocks containing only zeroes can be dropped. Now our address looks like:
The special address any, which matches any legal address and is represented as 0.0.0.0 in IPv4, is the address 0000:0000:0000:0000:0000:0000:0000:0000 in IPv6, but is often compressed to just “::“. The IPv6 localhost address is 0000:0000:0000:0000:0000:0000:0000:0001, and it compresses to “::1“.
Netmasks and Routing
The Internet is a network of sub-networks (or subnets) where each subnet can contain (smaller) subnets and every device is connected to at least one subnet. IP addresses reflect this structure. One portion of the IP address, the netbits, identifies the sub-network a device is on. The other portion, the hostbits, identifies a specific device connected to that subnet. (Netbits are the most significant, or leftmost, bits of an IP address. Hostbits are the least significant, or rightmost, bits.) In IPv4 the netmask describes how many bits are in the netbits and hostbits portions of an address. IP addresses, the netmask, and the default router on each subnet work together to correctly process, or route, messages from one machine to another.
A typical IPv4 netmask might be 255.255.255.0 (24 netbits to identify the subnet and 8 hostbits to identify the machine). While effective, the IPv4 netmask notation is unwieldy. For IPv6, the protocol designers chose the Classless Inter-Domain Routing (CIDR) schema to specify how many bits in the Internet Protocol address to use for routing. A netmask of 255.255.255.0 becomes /24 under CIDR, while 255.0.0.0 becomes /8. The IPv4 notation for network 10.0.0.0 with a netmask of 255.0.0.0 translates to 10.0.0.0/8. (CIDR is also called the “slash” notation.)
In IPv6 the number after the slash is called the “prefix length.” An example looks like this:
The netbits or prefix is the most significant 64 bits. The remaining part of the address (64 bits, in this case) is the suffix. In IPv4 terms, the prefix represents the network part, while the suffix represents the host part. The general numbering scheme for IPv6 is described in the IPv6 HOWTO (http://linuxdoc.org/HOWTO/Linux+IPv6-HOWTO/).
IPv6 in Linux
IPv6 was first implemented in the Linux kernel in version 2.1.8 (November 1996). Development today is mostly done by the USAGI project in Japan (http://www.linux-ipv6.org/). USAGI started in October 2000 with the goal of modifying a vanilla kernel to include more IPv6-related features. Because IPv6 is still in flux, most of the work of the USAGI team is currently available only as patches for the 2.2 or 2.4 series kernels. However, some core features that are well-defined and stable are widely available.
It’s easy to see if your Linux system is able to use IPv6 networking. If you’re running a 2.2 series kernel, installed by older distributions, it’s not likely that the kernel is IPv6-enabled. It’s possible to recompile your kernel (using the USAGI patches), but that is beyond the scope of this article. You can find pointers in the HOWTO.
If you’re using a series 2.4 kernel, IPv6 is probably already included or is available as a module. To see if your current kernel supports IPv6, simply issue the command
If there’s no error, you’re set. If you don’t find this file on your system, then IPv6 support is missing. You can load the IPv6 module by running the command
as root. If no error is reported, the module is loaded. (You can check by running lsmod as root.) At this point ls /proc/ net/if_inet6 should work, too.
In theory, all network devices should be able to support IPv6; however, some are not able to transport native IPv6 packets because their transport protocol is missing a type field. Devices that cannot support IPv6 include Serial Line IP (SLIP) devices (sl*), Parallel Line IP (PLIP) devices (plip*), and some ISDN devices (isdn* using “rawip” encapsulation and all ippp* devices).
Time to Flex Your Muscles
To use the newest network features, you need the ip utility; ip replaces the ifconfig and route utilities used for IPv4. Figure One shows typical output from the ip command using the -6 option for IPv6.
Figure One: Output From ip Command
# /sbin/ip -6 addr show eth0
3: eth0: <BROADCAST,NOTRAILERS,UP> mtu 1500 qdisc pfifo_fast qlen 100
inet6 fe80::212:34ff:fe12:3456/10 scope link
|
The output of the ip command shows that your device is ready. The IPv6 address was derived from your hardware MAC address and has an address scope of link (also known as link-local). Packets from a link-local addresses cannot be sent past a router, and generally cannot be used for HTTP, telnet, and the like. Instead, link-local addresses are used for several auto-configuration features built into IPv6, such as:
- Identifying what device has a particular address on the local link and finding its hardware MAC address (this feature replaces arp from IPv4).
- Recognizing whether there is a router on the link.
Venturing Forth
Now that your device is working, how do you find an Internet Service Provider that handles native IPv6? You probably can’t — they’re still pretty rare. Fortunately, the worldwide IPv6 backbone was created with a special tunneling mechanism in place, and its testbed, the 6bone (http://www.6bone.net/), is available for you to use.
6to4 tunneling is the quickest way to connect to the worldwide IPv6 network and is also usable with ISPs that assign IPv4 addresses dynamically through PPP or DHCP. An alternative method, static tunneling, is beyond the scope of this article, but further information is available in the HOWTO.
Figure Two shows how 6to4 tunneling works. Your computer takes outgoing IPv6 packets and encapsulates them as the payload of an IPv4 packet that is sent to the special address 192.88.99.1. Because of the way the IPv4 backbone is configured, packets sent to this address are delivered to the nearest 6to4 relay. These relays have been established to decapsulate 6to4 packets and route them on the IPv6 backbone, as well as handling return trips.
Figure Two: Connect to the IPv6 Backbone

Computers A and C use 6to4 tunnels to connect to the IPv6 backbone; their addresses begin with 2002: Computer B is connected directly to the IPv6 backbone; its address begins with 3ffe:, which indicates a 6bone testbed address.
|
To accomplish this you’ll need a unique address on the IPv6 network. (You already have a link-local address, but you’ll need a global one, too.)
First you need the network prefix, which for 6to4 tunnels is 2002::/16.
Next comes the host suffix, which has the remaining 112 bits, or seven blocks of four hexadecimal digits. Within the suffix, the first two blocks are your unique global IPv4 address, represented in hexadecimal.
The following block is for your use to designate as a subnet; it is zero by default. So if your IPv4 address is 209. 81.9.15, your IPv6 network address will begin with 2002:d141:0904:0:. Finally, the last four blocks are available for you to assign within your network (everything on your side of the 6to4 tunnel). Local 6to4 gateways (your computer, in thie case) usually get the manual suffix ::1.
This results in a fully specified IPv6 address of 2002:d151:90f::1. Using this global unique IPv6 address (no other host has your IPv4 address, from which it was generated), you can connect to the IPv6 network. Three types of 6to4 connections are possible:
- From 6to4 to non-6to4 (from your computer): The packets go from your computer via IPv4 to the nearest 6to4 relay, which decapsulates the packet and sends it along the IPv6 backbone toward the destination.
- From non-6to4 to 6to4 (to your computer): The IPv6 backbone routes such packets automatically to one of the 6to4 relays, although it might not be the same one you used upstream. This relay encapsulates the packet as the payload of an IPv4 packet with your IPv4 address, which, as you’ll recall, is contained in the IPv6 address, and sends it out over the IPv4 backbone toward you.
- Between 6to4 IPv6 addresses: The packets go from your computer via the IPv4 backbone to the nearest 6to4 relay, which decapsulates them and sends them along the IPv6 backbone toward a 6to4 relay close to the destination. That relay then re-encapsulates the packet and sends it out on the IPv4 backbone toward the final destination.
To begin your connection, first create a dedicated tunnel device of type sit, which stands for Simple Internet Transition, a set of protocol mechanisms and operational guidelines designed to ease the transition of the Internet to IPv6 with as little disruption as possible. By design, a sit interface will encapsulate upstream (outgoing) IPv6 packets and decapsulate downstream (incoming) ones.
In this example you’ll call your sit device tun6to4. The command is:
# /sbin/ip tunnel add tun6to4 mode
sit ttl 64 remote any local 209.81.9.15
(Note that the remote address is any and your local address is your IPv4 address. Also note that the ip command does not use the -6 option.)
Now bring up the tun6to4 tunnel device by running:
# /sbin/ip link set dev tun6to4 up
Next, configure your local IPv6 address. We already determined the IPv6 address of our example node as 2002:d151: 90f::1. Recall that we also need to specify /16 as the prefix length because we’re assigning a 6to4 address. The command is:
# /sbin/ip -6 addr add
2002:d151:90f::1/16 dev tun6to4
You’ll want to add the default route for all global IPv6 addresses. Currently they all begin with either 2xxx: or 3xxx:. The entire group can be described with 2000::/3, which means the first three bits of the address must be 001 binary and the rest can have any value. We want to route these packets into the tunnel through the IPv4 address 192.88.99.1 of the 6to4 relays. The ip -6 command accepts IPv4 addresses through a compatibility notation, and the full command is:
# /sbin/ip -6 route add 2000::/3 via
::192.88.99.1 dev tun6to4 metric 1
If you’re running the 2.2 kernel, you also need to define how to handle the 2002: prefix. (The 2.4 kernel handles this automatically, so the following command is not needed in 2.4.) If you have a 2.2 kernel, run the command:
# /sbin/ip -6 route add 2002::/16 via
::192.88.99.1 dev tun6to4 metric 1
Let’s take a look at the state of the tun6to4 device by running the following command:
# /sbin/ip -6 addr show tun6to4
4: tun6to4@NONE: <NOARP,UP> mtu 1480 qdisc noqueue
inet6 ::209.81.9.15/128 scope global
inet6 2002:d151:90f::1/16 scope global
You can also check the configuration by examining your routing table with the command ip -6 route list table all, as shown in Figure Three . (You might notice tun6to4 is not associated with eth0. That’s okay, because the packets are going out on the eth0 interface through IPv4, and eth0 was already configured at boot time through the standard IPv4 tools.)
Figure Three: An IPv6 Routing Table
# /sbin/ip -6 route list table all
local ::1 via :: dev lo metric 0 mtu 3924 rtt 375ms
local ::209.81.9.15 via :: dev lo metric 0 mtu 3924 rtt 375ms
::/96 via :: dev tun6to4 metric 256 mtu 1480 rtt 375ms
local 2002:d151:90f::1 via :: dev lo metric 0 mtu 3924 rtt 375ms
2002::/16 via ::192.88.99.1 dev tun6to4 metric 1 mtu 1480 rtt 375ms
2002::/16 dev tun6to4 proto kernel metric 256 mtu 1480 rtt 375ms
2000::/3 via ::192.88.99.1 dev tun6to4 metric 1 mtu 1480 rtt 375ms
local fe80::2e0:98ff:fe07:c6d5 via :: dev lo metric 0 mtu 3924 rtt 375ms
local fe80::2e0:98ff:fe08:d28 via :: dev lo metric 0 mtu 3924 rtt 375ms
fe80::/10 dev eth0 proto kernel metric 256 mtu 1500 rtt 375ms
fe80::/10 dev tun6to4 proto kernel metric 256 mtu 1480 rtt 375ms
ff00::/8 dev eth0 proto kernel metric 256 mtu 1500 rtt 375ms
ff00::/8 dev tun6to4 proto kernel metric 256 mtu 1480 rtt 375ms
default dev eth0 proto kernel metric 256 mtu 1500 rtt 375ms
|
Test Your Setup
The classic ping program doesn’t work with IPv6, but a new version, ping6, does. As root, ping6 yourself:
You can ping6 other link-local IPv6 addresses, but to do so you must specify the interface. The interface name can be specified with any address by appending “%” and the interface name (for example, ping6 ff02::1%eth0).
The Domain Name System (DNS) maps host names to IP addresses. A DNS server normally returns IPv4 addresses when given a host name (this is a query for an A record). To ask the server to return IPv6 addresses, you must make a query for either an AAAA record (which is older and more established) or an A6 record (which is newer and hasn’t yet gained widespread acceptance). You can test the ability of your DNS servers to resolve IPv6 addresses by running the command:
# host -t AAAA www.6bone.net
www.6bone.net. is an alias for 6bone.net.
6bone.net. has AAAA address 3ffe:b00:c18:1::10
Figure Four shows the output of some IPv6 utilities. This includes ping6 to test IPv6 packet transmission to the 6bone, traceroute6 to see how the connection is made, and tracepath6, which gives information similar to traceroute6.
Figure Four: Ping6ing the 6bone
# ping6 -c 1 www.6bone.net
PING www.6bone.net(www.6bone.net) 56 data bytes
64 bytes from www.6bone.net: icmp_seq=0 hops=60 time=265.128 msec
— www.6bone.net ping statistics
— 1 packets transmitted, 1 packets received, 0% packet loss
# traceroute6 www.6bone.net
round-trip min/avg/max/mdev = 265.128/265.128/265.128/0.000 ms
traceroute to 6bone.net (3ffe:b00:c18:1::10) from 2002:d151:90f::1,
30 hops max, 16 byte packets
1 swi6T1-T8.ipv6.switch.ch (3ffe:2000:0:40e::22f)
252.852 ms 323.346 ms *
2 2002:823b:1ffd:3:200:cff:fe3e:a419 (2002:823b:1ffd:3:200:cff:fe3e:a419)
273.631 ms * 271.985 ms
3 3ffe:200:1:40::2 (3ffe:200:1:40::2) 255.163 ms * 254.314 ms
4 rap.ipv6.viagenie.qc.ca (3ffe:b00:c18:1:290:27ff:fe17:fc0f)
461.495 ms 463.318 ms 464.784 ms
5 www.6bone.net (3ffe:b00:c18:1::10) 471.958 ms 463.246 ms
463.704 ms
# tracepath6 www.6bone.net
1?: [LOCALHOST] pmtu 1480
1: swi6T1-T8.ipv6.switch.ch asymm 3 224.995ms
2: 2002:823b:1ffd:3:200:cff:fe3e:a419 asymm 1 370.849ms
3: 3ffe:200:1:40::2 asymm 4 395.257ms
4: rap.ipv6.viagenie.qc.ca asymm 3 617.513ms
5: www.6bone.net asymm 4 566.452ms reached
Resume: pmtu 1480 hops 5 back 4
|
If you still have problems, you can also use the packet capture program tcpdump on the outgoing eth0 interface (or better, on all interfaces you have access to) to see what’s going on. Releases of tcpdump since version 3.6 are IPv6-enabled. Figure Five some of the most useful features for debugging IPv6 problems.
Figure Five: Using tcpdump with IPv6
The following command-line options to tcpdump are very useful to capture more information about a packet:
| -s 512 | capture 512 instead of the default 68 bytes of a packet |
| -vv | really verbose output |
| -n | don’t resolve addresses to names (useful if reverse DNS isn’t working properly) |
Since tcpdump can produce a lot of spurious output, you can place filter expressions on the command line to reduce the noise. The most common ones are:
proto ipv6 | displays only tunneled IPv6-in-IPv4 traffic (as in the examples in this article) |
ip6 | displays all native IPv6 traffic including ICMPv6 |
icmp6 | displays only native ICMPv6 traffic |
not port ssh | used when running tcpdump in a remote Secure Shell (ssh) session |
|
IPv6 Clients
The current versions of many Web browsers are IPv6-enabled (Mozilla, w3m, Netscape 6, mMosaic, lynx, and Konqueror).
A good starting point for browsing is http://www.kame.net/. If the turtle on this page is animated, the connection is via IPv6; if it’s static, the connection is via IPv4 (you have to use a GUI browser for this test). Another URL for testing is http://ipv6.aerasec.de/. Near the bottom of the screen it will read, “Your connection is via: IPv6.”
Other clients already IPv6-enabled include Telnet, Secure Shell (SSH), and FTP. Most applications will recognize an IPv6 address as an argument, or if given a host name, will try to resolve it first as an IPv6 address and then fall back to IPv4 if that doesn’t work. But be careful if you are using a proxy relay, because most cannot resolve IPv6 requests. See the man pages for more information.
IPv6 Servers
We’re finally ready to look at Apache. Many server applications are already IPv6-enabled, but IPv6 is seldom switched on by default. Before you launch any IPv6-enabled services it’s always a good idea to add a static IPv6 address on the related interface. Because an IPv6-enabled interface can handle multiple addresses, you can do this easily.
For example, to add the address 2002:d151:90f::5 on eth0:
# /sbin/ip -6 addr add
2002:d151:90f::5/64 dev eth0
You can also remove existing addresses using del instead of add.
Now let’s enable IPv6 on an Apache server. You need to be running at least version 2.0.32. We’ll assume you’re using virtual hosts, because the configuration files are easier to change. You can set up two kinds of virtual hosts (see Figure Six . Note that because the port address is separated from the IP address by a colon, the IPv6 address must be placed within square brackets to separate it from the port number.
Figure Six: Configuring Apache Virtual Hosts
The first type of virtual host listens on an IPv6 address only:
Listen [2002:d151:90f::5]:80
<VirtualHost [2002:d151:90f::5]:80>
ServerName ipv6only.yourdomain.com
# … more config lines
</VirtualHost>
The second type listens on both IPv4 and IPv6:
Listen [2002:d151:90f::2]:80
Listen 1.2.3.4:80
<VirtualHost [2002:d151:90f::2]:80 1.2.3.4:80>
ServerName www4-6.yourdomain.com
# … more config lines
</VirtualHost> |
After restarting the server, you should be able to run the test in Figure Seven to confirm that Apache is working. You should now be able to test connectivity from your your IPv6-enabled browser.
Figure Seven: Testing the Apache Server
# netstat -lnptu |grep “httpd2W*$”
tcp 0 0 1.2.3.4:80 0.0.0.0:*LISTEN12345/httpd2
tcp 0 0 2002:d151:90f::5:80 :::*LISTEN12345/httpd2
tcp 0 0 2002:d151:90f::2:80 :::*LISTEN12345/httpd2 |
Looking Ahead
We’ve only scratched the surface of the brave new world of IPv6. As you move ahead, you’ll want to look at setting up a Domain Name System using BIND.
Also, if you want to set up IPv6 for all your clients on a link, you need to control only one box (the IPv6 router). After installing the Router Advertisement Daemon on it, this daemon announces information about default gateway and address prefixes to use. You can think of this as DHCP on steroids, although DHCPv6 is still a work in progress.
Like IPv6 itself, IPv6 in Linux is still incomplete. The good news is that in current distributions, basics like routing, tunneling, autoconfiguration, and client and server applications are working well. The not-so-good news is that special features and enhancements are not yet in the mainstream.
FIREWALLING
The Linux 2.4 kernel series supports IPv6 firewalling by default (it’s maintained by the Netfilter project, http://www.netfilter.org/). The implementation is a little bit behind the IPv4 version, but is already able to protect your host or LAN against unwanted IPv6 traffic. Consider firewalling as soon as possible because unlike on IPv4 networks where internal hosts can be protected automatically by using private IPv4 addresses, IPv6 offers no such protection and a bad guy can connect to your internal IPv6-enabled LAN. Sure, it’s not easy to scan the address space (with its maximum 264 addresses per link) in a short time, but commonly used suffixes like ::1 are simple to test. Security is only as strong as its weakest point.
Also, don’t just rely on an IPv4 firewall! That’s because 6to4 tunneling basically pierces an IPv4 firewall since it cannot decapsulate the packets to see if something is amiss. Check your system by running
# netstat -A inet6 -nlptu
after an IPv6-enabled restart to see which services are already using IPv6 addresses and are candidates for protection.
As of this writing, IPv6 stateless packet filtering is working well. Stateful filtering, already implemented in IPv4, is still missing in IPv6, but is on the to-do list of the Netfilter project. In commercial firewalls, IPv6 support is still very rare, but most IPv6-enabled hardware routers can already be used for filtering using their Access Control Lists.
ENCRYPTION AND AUTHENTICATION (IPSEC)
Encryption and authentication of IPv6 packets is defined in the IPsec standard, just as for IPv4. For IPv4, the FreeS/WAN project (http://www.freeswan.org/) has created patches and a related toolset for the kernel. In July 2001 the USAGI project took an IPv6 port of FreeS/WAN originally developed by the IABG project and is working on migrating it into its kernel extensions.
|
Dr. Peter Bieringer is the author of the Linux IPv6 HOWTO.
He works for a network and security consulting company near Munich, Germany, and can be reached at pb@bieringer.de.
No comments yet.