Switching to IPv6

#tech

I've been in the process of porting my home network from IPv4 to IPv6 and it's been quite an adventure to say the least. It's much better than IPv4 for many different reasons. There's a lot of things I've had to learn (and relearn) to make this happen and I want to share my journey with you.

IPv4

In IPv4, every device on an internet network receives a 32-bit "address" that tells other devices where it lives. These addresses come in the form of four byte segments delimited by periods (for example, 24.39.230.204). IPv4 addresses can range from 0.0.0.0 - 255.255.255.255. Every time you connect to a website on the internet, your computer is effectively sending chunks of data to that website that look like this:

From: 123.45.67.89
To: 234.56.78.90
Data: Hi example.com!

Simple enough, right? With this address scheme there's over 4 billion unique addresses. That should be plenty.

Private IPs and NAT

It's not plenty.

The IPv4 scheme was invented in 1980 when the internet barely existed. Since then, our global population has exploded to over 8 billion humans, each armed with a multitude of phones, tablets, laptops, and smart fridges. Everyone and everything is trying to connect to the internet but we only have 4 billion possible address to go around. What now?

As a temporary solution, ISPs only provide each customer a single public-facing IP address[1]. Individual networks can then use private IP addresses such as 192.168.0.20 and 10.10.1.1 that are available only within a local network and dynamically assigned by the network router through a protocol called Dynamic Host Configuration Protocol (DHCP). The router performs Network Address Translation (NAT) to convert private IPs to public IPs and vice versa to ensure each consumer is still able to receive internet access.

Here's an illustration of how these components work together: Bob pays for Xfinity internet and receives the public IP address 25.24.23.22 and a modem-router combo where he sets up his wifi. When he connects to the wifi from his phone, his router dynamically assigns his phone the private IP address 192.168.0.100. Then, when he opens his browser and goes to example.com, his router takes his private IP address, translates it to his public address 25.24.23.22, then sends it to example.com. When example.com sends a response, the router receives the message and knows to send it back to 192.168.0.100.

Bob's Phone <---> Router <-----------------------> Internet
192.168.0.100     25.24.23.22
                  (NAT)

It's a bit clunky with a few extra steps but it works for most use cases.

Port Forwarding and Reverse Proxies

What happens if we want to host multiple websites or expose more than one server to our family and friends? Since we only have one IP address, we need to use a reverse proxy. A Reverse Proxy acts as a router between multiple local servers to reuse a single IP address for multiple hosted services. If I wanted to host three different websites, I would set up DNS for all domains to point to a single IP address, then set up a reverse proxy to route each request accordingly.

Here's an example Caddyfile for this scenario:

# point all requests to example.com to the server at 192.168.0.1
example.com {
	reverse_proxy 192.168.0.1
}

# point all requests to domain.com to the server at 192.168.0.2
domain.com {
	reverse_proxy 192.168.0.2
}

# point all requests to example.org to the server at 192.168.0.3
example.org {
	reverse_proxy 192.168.0.3
}

The same applies for ports. If we want to host a game server on a specific port, we need to expose that port in our router WAN and forward the port to our game server's computer port. If you wanted to host multiple game servers on the same port, you could use another reverse proxy.

Reverse proxying and port forwarding has allowed the internet to continue functioning for decades, but it's honestly a complicated mess.

IPv6

IPv6 was devised in 1995[2] as a solution to all the shortcomings of IPv4. In IPv6, IP addresses are 128 bits long and come in the form of 16-bit segments written in lowercase hexadecimal and delimited by colons (for example, 2001:0db8:1111:2222:3333:4444:5555:6666). While IPv4 was restricted to 4 billion addresses, IPv6 has realistically unlimited address space[3].

Because IPv6 addresses can be very long to type, there are special rules for shortening how IPv6 addresses are written:

  1. Leading zeroes in a 16-bit segment can be omitted, but each segment requires at least one digit. For example:
    2001:0db8:0011:0002:0333:0004:0005:0000 -> 2001:db8:11:2:333:4:5:0
    
  2. The longest consecutive run of all-zero segments can be compressed into ::. If two equal-length zero segments exist, the left one is compressed. Only one consecutive run can be compressed to prevent ambiguity. For example:
    2001:0db8:1111:2222:3333:0000:0000:0000 -> 2001:db8:1111:2222:3333::
    2001:0db8:0000:2222:0000:3333:4444:5555 -> 2001:db8::2222:0000:3333:4444:5555
    2001:0db8:0000:0000:0000:0000:0000:000a -> 2001:db8::a
    

IPv6 in Practice

The biggest difference between IPv4 and IPv6 is that IPv6 was designed with global addresses in mind. IANA has designated 2000::/3 as the Global Unicast Address (GUA) space, meaning that IP addresses in this range have guaranteed global uniqueness. There's no more need for NAT, reverse proxies, or local-only IP addresses. In theory, I can tell my family my laptop IP address is 2001:db8:47::1! and they could connect to my laptop directly using that IP[4]. This makes networking logic much simpler and removes a lot of complexity from determining how to connect to servers.

Another difference between IPv4 and IPv6 is how IP addresses are assigned. Because of the vast address space, most ISPs will send each consumer a prefix delegation, or an address space bitmask in which they are allowed to use IP addresses. For example, Spectrum might give you the address range 2001:633:47:89::/64, meaning you have over 18 quintillion addresses to use for your local network! Your prefix delegation will vary by ISP: some provide a prefix as vast as /48, while others remain more conservative at /64[5].

Migration Notes

How does IPv6 apply practically to a home network? While my home network had always supported IPv6 via dual-stack networking, it wasn't optimized for IPv6-first networking. It's been a large effort to migrate over to IPv6 for all my servers. Here are various notes or things I've learned along the way that have been invaluable in my transition:

mDNS is your friend

There were a lot of times where I either couldn't find my IPv6 server address or I didn't want to type it out every time I connected through SSH. Fortunately, multicast DNS (mDNS) exists as a link-local networking solution to broadcast a local-only domain using the hostname. For example, instead of typing out my IPv6 address for my game server, I can SSH using the hostname game.local. Apple products have stellar built-in support for mDNS but you can just as easily set it up on another operating system:

# Archlinux
pacman -S avahi nss-mdns
systemctl enable --now avahi-daemon

# FreeBSD
pkg install mDNSResponder
printf 'mdnsresponderposix_enable="YES"\nmdnsresponderposix_flags="-f /usr/local/etc/mdnsresponder.conf"' >> /etc/rc.conf
printf 'SSH\n_ssh._tcp.\ local.\n22' > /usr/local/etc/mdnsresponder.conf
service mdnsresponderposix start

Use brackets in URLs

It's trivial to navigate to an IPv4 address in the browser by typing it in directly, but IPv6 addresses require square brackets around the address to prevent ambiguity for port numbers. Below are some examples:

# IPv4
http://192.168.1.27:8080
http://192.168.0.1

# IPv6
http://[2001:db8::23]:443
http://[2100:444::3]

Many sites still do not support IPv6

As is stands today, operating an IPv6-only network is pretty risky if devices in that network browse the internet regularly. There are many sites and services that simply don't work yet. For example, Github SSH still doesn't work on IPv6 even though they've supposedly been working on it for the past two years. I learned this the hard way and it was unfortunately a deal-breaker for me.

Performance might be a second-class citizen

Don't count on improved performance with IPv6. Some ISPs just aren't great at IPv6. Miraculously, Spectrum seems to have good performance.

  1. This primarily applies to residential connections. Commercial buildings and corporations can generally receive more than one public IP address. ↩︎

  2. IPv6 turned 30 this past December and we're still only at 45% global adoption according to Google. Let that sink in. ↩︎

  3. IPv6 has 2^128 possible addresses including reserved address ranges. Excluding the reserved ranges, we still have billions upon billions of addresses. It's more than enough (for the next few decades at least). ↩︎

  4. We still use firewalls by default normally so this isn't exactly true, but it's perfectly reasonable to set up. ↩︎

  5. Spectrum's prefix delegation in Ohio appears to be /56. I'm mentioning this here because Spectrum doesn't mention it on their IPv6 support page and I had to discover it through Reddit and trial and error. ↩︎