A beginner hacker's guide to IPv6
A quick brain dump of everything I know regarding IPv6
February 02, 2020
I noticed recently how little I knew about IPv6. For someone working on broadband gateways, that's not something I'm most proud of. But I've learned a little in the past few months, and I thought I'd share it here.
How to read an IPv6 address: the zeroes are hidden
An IPv6 address is 128 bits wide, and written in eight groups of 4 hex-digits, separated by colons, like this:
Leading zeroes are ignored, so the previous address can be written like this:
And a sequence of one ore more groups that are all zeroes can be replaced with
::, so the previous address is canonically written like this:
This is the address of this blog at the time of this writing.
Put the address inside square brackets for URLs
To reduce the confusion with the IP:PORT notation, the IPv6 in URLs is enclosed in square brackets for URLs:
curl -v http://[2001:41d0:1:c38f::1]
curl -v https://[2001:41d0:1:c38f::1]:443
But not all tools would need that:
Types of IPv6 addresses
There are three types of addresses to know about:
- the loopback address
::1; that's your
127.0.0.1in IPv4 (or the whole
- link-local addresses in the
fe80::/10range : their scope is local, and they shouldn't be routed/forwarded. Equivalent to
- global addresses; those are globally routed addresses; they're any other address.
Other interesting address types not covered here:
- multicast addresses
- unique local addresses (previously named site-local)
fc00::/7(can start with
fd00:); they are used to build a private network.
- the unspecified address
::(all zeroes) used for broadcast.
Client IPv6 addresses are autoconfigured by default
In IPv6, client hosts don't use DHCP by default (except in a few cases). They use autoconfiguration, which means the host decided of its address by itself, inside a pool of available addresses: this is Stateless Address Auto Configuration (SLAAC). Instead of asking your router to give you an address, in SLAAC, the client machine sends a Router Solicitation, which responds with a Router Advertisement that contains the range in which the client can configure an address; then chooses an address at random (or based on its MAC address), and runs a collision detection algorithm (Duplicate Address Detection) to prevent having the same address as a peer.
For link-local addresses, there does not even need to be router advertisements, since the range is known by default, a host can pick an address and then run it's duplicate detection algorithm.
DHCPv6 has lost and shouldn't be used
There exist a spec to attribute addresses via a DHCP mechanism: DHCPv6. But it isn't supported in Android, by choice. Admins that want to match IPv6 addresses to MAC addresses (say, for compliance purpose) should watch ICMPv6 SLAAC advertisements instead. But in a world of random MAC addresses by default on consumer devices, it doesn't really make sense. It's better to enforce a zero-trust network with a higher level authentication and a VPN.
Use AAAA DNS records
You store IPv6 addresses in an AAAA record instead of an A record:
$ dig anisse.astier.eu AAAA +short 2001:41d0:1:c38f::1
Your ISP gives you more IPv6 addresses than you could ever use
Your ISP probably gives you a
/48 (mine gives a
/61): it means that you have 235 to 248 more addresses than available in the whole IPv4 range (ignoring reserved ranges). I could address 267 devices in my network; that's 147,573,952,589,676,412,928 IPs.
Some cloud providers might give you single IPv6 address (
/128). I think this is wrong and short-sighted; mostly used for market segmentation (the simplicity of configuration does not hold up a cursory look).
All your devices are globally reachable
That's the thing that surprises most people used to an IPv4 NAT-ed world mindset. Since your ISP gives you so many addresses, all your local devices can have a globally routed address. And it's a good thing, mostly. What this implies:
- you can access your dev web server from anywhere in the world if you listen on global addresses instead of local or loopback one.
- you can send your DNS requests to your home pi-hole wherever you are. Ditto for any service hosted on a random machine in your network.
- you can directly connect to a peer for video chat, exchange data, etc. No need for UPnP, UDP hole punching, STUN gateways, and many other types of NAT-traversal technologies.
Security implications: you should make sure privacy extensions are enabled
Unfortunately, by default many OSes used their MAC address to choose a global address with SLAAC. This means that whole-plage scanning with masscan-like tools are possible on given OUIs. It takes about 5 minutes to scan the whole IPv4 range nowadays. That's what companies like Shodan or CybelAngel do continously.
This has the following implications for IPv6:
- if badly-configured software starts some VMs with open services and a static network MAC address, you could instantaneously scan a given IPv6 prefix (provided you know its size) to for the presence of such a VM; because the last bits of the IPv6 would always be same same.
- If you know a particular (say, IoT) device has open services and is vulnerable; you could scan its OUI for a given IPv6 prefix. That's still 224 IPs to scan; much less if you know the MAC sequencing pattern. This could be used for targeted attacks, or botnet/worms.
- If a device connects to a malicious site, it can be scanned; for example that dev web server on your laptop; and the type of devices leaks because the OUI is in the IPv6. This breaks expectation of IPv4 NAT-ed world where you need to manually forward port for them to be publicly available
Luckily, all of this was understood a long time ago, and there are privacy extensions in IPv6: a way to randomize your SLAAC address, just like we now randomize Wifi MACs on untrusted networks. It is now implemented in most modern OSes. Unfortunately older ones, and some Linux distributions don't enable privacy extensions by default. In Linux, those are represented as
temporary instead of
ip -6 addr. Those temporary addresses are used when connecting to a service over IPv6, so that your MAC doesn't leak. The address should change regularly.
As far as I understand, privacy extensions address the issue of data leakage, but not the fact that you can then be scanned for mis-configured software (which to be fair is already the case in a NAT-ed IPv4 + websocket world). That's because the initial expectation was to have every device with its own firewall; and consider that it's up to the device to properly handle what's exposed to the world.
Therefore, a small issue I see, is that it's hard to have a server application to listen only on global IPs. It should enumerate the interfaces and IPs, and only listen on those that have "scope global" but not "temporary" or "secondary" addresses.
- It has been mandatory to support IPv6 on new devices in Brazil for three years.
- It will soon be mandatory in France for 5G carriers.
- When using link-local addresses, you should do scoping; which is add a % after the address to specify through which interface your connection should go through. But wget does not support link-local scoping; use curl instead. To connect to a link-local IP on port 8080 :
curl -v http://[fe80::6e60:6ddd:d354:2234%wlp2s0]:8080
- It's 2020 and Fedora still puts
/sbin; without adding it to non-root users'
PATH. I don't know why.
- At FOSDEM, the default network is IPv6 only, and it works really well. But from time to time you might discover that something is not working. It's because it's not connecting over IPv6 (like the Steam client for instance).
There are many RFCs on IPv6; I couldn't cover here anywhere near everything that a professional network engineer should know. I hope I've covered the basics so that you can search for the rest yourself.
Thanks to Stéphane Bortzmeyer and Neil Armstrong for feedback on this article.