Experimenting with an IPv6 network that coexists with IPv4

Published on 2024-09-13 by ADAM

In this experiment you'll setup your first IPv6 network to live alongside your IPv4 legacy network. I'm assuming you've already worked with the experiments in the first two blog posts in this series. We're going to demonstrate the principle behind Dual Stack networking and prove to ourselves that running an IPv6 network alongside an IPv4 network is no big deal.

First, grab those few machines that you had on the isolated IPv6 experiment network. Fold them back into your network the way that they always were. Let them reclaim their old IPv4 addresses. (I'll assume that they're in RFC-1918 space, since this series is aimed at the hobbyist-home-user.) Now go to each of them in turn and dynamicall re-assign their IPv6 addresses via the command line.

Once you do, run an ifconfig em0 for example. The output should then look something like this:

% ifconfig em0
em0: flags=1008843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST,LOWER_UP> metric 0 mtu 1500
	options=8209b<RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,VLAN_HWCSUM,WOL_MAGIC,LINKSTATE>
	ether 10:20:30:40:50:60
	inet 10.1.10.42 netmask 0xffffff00 broadcast 10.1.10.255
	inet6 fe80::1220:30ff:fe40:5060%em0 prefixlen 64 scopeid 0x1
	inet6 fd01:2:3:4:5:6:7:c prefixlen 112
	media: Ethernet autoselect (1000baseT <full-duplex>)
	status: active

Once a few machines are up like this, you should be able to ping them on both their 4 address and their 6 address. (Ignore the fe80:: IPv6 address on the card for the moment. We'll come back to that in another blog post. For now, don't mess with these addresses or try to ping them or SSH to them.) If pings work you should be able to SSH to them too. On both their legacy network addresses and the shiny new IPv6 addresses you gave them. Don't worry too much about coming up with a good IPv6 address plan for your experimental network. You're going to throw this one away. Just keep it simple.

When SSHing to various machines, you can run echo $SSH_CLIENT and it will print the source address of your connection. Verify that connections to IPv6 addresses come from the expected IPv6 source and the same for IPv4. You should be able to do all of this without impacting any network traffic for machines not participating in these experiments. For those which are participating, they should be unaffected as well, but some operating systems have some quirks with reaching the wider internet when there's local IPv6 that can't reach the internet. This is a transition step, of course... so we'll deal with that a bit later.

Now you've gotten a few hosts to converse via Modern IP and in a way that's integrated with your existing infrastructure. Congratulations. You're now running a dual-stack network. Dual-stack networks are an important part of the IPv6 transition strategy. Any plan which has to upgrade nodes that only speak IPv4 to be able to continue speaking classic IPv4 with still-un-upgraded nodes but speak some enhancement or another with each other would have to go through this state.

Dual-stack explicitly doesn't map IPv4 into any part of the IPv6 address space. If it did, there's no benefit. The altered packet header cannot be understood by IPv4 legacy hosts, and thus legacy packets would have to always be sent to any host in the "might not speak IPv6" range, because it cannot be known what they speak. Any effort which is surmised as "we need to go around to them all and teach them the new address space" is precisely the same task that IPv6 deployment has been trying to accomplish for three decades, now.

Keeping the two stacks entirely separate is the cleanest way to handle this. But they can coexist in the same physical network, just like we've setup now. Over time, more traffic should be routed over the new IPv6 space. As flows move from legacy to modern IP, the legacy IP space becomes ever more irrelevant. Already (as of 2023) on the wider internet, the majority of the traffic being carried is over IPv6, not IPv4. This trend is going to continue, and it seems to be slightly accelerating. The IPv4 shortage/endgame is forcing more and more traffic towards IPv6.

So, how does this affect our experiment? Well, the days of talking to hosts by IP address are long in the past. These days we use DNS on the wider network, and for home networks we either use DNS or /etc/hosts files. Names are fantastic tools for migration to Modern IP. We can associate a name with an address in both IPv4 and IPv6, when that host is running dual-stack. Any host running legacy-only will decline to ask what the IPv6 address of a host is. For dual-stack hosts that want to talk to other dual stack hosts, they can choose whether to talk over IPv4 or IPv6 -- there's a set of algorithms to determine which to use. (Someday I'll write a blog post ranting about that algorithm, "Happy Eyeballs".) And for IPv6-only hosts (a growing number, online), they're stuck with the opposite problem to IPv4 only hosts. However, there are some migration tools which permit mapping parts or all of IPv4 space into IPv6 space -- all under the control of the network administrator of that 6-only site.

So let's make our experimental dual-stack network have IPv6 mappings for our names.

Suppose this is your /etc/hosts file on all of your machines:

127.0.0.1 localhost

10.1.10.22 ssh-server
10.1.10.30 build-server
10.1.10.80 webhost
10.1.10.99 workstation

We can modernize it thus:

127.0.0.1 localhost

10.1.10.22 ssh-server
10.1.10.30 build-server
10.1.10.80 webhost
10.1.10.99 workstation

# IPv6 names:

::1 localhost # This is probably already in your hosts file!

fd01:2:3:4:5:6:7:22 ssh-server
fd01:2:3:4:5:6:7:30 build-server
fd01:2:3:4:5:6:7:80 webhost
fd01:2:3:4:5:6:7:99 workstation

# Note that although the human-readable digits in the last group 
# match between IPv4 and IPv6, they're not the same bit pattern.
# This is perfectly acceptable.  There's no requirement for similarity of
# addresses between the two protocols for the same machine.

You should run a DNS server -- gossiping around versions of hosts files is tedious, error prone, and painful. If you run a DNS server (I hope you do!), you might augment your zone file thus:

; ...

ssh-server    IN A     10.1.10.22
build-server  IN A     10.1.10.30
webhost       IN A     10.1.10.80
workstation   IN A     10.1.10.99



; Add additional `AAAA` records for the 6-enabled hosts.
; These can be interlaced with A records for better readability,
; if desired.

ssh-server    IN AAAA fd01:2:3:4:5:6:7:22
build-server  IN AAAA fd01:2:3:4:5:6:7:30
webhost       IN AAAA fd01:2:3:4:5:6:7:80 
workstation   IN AAAA fd01:2:3:4:5:6:7:99

Once your host names are available to all machines, you'll find that legacy-only hosts just don't care about this change. And your new dual-stack hosts will automatically start to try to talk more 6 with each other. You should be able to run your network for days like this. You may find that the dual stack hosts have slower global internet response time due to trying to talk IPv6 globally but being unable to do so.

Most of those issues have been resolved for most operating systems, but it was the leading cause for why the terrible advice "disable IPv6 to fix connection problems" was promulgated and actually "seemed to work". We're not going to turn off IPv6. At least not permanently. For any machine which is having some problems, it's fine to reboot it such that it doesn't have an IPv6 address anymore. (Remember that we manually provisioned these addresses for these machines after they booted. So there should be no permanent static IPv6 assignment. You may wish to remove the IPv6 hosts file entries or DNS entries for machines you've had to disable IPv6 on. We'll get to re-enabling it, though.)