Preventing IPv6 Leakage
In our experiments, we will use global IPv6 addresses from the range designated for Internet use. Today, since providers do not support or issue IPv6 addresses to their customers, such experiments should not cause any issues. However, just in case, block IPv6 packets from leaving your router. If your router runs Linux, you can block all IPv6 traffic using the following commands:
1
2
3
# ip6tables -P OUTPUT DROP
# ip6tables -p INPUT DROP
# ip6tables -p FORWARD DROP
Assigning Global IPv6 Addresses
The link-local addresses we used in the first article are quite limited in application. In real life, we will need global unicast addresses. Addresses from the 2000::/3 range are such addresses. Curious readers may know that addresses from the 2001:0DB8::/32 range are intended for experimental use, so we will use those. Let's assign a real IPv6 address to the network interface eth0:
1
# ip -6 addr add 2001:0db8::1/64 dev eth0
Note: /64 is not CIDR notation; it indicates the number of prefix bits. The following diagram will help clarify this:
1
2
3
2001:db8:0000:0000:0000:0000:0000:0001
_____________|____|___________________
Network ID Subnet Interface ID
The Network ID is determined by the provider when issuing a block of IPv6 addresses. You can manage the Subnet and Interface ID values. Thus, in our case, 64 bits are allocated for Network ID + Subnet, and 64 bits for the Interface ID. Recall that in IPv4, a total of 32 bits were allocated for an address, so a block of this size will last you a very long time!
You can now ping the interface within the local system using its assigned IPv6 address. Here, I am entering the full-format long IPv6 address only as an example, so you can see how the ping6 program automatically shortens it:
1
2
3
$ ping6 2001:db8:0:0:0:0:0:1
PING 2001:db8:0:0:0:0:0:1(2001:db8::1) 56 data bytes
64 bytes from 2001:db8::1: icmp_seq=1 ttl=64 time=0.043 ms
However, pinging from another host will not work, as, just like with IPv4, we will need a router for this.
Adding Addresses
You can add as many addresses as you want to your system's interfaces. Simply count in hexadecimal order: 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f, 10, 11, and so on, thereby obtaining new addresses:
1
2
3
4
5
6
7
8
2001:db8::1
2001:db8::2
2001:db8::3
...
2001:db8::18
2001:db8::19
2001:db8::1a
2001:db8::1b
Routing
Obviously, your router must support IPv6. If your router is a Linux system, you can enable routing with the following command:
1
# sysctl -w net.ipv6.conf.all.forwarding=1
To check if IPv6 routing is enabled, use the command:
1
2
# cat /proc/sys/net/ipv6/conf/eth0/forwarding
1
A value of "1" means everything is fine and IPv6 routing is enabled on your device. Now, install radvd (router advertisement daemon) and place the following in its configuration file /etc/radvd.conf, changing the interface name eth0 if necessary:
1
2
3
4
5
6
7
interface eth0
{
AdvSendAdvert on;
prefix 2001:db8::/64
{
};
};
Now add an IPv6 address to your router's interface:
1
# ip address add 2001:db8::1a/64 dev eth0
Check that everything is set up correctly using the following commands:
1
2
3
$ ifconfig eth0 | grep inet6
inet6 addr: 2001:db8::1a/64 Scope:Global
inet6 addr: fe80::20e:2eff:feb9:cbad/64 Scope:Link
1
2
3
$ ip -6 route show
2001:db8::/64 dev eth0 metric 1024 mtu 1500 advmss 1440 hoplimit 0
fe80::/64 dev eth0 proto kernel metric 256 mtu 1500 advmss 1440 hoplimit 0
And now you can start radvd:
1
# /etc/init.d/radvd start
You should now be able to ping your router's interface without any issues. Note that for global addresses, unlike link-local addresses, you do not need to specify the interface name:
1
2
3
$ ping6 2001:0db8::1a
PING 2001:db8::1a(2001:db8::1a) 56 data bytes
64 bytes from 2001:db8::1a: icmp_seq=1 ttl=64 time=1.73 ms
All computers connected to the same switch as the router should now automatically obtain addresses from the 2001:0db8::/64 range. To add the router as the default gateway in your hosts' routing tables, use the following command:
1
# ip -6 route add default via 2001:db8::1a
You can avoid manually adding this entry to the hosts' routing tables by slightly extending your radvd configuration:
1
2
3
4
5
6
7
8
9
10
11
12
13
interface eth0
{
AdvSendAdvert on;
prefix 2001:db8::/64
{
AdvOnLink on;
AdvAutonomous on;
};
route ::/0
{
};
}
Now, in the IPv6 routing tables of your hosts, you will see the following:
1
2
3
4
$ ip -6 route show
...
default via 2001:db8::1a dev eth0 metric 1024 mtu 1500 advmss 1440 hoplimit 0
...
What if you don't want radvd to distribute IPv6 addresses to everyone in your network? List the link-local addresses of the stations you want to assign addresses to in the daemon's configuration file, and requests from others will simply be ignored:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
interface eth0
{
AdvSendAdvert on;
prefix 2001:db8::/64
{
AdvOnLink on;
AdvAutonomous on;
};
route ::/0
{
};
clients
{
fe80::20d:b9ff:fe05:25b4;
fe80::20b:6aff:feef:7e8d;
fe80::221:97ff:feed:ef01;
};
};
IPv6 Address Calculator
Understanding binary arithmetic is crucial for grasping IP addressing principles. Manual address calculations can be quite tedious and often lead to errors. Why not let the computer handle these calculations? There are many online utilities available for this purpose; choose whichever you prefer! Additionally, most distributions include the ipv6calc utility in their repositories, which is useful for local use.
Name Services
Generally, configuring DNS for IPv6 is a topic for a fairly lengthy article, but I hope that some of the points described here will give you the right direction.
The idea behind the autoconfiguration of IPv6 network interfaces (link-local addresses and router advertisements) is to eliminate the need to maintain a DHCP server; however, you still need to run a DNS server so that hosts can perform name-to-IP and IP-to-name resolution. BIND9 already supports IPv6, but as is always the case with BIND, you will have to put in some effort by editing several configuration files located in different places. Other DNS daemons would require less effort from you, but none of them fully supports IPv6 yet. If you are interested in configuring IPv6 in BIND, you can refer to the BIND manual.
In the previous article, we considered the option of using the old-fashioned /etc/hosts. Alternatively, you can use Dnsmasq, which is my favorite tool for organizing DNS in local networks. It supports IPv6 DNS and TFTP, but it lacks DHCP, which prevents it from being a universal solution. Dnsmasq makes the contents of /etc/hosts available over the network using the DNS protocol. First, configure the IPv6 interfaces of your hosts to use static addresses, then place the address-to-name mappings in the /etc/hosts file of your Dnsmasq server and restart the Dnsmasq daemon. Next, install rdnssd (recursive DNS server discovery daemon) on the same host where you have radvd installed, and then add a line to the /etc/radvd.conf configuration file specifying the address of your Dnsmasq server:
1
RDNSS 2001:0db8::1b
Restart radvd. The radvd and rdnssd projects are still under development, so you may encounter some issues, although they work perfectly on my Debian systems.
