The breadth of address allocation options available in IPv6 world confuses many engineers thoroughly fluent in IPv4, but it also gives operating system developers way too many options… and it turns out that different operating systems behave way differently when faced with the same environment.
Like in IPv4 world, it’s possible to configure static IPv6 host addresses. However, since every IPv6-enabled interface usually has more than one IPv6 address (at least a link-local address and a global one), some host operating systems decide to go for more than just the statically configured IPv6 address.
IPv6 addresses can also be assigned to hosts via DHCPv6. The hosts could send DHCPv6 request and hope for the best (which might be the action-of-last-resort if everything else fails) or listen to Router Advertisement (RA) messages and use DHCPv6 only if the RA messages contain the Managed configuration (M) flag.
However, you won’t see DHCPv6 requests sent from the hosts just because the RA messages contain the M flag – some host operating systems (like Android) decided not to implement DHCPv6 (in some cases because someone religiously believes in evilness of DHCPv6), or the administrator disabled DHCPv6 client, in which case the M flag has no chance of ever triggering a DHCPv6 request.
Finally, there’s stateless autoconfiguration (SLAAC). Whenever a RA message contains an on-link prefix with the Autoconfiguration (A) flag set, a host can automatically create an IPv6 address within that prefix (using its MAC address or a random generator).
I guess you already spotted the vagueness of the previous section – the network devices cannot dictate the host behavior, they can only give hints on what’s available.
Some network operating systems (Linux) decide to use the first available mechanism: if you configure a static IPv6 address on a Linux host, it stops looking for alternatives (at least according to email exchanges on one of the mailing lists I’m tracking – it might be Linux distro specific, in which case please write a comment).
Other operating systems grab all they can: Windows will happily ask for a DHCPv6-assigned address whenever it receives an RA message with the M flag set regardless of whether it already has a static IPv6 address, and will add an autoconfigured address to the mix if the prefixes in the RA messages have the A flag set regardless of whether it already got static and/or DHCPv6-assigned addresses.
The only way to stop a Windows host from getting more addresses than you want it to have is to limit the options – don’t set the M flag in the RA messages if you want hosts to use static IPv6 addressing (or disable DHCPv6 clients on the hosts), and don’t set the A flag on prefixes if you want to use DHCPv6-assigned addresses. Oh, that breaks Android. Too bad – thank the overly biased people who can’t agree on what’s the proper way of doing things.
The Really Hard Part
Having multiple IPv6 addresses on a Windows host doesn’t look like a big deal until you try to figure out which source IPv6 address it will use for outgoing sessions (and source address selection rules are not really helpful in this case).
Here’s what Luka Manojlovič, one of the Slovenian IPv6/Windows gurus found out:
- If a host has static and/or DHCPv6-assigned + SLAAC addresses, the SLAAC address is used for outgoing sessions;
- When there’s no SLAAC-assigned address on the host, static address takes precedence over DHCPv6-assigned address.
The Windows behavior is based on RFC 6724 rule 5.5:
If SA or SA's prefix is assigned by the selected next-hop that will be used to send to D and SB or SB's prefix is assigned by a different next-hop, then prefer SA. Similarly, if SB or SB's prefix is assigned by the next-hop that will be used to send to D and SA or SA's prefix is assigned by a different next-hop, then prefer SB.
SLAAC-generated addresses are considered “assigned by the selected next-hop” (because they were generated based on RA which is also used to set the default next-hop information) and thus prevail over any alternate source IPv6 addresses.
Isn’t that wonderful? Try figuring out which source address to use in your firewall filter ;)
On a more serious note, stop stuffing things from multiple security domains into the same subnet (or start using microsegmentation). If all hosts in the same /64 prefix belong to the same security domain, it’s easy to write firewall rules.
For more details, read the excellent test report written by Antonios Atlasis and Enno Rey. They tested several Linux distributions, two versions of Windows, and Mac OSX in eight different scenarios. Enno is also one of the authors of an IETF draft describing the problem.