My Linux server IPv6 deployment approach

I previously discussed the ease of deploying IPv6 for Linux servers. Whether it is Debian, Fedora or another distribution the IPv6 stack should "just work" these days. However, for maintaining a production network with minimum risk of interruption, there are a few extra things to be aware of during IPv6 deployment.

Here I present a rough set of steps that can be followed, usually with minimal or no downtime, to deploy IPv6. The steps are in the order that they should be used in practice

Plenty of other web sites already explain the theory of IPv6 networks or practical configuration detail (like how to set a static IPv6 address in Debian). This page ignores all of that detail and looks at the overall project strategy.

Borrow the last decimal octet (or host bits) of IPv4 addresses

As mentioned in my earlier blog:

  • Of the 128 bits in IPv6 addresses, most sites now use a fixed 64 bit netmask for all their subnets. This is the practice encouraged by RFC 4291.
  • Therefore, there are always more bits in the 64-bit "host" portion of the address than in the host portion of any 32-bit IPv4 address.
  • Consequently, it is possible to just borrow the host portion (typically the last octet for a class-C network) and use it as the host portion of an IPv6 address
IPv4 address Host portion of address IPv6 address
192.168.1.5/24 5 2001:1234:567::5

Gotcha: remember that the IPv4 addresses are usually written in decimal while IPv6 addresses, including the example above, are hex. This doesn't really matter in practice unless the addresses are being manipulated by code that is sensitive to the host bits. For all other intents and purposes, it just makes it easy to read the addresses and associate them with IPv4.

A completely valid alternative is to use the full IPv4 address as the host portion of the IPv6 address. For example, if the IPv4 address = 192.168.1.5, the IPv6 address may be 2001:1234:567::192.168.1.5. This approach is slighly more verbose and is completely valid. Which approach you use is at your discretion.

Create reverse mappings (PTR records) in DNS

Just as IPv4 has the in-addr.arpa zone and telephone numbers have the e164.arpa zone (for ENUM), IPv6 addresses have a reverse mapping zone too: ip6.arpa

The recommended way to proceed is to create reverse mappings for all hosts that have IPv4 reverse mappings.

Some services may be using reverse lookups for authentication (e.g. MySQL will check this for any user who has a "Host" restriction defined). This is why it is recommended to create all the reverse mappings very early in the IPv6 program, before any hosts start making connections over IPv6.

Create extra A records in DNS

It's possible that some applications will be more stubborn about IPv6 adoption than others.

For example, if you have a host called wolf.example.org and it hosts a mail server, web server, DNS server and XMPP server all using the name wolf then all those server processes will have to support IPv6 connectivity from the moment you add an AAAA record.

A good practice is to create independent DNS A records (such as ns1.example.org and mail.example.org) for each application (not just CNAME records). Existing CNAME records can be converted to A records and converted back to CNAME records after the IPv6 deployment is 100% complete.

Duplicate firewall entries

Duplicate all IPv4 firewall entries to create an IPv6 firewall

For many types of network, this is a trivial (although possibly tedious) task. There are some small gotchas:

  • There is no NAT. Any firewall entries for NAT need to be reviewed: for source NAT, it is necessary to use a mechanism like connection tracking to protect workstations that previously had asymmetrical access to the public Internet. For destination NAT, see the TPROXY feature in ip6tables
  • IPsec works slightly differently. Rules for AH and ESP packets can't simply be duplicated for IPv6, they need further tweaks or warnings will be generated.
  • IPv6 makes some ICMP packages mandatory. If IPv4 ICMP is completely blocked, you still need to enable the IPv6 ICMP (or at least the subset of ICMP packets that are mandatory).

For more comments about firewalling IPv6, please see my earlier blog on the subject

Put the IPv6 addresses on the hosts

Add the necessary records to the appropriate place, for example, the /etc/network/interfaces files on Debian/Ubuntu style systems.

For hosts that have multiple addresses on a single interface, it is often desirable to ensure that outbound connections always appear to come from just one of the addresses. This can be achieved using the preferred_lft option when configuring the non-default addresses.

For example, if configuring three addresses on eth0:

ip addr add dev eth0 preferred_lft 0 2001:1234:567::10/64
ip addr add dev eth0  2001:1234:567::11/64
ip addr add dev eth0 preferred_lft 0 2001:1234:567::12/64

In the example above, all outgoing IPv6 connections will appear to come from 2001:1234:567::11/64

Important: this is only a very shallow discussion of the issues around source addresses. If it doesn't provide a valid solution for you, there are many dedicated articles about this specific topic, madduck's blog looks at it for firewalls and tunnels but the concepts are valid for any type of multi-homed host

Review listening processes with netstat

Now that hosts have IPv6 addresses, it is worthwhile looking through the output of

netstat -nlp

to see which processes have bound to both IPv4 and IPv6 addresses and which processes remain stuck on IPv4 only.

For processes that are only listening on IPv4 or only bound to a specific address (rather than 0.0.0.0), it is a good idea to investigate the way they are configured and find out if they will support IPv6.

Review the monitoring infrastructure (Nagios, Ganglia, etc)

Now is a good time to review the monitoring infrastructure.

Make sure that tools like Nagios are testing the services using their dedicated DNS names and not the host names.

For example, if the host wolf.example.org runs an LDAP server accessible as ldap1.example.org, make sure Nagios is configured to poll ldap1.example.org.

Look at the check_v46 wrapper for Nagios and similar solutions to make sure that Nagios is testing both the IPv4 and IPv6 version of each service.

Just as developers use unit testing as part of test-driven development workflows, administrators deploying IPv6 can use the monitoring framework to validate the progress of their IPv6 program.

Check for ACLs

Do any server processes use IP-based ACLs to control access?

For example, an Apache web server may be using an IP ACL to restrict access to some pages. MySQL or Postgres databases may have IP ACLs defined for some users or databases.

When hosts start using IPv6 to connect to services, their IPv6 source addresses won't pass the ACL and services may be inaccessible. Therefore, it is worthwhile checking for such ACLs early on.

Prepare DNS servers first

Preparing the DNS servers first is a good step. The DNS servers should be configured to accept queries over IPv6.

Once the DNS servers are listening on IPv6 addresses, go ahead and do some of the following:

  • Insert IPv6 AAAA records for the name servers in their own zone files. As mentioned in the previous tip, the name server records should have their own independent A records already with names such as ns1.example.org. Consequently, no other application should notice when the AAAA record is created.
  • Create IPv6 glue records for any name servers that have IPv4 glue records

Configure secondary name servers to poll over IPv6

Configure the secondary nameservers to poll the primary nameserver using it's new IPv6 address.

Update resolv.conf on all hosts

Now that DNS servers are listening on IPv6, it is possible to put IPv6 nameserver addresses in /etc/resolv.conf on all the other hosts.

Configure and test other low-level services

Although services such as LDAP and MySQL may not be exposed to public Internet users, they are an essential foundation for many other applications to run. Make sure all these low level services are accessible over IPv6. Test them.

After testing each of these services, it is OK to go ahead and create the AAAA records for the service.

Configure and test other services

Continue testing each service is accessible over it's IPv6 address and then add the necessary AAAA record. This includes all the high level services now, such as mail and web servers.

Configure and test hostnames

Finally, start adding AAAA records associated with hostnames to the DNS zone. Now it should be possible to ssh or ping6 the hostnames using IPv6.

You may also want to add the IPv6 address of each host into it's own /etc/hosts file at this stage.

Comments

Daniel, Great tutorial. I had to set up a DHCPv6 server one time in our lab a little over a year ago. It was fun, but the learning curve was brutal! I specifically like your idea of translating the IPv4 addresses to IPv6, (which is what I did)... I would personally like more people to start going toward IPv6, as this is the direction we are going anyways. It really is not that bad once you get the hang of it. Cheers,
Jason

One small correction; IPv6 NAT has in fact been implemented in Linux. It's sad, but true, and has been in the kernel for some time now.

You can see it for yourself if you type "ip6tables -t nat -L". The fact -t nat even works is proof enough, but you can see the chains in there.