Silmor . de
Site Links:
Impressum / Publisher

IPv6 Router

The automatically configured IPv6 addresses in the fe80::* range can already be used locally. They are link local addresses, which means:

There are two ways to tell programs what link to use when using link local addresses: either an explicit parameter (like -I for ping6) or with the %-notation. In the latter case the link identifier is appended to the address with a "%" in between them. For Linux the name of the network device is used, for Windows a number is used (it is conveniently shown in the output of ipconfig).

So if I wish to ping my router (fe80::240:63ff:fede:3c19) from my Linux box (fe80::2e0:81ff:fe2e:b6d1) I can use these two commands:

# ping6 -I eth0 fe80::240:63ff:fede:3c19
# ping6 fe80::240:63ff:fede:3c19%eth0

From my Windows box it would look like:

c:\ > ping fe80::240:63ff:fede:3c19%4

Many IPv6 enabled programs support this %-notation, but not all of them, so it would be more convenient to give each network device an address that is unique at least in the local sites networks so that the operating system does not need a device ID for routing.

Local Networks

Throughout this document I'll use 2001:db8::/32 as example network, since this prefix is reserved for documentation.

If you don't have access to your own globally routable prefix yet, you can create a private network prefix as described in RFC 4193:

Under Linux the algorithm described in the RFC would look about like this in the shell:

# (ifconfig ; date +%s.%N)|sha1sum
7eb7dd5d753a0e827c3f0c4af2d36c1b275ef73a  -

since Linux already has a very high quality random source it is easier to do this:

# dd if=/dev/random bs=20 count=1 | md5sum
7eb7dd5d75f2ea4a42be3475b66d955c  -

(whether we use sha1 or md5 does not matter in this context)

Linux Router

I'll assume that a Linux based router is used here, since this is what I am familiar with. The setup for other Unix-like systems will probably be similiar. For Windows please check the MSDN - I have no clue how to configure a Windows to be a router in the first place!

In order to convert a Linux box from a simple end node into a router it must be configured to forward traffic:

echo 1 >/proc/sys/net/ipv6/conf/all/forwarding
echo 1 >/proc/sys/net/ipv6/conf/default/forwarding

You can check whether routing is enabled by simply doing "cat" on those pseudo-files:

bash$ cat /proc/sys/net/ipv6/conf/eth0/forwarding
1
bash$ cat /proc/sys/net/ipv6/conf/eth2/forwarding
0

The example above shows you that routing is enabled for packets arriving on eth0 and disabled for those on eth2.

Unfortunately this also changes autoconfiguration behaviour - while the link local fe80::* address is still automatically configured the next stage is omitted and you need to manually configure the local address. This can be done with ifconfig:

ifconfig eth0 2001:db8::1 up

Most systems have some kind of configuration where you can store the IP address, eg. Debian (/etc/network/interfaces):

auto eth0 eth1 ppp0
iface eth0 inet static
        #leave it as it already is for IPv4
iface eth0 inet6 static
        address 2001:db8::1
        netmask 64

Whether you copy the last 64 bit of the address from the devices fe80::* address or you simply set it to some low value (eg. "1"; "0" is reserved for broadcast) is your own choice.

Now you could go ahead and manually configure each host in the network and you would already be able to route.

Automagic

On the other hand for any network with more than one non-router it is easier to let them configure themselves.

This is where RAdvD comes into play, the router advertisement daemon. Any IPv6 enabled device that comes online asks the network what the current network prefix is, the radvd responds to these queries. After you installed radvd (Debian: apt-get install radvd) you need to configure it (/etc/radvd.conf):

interface eth0
{
   AdvSendAdvert on;
   prefix 2001:db8::/64 { };
};

As soon as radvd is started a simple ifdown eth0;ifup eth0 on each other computer in the network will re-initialize the network card and they will automatically configure themselves from now on. If you are the patient type, just wait a few minutes until the router has sent its automatic regular router advertisement.

The prefixes defined for each network should (almost) always be /64 masked, since the host-IDs calculated during autoconfiguration are 64 bit wide for almost all network types - certainly for all ethernet type networks. A violation of this rule results in the hosts being unable to automatically assign IP addresses - they'll just use the router information and leave address configuration to the admin or DHCP.

Debugging Routes

Sometimes the setup does not work. In this case it is good to know a few tools that can help. I will explain a few typical properties of network configurations below, the full list of commands, parameters, flags, options, etc.pp. can be found in the man-pages of "route" and "ip".

While I explain this on the example of Linux, it should not be very different on other operating systems, since the algorithms and parameters are standardized.

The "ip" utility can show you most properties of the network devices installed on the machine, for example the following command will show you all IPv6-enabled devices and their IPv6 addresses (it will show all devices and also IPv4 addresses if you leave out the -6 flag):

bash$ ip -6 addr show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qlen 1000
    inet6 2001:db8:f:1:240:63ff:fede:3c19/64 scope global
       valid_lft forever preferred_lft forever
    inet6 fe80::240:63ff:fede:3c19/64 scope link
       valid_lft forever preferred_lft forever
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qlen 1000
    inet6 2001:db8:123:2:240:63ff:fede:3bab/64 scope global
       valid_lft forever preferred_lft forever
    inet6 fe80::240:63ff:fede:3bab/64 scope link
       valid_lft forever preferred_lft forever
4: eth2: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1500 qlen 1000
    inet6 fe80::250:22ff:fe96:1b0b/64 scope link
       valid_lft forever preferred_lft forever
139: sixxs@NONE: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1280
    inet6 2001:db8:9:1::2/64 scope global
       valid_lft forever preferred_lft forever
    inet6 fe80::5dda:b209/64 scope link
       valid_lft forever preferred_lft forever
    inet6 fe80::c0a8:2b01/64 scope link
       valid_lft forever preferred_lft forever
    inet6 fe80::c0a8:2a01/64 scope link
       valid_lft forever preferred_lft forever
    inet6 fe80::c0a8:201/64 scope link
       valid_lft forever preferred_lft forever
    inet6 fe80::c0a8:101/64 scope link
       valid_lft forever preferred_lft forever

Each block above starts with the internal device ID of the network device. Device IDs do not need to be consecutive, in fact they are required to be unique while the system is not shut down. The first line of each block also contains the name of the device, some flags, the link MTU and an optional queue length.

Flags shown above:

The MTU is the maximum packet size that the device can transport. For loopback, ATM and a few other WAN types this is usually a relatively big value in the range of 16kB to 64kB. For ethernet this is typically 1500 bytes, some gigabit ethernet setups can have an MTU of 15000 bytes. Tunnels should have a MTU that approaches the MTU if the connection that carries the tunnel minus the overhead of the tunnel protocol (usually in the range of 40 to 100 bytes of overhead per packet). A MTU of 1280 bytes is the absolute minimum for IPv6. A MTU that is too high for the physical link (eg. over 1500 for ethernet or larger tunnel MTU than the underlying transport allows) will lead to sporadic loss of packets and connections. A MTU that is too small will make the link unnecessarily slow.

The queue length (qlen) is the amount of packets that the kernel can cache while waiting for the link to become free for sending them - usually you do not need to worry about this parameter.

In the table above we already see that we have five devices: lo, eth0/1/2, and sixxs. The lo device is the loopback device that should always be configured to have the IP address ::1/128, sixxs is a tunnel device (it actually tunnels over an IPv4-only PPP connection that is not seen here), eth0 and eth1 are regular ethernet segments. Eth2 only has a link-local, but no global IP address - in this case this is because it is connected to the DSL modem only - in other setups this could be a cause to worry about some missing setup.

Each block then lists the IPv6 addresses (lines starting with inet6) of the device:

The following is the IPv6 routing table of the same host:

 0| bash$ route -6 -n
 1| Kernel IPv6 routing table
 2| Destination                           Next Hop         Flag Met Ref Use If
 3| 2001:db8:9:1::/64                     ::               Un   256 0    69 sixxs
 4| 2001:db8:f:1::/64                     ::               U    256 0     0 eth0
 5| 2001:db8:123:2::/64                   ::               U    256 0     0 eth1
 6| 2001:db8:1122::/48                    2001:db8:f:1::3  UG   1   0     0 eth0
 7| fe80::/64                             ::               U    256 0     0 eth0
 8| fe80::/64                             ::               U    256 0     0 eth1
 9| fe80::/64                             ::               U    256 0     0 eth2
10| fe80::/64                             ::               Un   256 0     0 sixxs
11| ::/0                                  2001:db8:9:1::1  UG   1024 0   58 sixxs
12| ::/0                                  ::               !n   -1  1    89 lo
13| ::1/128                               ::               Un   0   1    93 lo
14| 2001:db8:9:1::/128                    ::               Un   0   1     0 lo
15| 2001:db8:9:1::2/128                   ::               Un   0   1    72 lo
16| 2001:db8:f:1::/128                    ::               Un   0   1     0 lo
17| 2001:db8:f:1:240:63ff:fede:3c19/128   ::               Un   0   1    62 lo
18| 2001:db8:123:2::/128                  ::               Un   0   1     0 lo
19| 2001:db8:123:2:240:63ff:fede:3bab/128 ::               Un   0   1     0 lo
20| fe80::/128                            ::               Un   0   1     0 lo
21| fe80::/128                            ::               Un   0   1     0 lo
22| fe80::/128                            ::               Un   0   1     0 lo
23| fe80::/128                            ::               Un   0   1     0 lo
24| fe80::5dda:b209/128                   ::               Un   0   1     0 lo
25| fe80::c0a8:101/128                    ::               Un   0   1     0 lo
26| fe80::c0a8:201/128                    ::               Un   0   1     0 lo
27| fe80::c0a8:2a01/128                   ::               Un   0   1     0 lo
28| fe80::c0a8:2b01/128                   ::               Un   0   1     0 lo
29| fe80::240:63ff:fede:3bab/128          ::               Un   0   1     0 lo
30| fe80::240:63ff:fede:3c19/128          ::               Un   0   6    81 lo
31| fe80::250:22ff:fe96:1b0b/128          ::               Un   0   1     0 lo
32| ff00::/8                              ::               U    256 0     0 eth0
33| ff00::/8                              ::               U    256 0     0 eth1
34| ff00::/8                              ::               U    256 0     0 eth2
35| ff00::/8                              ::               U    256 0     0 sixxs

This table shows the following columns:

The following flags are of importance:

The kernel makes routing decisions by matching packets against the routing entries in the table. For this it considers the entries with the highest network mask (/128) first and then works its way down to the ones with the lowest mask (/0). If the kernel is told to send the packet on a specific device then only routes of this device are considered.

Packets with link local addresses are not forwarded. Incoming packets are matched against the incoming interfaces addresses, outgoing packets must have a flag (eg. %eth0) telling the kernel where to send it - the routing table is only used to decide whether the packet remains on the same host or enters the interface. Lines 20 through 31 contain routes that tell the kernel to loop packets to these addresses back to itself (device "lo"), lines 7 through 10 contain lines allowing the kernel to send the packets onto the link. Since there are no lines allowing link local routes with a less than 64 bit netmask a packet eg. to fe80:1:2:3:4:5:6:7 would simply be dropped without sending it at all.

Multicast packets are also handled linke link local packets - if multicast is to work across routers each router on the way needs to run a multicast routing daemon that handles the specifics of multicast routing. Lines 32-35 allow multicasting on our interfaces.

Each IP address that is assigned to a local interface will also have an entry routing it to "lo" - this tells the kernel that this address is reachable locally - if the entry is missing the address is not reachable from within or outside this host. Each device has an entry with its own network so that packets targetting this network are routed to the correct device (lines 3-5). Those two types of entry are made automatically when the interface is configured and brought up - but they can be removed manually, thus disrupting the connectivity of the device.

There is an excluding entry in line 12: it tells the kernel that under no circumstance the default route can lead through the loopback device. This is less interesting for routers that have an alternative default route, but it is important for stand-alone hosts to know what to do with packets they cannot identify.

Line 11 contains this hosts default route: it tells the kernel that any packet not matching any of the other routes should be directed to the host 2001:db8:9:1::1 on the device sixxs.

Finally line 6 contains a gateway route: packets to the network 2001:db8:1122::/48 will be directed to the host 2001:db8:f:1::3 on the link eth0 (which services 2001:db8:f:1::/64 as per line 4). If this line was missing packets targetting this network would only match the default route and be sent through sixxs instead of eth0. A reason to have routes like this could be that 2001:db8:f:1::3 is the gateway of another department in the company that services several separate networks.

Examples

ping6 ::1

ping6 fe80::1111

ping6 fe80::240:63ff:fede:3c19%eth0

  1. it is a link local target, iface eth0 was requested, we consider only routes on eth0 (or loopbacks for it)
  2. it does match the /128 rule in line 30 - the packet is looped back to the local host

ping6 fe80::1111%eth0

  1. it is a link local target, iface eth0 was requested, we consider only routes on eth0
  2. it does not match the /128 rules in line 30 or 22, we keep searching
  3. it matches the /64 rule in line 7, the packet is sent on eth0

ping6 fe80:1:2:3:4:5:6:1111%eth0

  1. it is a link local target, iface eth0 was requested, we consider only routes on eth0
  2. it does not match the /128 rules in line 30 or 22, we keep searching
  3. it does not match the /64 rule in line 7, we keep searching
  4. it does not match line 3 or 32
  5. it does not match line 6
  6. there are no more lines for eth0, the packet is dropped (host unreachable)

ping6 2001:db8:f:1::1111%eth0

  1. it is a global target, but iface eth0 was requested, we consider only routes on eth0
  2. it does not match the /128 rules in line 30, 22 or 17, we keep searching
  3. it does not match line 7, but it matches the /64 rule in line 4, the packet is sent on eth0

ping6 2001:db8:f:1::1111

  1. it is a global target - we consider all routes
  2. it does not match the /128 rules
  3. ...
  4. it matches the /64 rule in line 4, the packet is sent on eth0

ping6 2002:2:3::1

  1. it is a global target - we consider all routes
  2. it does not match the /128 rules
  3. it does not match any of the /64 or /48 rules
  4. it matches the default route (line 11) and is forwarded to 2001:db8:9:1::1 on interface sixxs (it is expected that the next hop knows what to do about this packet)

ping6 2001:db8:1122:99:22:33:44:1111

  1. it is a global target - we consider all routes
  2. it does not match the /128 rules
  3. it does not match the /64 rules
  4. it matches the /48 rule in line 6, the packet is forwarded to 2001:db8:f:1::3 via link eth0 (it is expected that the next hop knows how to forward it further)

Traceroute

While checking your routing table can tell you whether this one router knows how to handle a packet and ping can tell you whether packets get all the way through to a target, the traceroute program can tell you which router on a path drops packets. It does so by first setting the hop limit of the packet to 1 (it gets dropped by the first host) and then gradually increasing the hop limit - from each router on the path it should receive a hop limit exceeded response until the packet actually reaches the target host and receives a valid response.

bash$ traceroute6 -n -I six.silmor.de
traceroute to six.silmor.de (2002:d9a0:db4b::1), 30 hops max, 40 byte packets
 1  2001:db8:9:1::1  37.323 ms  39.015 ms  40.921 ms
...
10  * * *
11  2001:db8:0:100::1:1  123.545 ms  124.294 ms  123.362 ms
12  2002:d9a0:db4b::1  127.276 ms  125.318 ms  128.002 ms

The option "-n" tells traceroute to print addresses numerically (this can speed things up significantly, esp. if there is trouble with reaching DNS servers), the -I option tells traceroute to use ICMP ping packets instead of UDP. Depending on your installed traceroute implementation it may use ICMP, UDP or TCP per default, depending on the configuration of the routers and firewalls in between any one of them may or may not work - usually ICMP is the safest bet.

(Note: the IP addresses in the traceroute output have been changed to match the example setup above. I omitted lines 2-9, since they don't add much information.)

The number left of each line is the hop limit that has been tried - each one is tried with three packets. On the first try the error message comes from the other end of the tunnel (2001:db8:9:1::/64 is the prefix of the sixxs device). Lines like number 10 show that no response was received - this can be either due to the packet being dropped or due to the router being configured to not send hop-limit-exceeded errors. In line 11 we get a response again, so line 10 was not a dropping router. Finally in line 2 we reach the target host.

Traceroute tries a maximum of 30 hops, which is the default hop limit for normal packets on most operating systems. If the last lines all contain "* * *", then it is very likely that the packets were dropped on the last router that is listed.

Links


Webmaster: webmaster AT silmor DOT de