IPv6 - Set Up An IPv6 LAN with Linux
Submitted by Mark Clarke on Sun, 04/05/2015 - 18:05 This post has been recovered from our old blog. A lot has changed since 2015.
Setting up an IPv6 LAN with Linux? Ever wondered how to do that? For years we have heard the dire predictions about the impending doom of IPv4 and the imminent arrival of IPv6. As with any eschatological prediction you either choose to ignore it and hope for the best, or you prepare for the event as best one can. So far the former strategy has served many sys admins well and proved to be an effective strategy .
If however, you have decided to gird your loins and face IPv6 head on, you probably quickly discovered, that, although there is a lot out there about the theory of IPv6, there is very little in the way of practical how tos when it comes to setting up an IPv6 LAN.
What makes understanding IPv6 troublesome is the complexity of working in a mixed environment of IPv4 and IPv6. This complexity becomes evident when one tries to connect to an external IPv6 network or the Internet which is still predominantly IPv4.
Hands-on LPI training and Linux Foundation courses
This blog posts break this down into two separate problems:
If you separate these two issues out its much easier to figure out what you need to do. Both of these steps have issues that need to be understood before the IPv6 "ah-hah" moment. Once that happens you will also have the "oh no" moment which might help you understand why there is such slow movement on IPv6 adoption. In the first part we will configure an Ubuntu 14.10 server to manage an IPv6 LAN. In the 2nd part we will deal with the myriad of options to connect an IPv6 network to the internet.
First we need to cover some theory on IPv6 addresses. There is a lot of article covering IPv6 addressing on the web, so I will just summarize what you need to know to proceed with setting up an IPv6 network. There are some nuances and subtleties we will brush over to provide you with a working conceptual model.
Sometime you will see an addresses listed with a prefix such as /48 or /56 etc. This does not mean that 16 (64-48) or 8 (64-56) bits of the 64 network prefix has been reserved for use by hosts as with IPv4 CIDR. The network address is always 64 bits long. This notation refers to a block of networks. i.e all networks that begin with the first 48 or 56 bits set as specified. This is known as a routing prefix and is used in routing rules, resulting in smaller routing tables. It is also used for when you are assigned a block of IPv6 networks.
The idea with IPv6 is that you should be assigned a block of networks by your ISP or IANA instead of a single host address or single IPv4 network as currently happens with IPv4.
The remaining bits of the network prefix 16 (64-48) or 8 (64-56) are called the subnet id. So the routing prefix + subnet id make up the network prefix of an IPv6 address. Dont' be confused by the use of the word subnet in subnet id.It is not an IPv4 subnet mask. It is simple the part of the network prefix you get to assign yourself as the administrator of that block of network addresses. So if you get an IPv6 address block with a 56 bit routing prefix it means you can have 255 (28) networks each with 1.844674407×10¹⁹ (264) hosts!. Its up to you to determine how the subnet portion is used to create the network address. So if you are given a block of IPv6 network such as fdc8:282a:f54c::/48 it means you can have 216 networks. Your networks addresses are :
We wil come to the host identifier portion later later. The IPv6 network address space has been "sliced up" into different blocks. What you need to know about these blocks is given below: (each address block is explained further later)
For more information on the address blocks see the IANA site
We will set up an IPv6 network incrementally. We will start with the simplest and most trivial IPv6 and add services as we go. This will help us arrive at a understanding of how the various services fit together. We will go from the simplest IPv6 network to one which has all the basic network services required of a business network.
To setup the simplest IPv6 network you just have to boot up a host or two with a IPv6 enabled operating system such as Ubuntu. Open a terminal and type:
"ip -6 address list"
You should see output similar to the following:
1: lo: mtu 65536 inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: eth0: mtu 1500 qlen 1000 inet6 fe80::922b:34ff:fe7b:6ff1/64 scope link valid_lft forever preferred_lft forever,multicast,up,lower_up>,up,lower_up>
IPv6 link local addresses have been assigned automatically to any interfaces that you have. The IPv6 localhost address (IPv4 127.0.0.1) is ::1/128. You can do the same on another host to gets it IPv6 link local address and then do a IPv6 ping with "ping6" - note the 6.
ping6 fe80::922b:34ff:fe7b:6ff1
The fe80::/64 network prefix is the link local network as explained in the table above. It should be the only IPv6 network address you will see across different physical networks. In fact every host on an IPv6 network must have an link local address (fe80::/64).
The host identifier portion of the link local address, the remaining 64 bits, is generated from the mac address with a algorithm applied to extend the 48 bit mac address to the 64 bit host address required for IPv6. See EUI64 for the algorithm used. The host identifier may also be manually assigned by the system administrator. This introduces the risk of duplicate IP addresses being assigned, so IPv6 has a duplicate address detection protocol that allows hosts to determine if there is a conflict before assigning itself an address.
In most cases you will let this be automatically generated. In IPv4 initially IP address had to be manually assigned or assigned via a DHCP server. Later the 169.254/16 address range was reserved for auto-configuration in IPv4 network. Unlike IPv4 your interfaces will always have an fe80::64 address, it is not used instead of a valid IPv6 address. In IPv6 your interfaces will typically have multiple IP addresses.
IPv6 configuration is done using layer 3 (network layer) protocols and not layer 2 (media layer eg. Ethernet) as with IPv4; so a valid IPv6 address is required before any additional configuration can be done. Of couese it also allows for zero config simple networks.
With a link local address you can communicate with other IPv6 hosts on the local network segment or broadcast domain. i.e the same switch or shared media network. So for a home LAN not connected to the internet this is all that is required. You can connect to your printer, Smart TV, PlayStation etc automatically using protocols such as UPnP and multicast DNS (ZeroConf). Connecting to the internet, or a network in a different physical network or logical network, will require a bit more work.
If this all there was too it then we could all go home. But if you start to think about it you will begin to have some doubts as to how useful a link local only IPv6 network is.
To address these issues you need to assign yourself a non-site local address. This can be a unique local address (ula) or a global address. For a global address you will need to get an IPv6 network block from your ISP or get one assigned to you by IANA. So we will make use of a ULA address which you can assign yourself.
By convention a ULA is not routed over the public internet. Routers on the public IPv6 network should refuse to route such traffic in a similar manner to private IPv4 addresses. Essentially there should be no routing entries in the routers responsible for internet traffic, making them unreachable from outside an organisation.
If you are going to start experimenting with IPv6 there are two reasons to use a ULA
One feature of unique local addresses is that they should be different for every network you see. Unlike IPv4 where private addresses (196.128/16, 10/8 and 172.16/16) meant there are often networks with the same network mask - eg nearly every home and office has a network with the network mask of 192.168.1.0/24 address or 10.0.0.0/24 range; you might never see a duplicate IPv6 ULA network address. This is because only the first 8 bits of the network prefix are fixed at "fd". The remaining 56 bits of the netowrk prefix, the subnet id, can be randomly selected. System administrators are meant to create the subnet id themselves. A handy way to generate the subnet id for the ULA is to use a site like unique-local-ipv6.com. From here you will get a /48 address range meaning you can have up to 65356 private networks!
Its generally a good idea to use a random subnet id rather than generate one like fd01:1:1:1::0/64 as this increase your chance of a conflict. Why would you be worried about a conflict if these are not routable? Have you ever had to merge two network that had the same IPv4 address range? Have you ever tried to setup a VPN between two network with the same IP network range?
Global address will be assigned to you by an ISP unless you get your own block and tell your ISP to route it to you. So much like you get a public IP address from your ISP for IPv4 you will in future, get an IPv6 network address range when you dial up. Note: not a single IP address but a whole block of IPv6 addresses. Depending on your ISP you may get only one network or be assigned a block with multiple networks. In this case the router will received the network address prefix to use on your network. It will work the same as for the steps below except instead of a ULA network it will be a global address. Note you don't get assigned a full IPv6 address. You get the network prefix. So to summarise. You will need at least two IPv6 addresses for each interface if you want to do normal networkng tasks like route between network. A link local which is always present and at least one ULA or global address or perhaps all three!
For our exercise we will use ULA addresses to setup an IPv6 only LAN.
Note:You can setup the following IPv6 network on a network that is already configured for IPv4. You can run IPv6 in parallel with IPv4. This is known as a dual stack setup. Once done you can stop the IPv4 services and run the network on IPv6 only or keep it dual stack. One reason to test without IPv4 infrastructure running is to convince yourself that your network really is working over IPv6.
Ok, now things start to get a bit more complicated. First we need some more theory :( We have already seen how a link local address is assigned. But how is the ULA address assigned? The nodes will need some way to get the network prefix? For this IPv6 makes use of a router advertisement service that runs on the local network router. This is what they mean when they say SLAAC (Stateless Automatic Address Configuration) configuration. The process is as follows:
So a node now has an ULA IPv6 address and a default gateway and all should be good. This is known as stateless address assignment. The router does not assign an address per se. It has no idea what IPv6 address the hosts ends up using, only that it is in the provided network. Hence the stateless in the term stateless automatic address configuration (SLAAC).
The advertisement service can run on any Linux box, but that box will become the default route for IPv6 traffic. In future your ADSL router will provide router advertisement services. First assign the Linux box a static IPv6 address from the ULA network: (In the examples that follow I use the fd5f:12c9:2201::/48 ULA routing prefix and I have chosen fd5f:12c9:2201:1::/64 as the network prefix. (ie :1 is the subnet id).
Configure a static IPv6 on Ubuntu
sudo vi /etc/network/interfaces
auto eth0 iface eth0 inet6 static address fd5d:12c9:2201:1::1 netmask 64 autoconf 0 dad-attempts 0 accept_ra 0
Now we need to install the router advertisement service:
Router Advertisement Daemon Configuration
sudo apt-get install radvd
vi /etc/radvd.conf
interface eth0 { AdvSendAdvert on; prefix fd5d:12c9:2201:1::1/64 { AdvOnLink on; AdvAutonomous on; }; #Send DNS Server setting - assumes there is a DNS server setup at the address below RDNSS fd5d:12c9:2201:1::2{ }; };
Restart the service and then on a client restart the network. You should see two IPv6 address on your network card.
ip -6 address list
You can ping the router with the ping6 utility:
"ping6 fd5d:12c9:2201:1::1" if this doesn't work try "ping6 fd5d:12c9:2201:1::1 -I eth0" -> Use the interface with the assigned IPv6 address. We will cover DNS and IPv6 in the net section.
Congratulations you have an IPv6 network up and running! If your router is multi honed and has two interfaces with IPv6 addresses you will be able to route between the two networks. You will need to setup two static IPv6 addresses in /etc/network/interfaces.
After the initial excitement of getting a routable IPv6 network up and running you start to realise you need a few more services:
Sadly the router advertisement service can only provide a network prefix, default route and dns server address and not much else. To provide the required service we need to use a DHCP server. To get the node to use a DHCP server we need to configure the radvd service to tell nodes to contact a DHCP server for additional configuration information.
You can configure radvd to tell the nodes to contact the DHCP server for
So a DHCP server can be used in a stateless and stateful IPv6 setup. We will use DHCP to send configuration information such as DNS servers and to assign IP addresses since we want to assign fixed IP to well known hosts.
Edit the /etc/radvd.conf file
interface eth0 { AdvSendAdvert on; prefix fd5d:12c9:2201:1::1/64 { AdvOnLink on; AdvAutonomous on; AdvManagedFlag on; # get a full IP address from the DHCP server AdvOtherConfigFlag on; # get other configuration info from the DHCP server }; };
Setting up DHCP6 is similar to DHCP for IPv4. We will use the isc-dhcpd-server:
"sudo apt-get install isc-dhcp-server"
Edit the /etc/dhcpd/dhcpd6.conf: (note comments removed for clarity)
ddns-update-style interim; ddns-updates on; update-conflict-detection false; update-optimization false; option domain-name "jumpingbean.co.za"; option dhcp6.name-servers fd5d:12c9:2201:1::2; default-lease-time 600; max-lease-time 7200; include "/etc/dhcp/rndc.key"; log-facility local7; zone jumpingbean.co.za. { primary 127.0.0.1; key rndc-key; } zone 1.0.0.0.1.0.2.2.c.9.2.1.d.5.d.f { primary 127.0.0.1; key rndc-key; } subnet6 fd5d:12c9:2201:1::/64 { range6 fd5d:12c9:2201:1::100 fd5d:12c9:2201:1::200; }
A lot of the configuration for DHCPv6 is the same as DHCPv4 and I am assuming you are familiar with the configuraiton of DHCPv4 for dynamic DNS updates. Here we set up the DHCP server to
Note: To setup a fixed IPv6 address in DHCPv6 you make use of a DUID (Device Unique ID) which is not the mac address which is used for IPv4 DHCP. The DUID is assigned by the operating system and remains the same even if network cards change. The complete unique id is made up of the DUID and an IAID (interface assigned id) as you may have more than one interface on a node requesting IP addresses from the DHCP server. I.E Each interface has a unique ID.
Below is an example of a fixed assignment
host example { host-identifier option dhcp6.client-id 31:30:30:30:30:31:33; fixed-address6 fd5d:12c9:2201:1::101; }
I am not aware of a way to get the DUID and IAD of a interface on a node in Linux. You can look in the leases file on the DHCP server once an address is assigned but this is no ideal. A binary copy of the node's DUID can be found at /var/lib/dhcpv6/dhcp6s_duid but it cannot be simple cat'ed to stdout. If anyone knows how to read the unique id for an interface on a node please let the internet know :)
Before moving on to configuring the name server there are some issues to note about the DHCP server.
sudo update-rc.d dhcpd disable
dhcpd -6 -cf /etc/dhcp/dhcpd6.conf -lf /var/lib/dhcp/dhcpd6.leases eth0
If you going to run dual stack you will nee to add this for the IPv4 mode of the DHCP server
dhcpd -4 -cf /etc/dhcp/dhcpd4.conf -lf /var/lib/dhcp/dhcpd4.leases eth0
You might also have apparmour prevent writing to the lease file if you try and write it to a different location. You can either stop apparmor or configure the dhcp server to write the lease file to location that its profile supports writing to.
First you will need to install bind9. DNS differs from DHCP in that only one instance of the DNS server needs to be running to service both IPv4 and IPv6 requests. It simple need to bind to both IPv4 and IPv6 addresses. A DNS server will provide answers to queries for an IPv4 or IPv6 address no matter what the source address of the query. i.e it doesn't look at whether the query came from an IPv4 or IPv6 address it just looks at what it was asked to lookup - the record type.
Next we need to edit the bind configuration to setup our zones and tell bind to listen on IPv6 or IPv6 and IPv4 interfaces. Most of this is standard bind9 setup as for IPv4. The only real change at this point is the AAAA records in the zone file and the awful reverse zone name that is a mission to type without making a mistake.
/etc/bind/named.conf.options
options { directory "/var/cache/bind"; forwarders { 8.8.8.8; }; dnssec-validation auto; auth-nxdomain no; # conform to RFC1035 listen-on-v6 { any; }; };
/etc/named/named.conf.local
zone "jumpingbean.co.za" { type master; allow-update { key rndc-key; }; file "/var/lib/bind/jumpingbean.co.za"; }; zone "1.0.0.0.1.0.2.2.9.c.2.1.d.5.d.f.ip6.arpa" { type master; file "/var/lib/bind/fd5d:129c:2201:1"; allow-update { key rndc-key; }; };
The zone files below already contain some dynamically updated IPv6 address from the DHCP server. Those are the ones annotated with the TXT entries. You will only make entries for the static IPv6 addresses and let DHCP handle the dynamic address entries.
Zone files
/var/lib/bind/jumpingbean.co.za
$ORIGIN . $TTL 604800 ; 1 week jumpingbean.co.za IN SOA ns.jumpingbean.co.za. no.jumpingbean.co.za. ( 182 ; serial 604800 ; refresh (1 week) 86400 ; retry (1 day) 2419200 ; expire (4 weeks) 604800 ; minimum (1 week) ) NS ns.jumpingbean.co.za. A 127.0.0.1 AAAA ::1 $TTL 300 ; 5 minutes android-a74e95670198fd6a A 10.0.10.4 TXT "0002ec64161ce51591018b9eb0a01ae6b9" $TTL 604800 ; 1 week gateway AAAA fd5d:12c9:2201:1::2 ns AAAA fd5d:12c9:2201:1::2 $TTL 300 ; 5 minutes trinity A 10.0.10.3 $TTL 187 ; 3 minutes 7 seconds TXT "025c83d7b0b5ca62d26381f057fbeed483"
/var/lib/bind/fd5d:129c:2201:1
$ORIGIN . $TTL 604800 ; 1 week jumpingbean.co.za IN SOA jumpingbean.co.za. no.jumpingbean.co.za. ( 182 ; serial 604800 ; refresh (1 week) 86400 ; retry (1 day) 2419200 ; expire (4 weeks) 604800 ; minimum (1 week) ) NS ns.jumpingbean.co.za. A 127.0.0.1 AAAA ::1 $ORIGIN jumpingbean.co.za. $TTL 300 ; 5 minutes android-a74e95670198fd6a A 10.0.10.4 TXT "0002ec64161ce51591018b9eb0a01ae6b9" $TTL 604800 ; 1 week gateway AAAA fd5d:12c9:2201:1::2 ns AAAA fd5d:12c9:2201:1::2 $TTL 300 ; 5 minutes trinity A 10.0.10.3 $TTL 187 ; 3 minutes 7 seconds TXT "025c83d7b0b5ca62d26381f057fbeed483"
Now we have a fully functional IPv6 LAN. You may have IPv4 running at the same time and a interface can have a IPv4 and IPv6 address. To test DNS try the following (you can try it on public DNS servers too)
dig @DNS-IP www.google.com A
dig @DNS-IP www.google.com AAAA
You can query the local DNS server you just setup as well for an address you assigned.
So now you have a fully functioning IPv6 network. You can disable the IPv4 network and see that you can still reach all machines and services. On the client side you will not have to do any explicit configuration changes. Everything will be fine until you try and access the internet. The following will fail:
"ping6 www.google.com"
"ping www.google.com"
The first ping to google IPv6 address will fail unless you have global address. If you have an fd00::/7 address you won't get a response. The second will fail because you are trying to access an IPv4 host from an IPv6 network. And this leads to the second issue we need to deal with to understand IPv6.
This is the most troublesome part of the IPv6 protocol. There are a myriad of "transition mechanism" designed to ease the transition form IPv4 to IPv6. None of them are ideal as far as I can tell and most have requirements which place them outside of the reach of small and medium businesses until IPv6 becomes more widespread.
At the time of writing this article the most common occurrence is for an ISP to assign a single IPv4 address to your router. As IPv6 becomes more widely adopted this will change and the step below may not be that relevant. The issue is that IPv6 services cannot be access via an IPv4 address and IPv4 services cannot be natively connected from an IPv6 only host. We are going to look at two solutions:
For the sake of simplicity we will assume an IPv4 address on the router. The advantage of NAT64 is that you can use IPv6 internally and still use your ISP public IPv4 address. Another advatnage is you can keep using your IPTables IPv4 firewall rules. The disadvantage is that you will only need to connect to IPv4 hosts on the internet. So it kind of defeats the purpose of setting up an IPv6 network other than to experiment with its features.
NAT64 protocol nats all outgoing IPv6 addresses to a pool of IPv4 addresses and then routes the request to the ISP. This means there will be double natting. Once for NAT64 and then again for your router to the ISP. To setup NAT64 install tayga.
"sudo apt-get install tagya"
edit /etc/tagya.conf
tun-device nat64 # the interface to create to perform the natting ipv4-addr 192.168.255.1 # the ipv4 address for the tayg interface from the pool below. ipv6-addr fd5d:12c9:2201:1::3 # the IPv6 address to assign to the tun-device nat64 above prefix fd5d:12c9:2201:1:1:1::/96 # see explanation below dynamic-pool 192.168.255.0/24 # the pool of IPv4 addresses to assign to each IPv6 address data-dir /var/spool/tayga
So NAT64 creates a interface to listen on. The interface gets an IPv6 and IPv4 address. Any request from an IPv6 source for an IPv4 address will get routed to the nat64 interface. To do this we need to add a route for IPv6 addresses:
"sudo ip route add fd5d:12c9:2201:1:1:1::/96 dev nat64"
All that remains is to explain where the network prefix d5d:12c9:2201:1:1:1::/96 used above and in tagya.conf file come from. This is a network from your ULA block which you set aside for IPv4 to IPv6 address translation. You need to configure the bind DNS server to automatically convert any IPv4 addresses to IPv6 using the prefix above. This way you won't get an error when you try and ping an IPv4 host from an IPv6 address.
/etc/bind/named.conf.options file and add the items in bold below:
options { directory "/var/cache/bind"; forwarders { 8.8.8.8; }; dns64 fd5d:12c9:2201:1:1:1::/96 { clients { any; }; exclude { any; }; }; dnssec-validation auto; auth-nxdomain no; # conform to RFC1035 listen-on-v6 { any; }; };
At this point your IPv6 network can live happily in a sea of public IPv4 addresses. Unfortunately you won't be able to access an IPv6 host with a global address just yet :(
Alternatively you can keep a dual stack and then setup a IPv6 tunnel at one of the well known tunnel brokers such as Hurricane Electric or setup a Teredo tunnel. Both have draw backs. The Hurricane Electric service requires you to setup a SIT tunnel to one of their points-of-presence. This requires a static IPv4 address or you will need to constantly update the configuration on their site when your ip changes. A Teredo tunnel requires a IPv6 address.
The advantages of a SIT tunnel is that you get a routable global IPv6 address at the POP and you can access IPv6 nodes natively. The disadvantage is your traffic needs to be proxied or tunneled over the IPv4 internet increasing latency. If you get a SIT tunnel you only have one global IP address for the host the tunnel is created on so you will need to setup a tunnel per node or have an IPv4 network and nat it through the SIT tunnel.
One point to bear in mind when using IPv6 is that it will bypass all your IPv4 security measures. If you have an IPTables ruleset for IPv4 you will need to re-implement that for IPv6 with IP6tables. There is no natting in IP6tables currently. One thing to remember, if you in a co-location data centre and geting IPv6 auto-generated link-local addresses, any machine in the same centre can connect to your server via IPv6, potentially by passing any IPv4 ruleset you have setup! Some data-cenre might be assigning you global ipv6 addresses without you knowing! So check your co-location servers and make sure you don't have any back-doors due to mis-configuration. At least one data centre we have server at had helpfully given us an gobal IPv6.
The transition mechanisms are a mess. One just has to look at the acronym soup on Wikipedia transition mechanism page dealing with the myriad of ways to inter operate between IPv4 and IPv6. We have only tried two! We are still experimenting with the tunneling mechanisms above to see if they work properly as they promise the most benefits, being able to reach servers in different locations over the public internet with routable IPv6 addresses. So far we have met with limited success. No doubt we got to learn a bit more. But this also points to the biggest reason IPv6 is not being adopted. There is no real way for the two protocols to inter operate. A painful time will come when 50% of the world is on IPv6 and the rest on IPv4.
At least you can get some experience setting up internal IPv6 networks in the meantime.