Per Request IPv6 Addresses

Erik Kline

08.2012

More randomness

In thinking about the "Kaminsky attack" and more generally the importance of increasing the number of bits of randomness to make spoofing increasingly difficult, I thought about the size of the IPv6 address space. What if, in addition to randomizing DNS query IDs, query case, and UDP source ports, a recursive resolver randomized the IPv6 source address as well?

Theory of operation

What follows is merely a recording of some ideas without having yet gone through the learning experience of implementation...so naturally it's worth rather less than the electrons expended to render this page.

Simple approach

At the very minimum, an IPv6-capable recursive resolver would likely have an entire /64 at its disposal. In theory then, the resolver could use almost any random 64 bit IID for sourcing a query toward an "upstream" DNS server. However, to use this address naively would generally entail adding the address to an interface, waiting for Duplicate Address Detection (DAD) to succeed or flying with Optimistic DAD, and binding a socket to use this source address or using sendmsg(2) with IPV6_PKTINFO goodness. However, it might be easy to get into a situation where an overabundance of multicast joins exhausted some resource in the switch(es) or router(s) nearest the recursive resolver.

Routed approach

A possibly better approach is to route an entire prefix (potentially even more than a single /64!) to the recursive resolver. It may even be easy enough to script a DHCPv6 Prefix Delegation (PD) request in the course of starting the recursive resolver service. In this configuration there should be no need to be concerned with multicast joins nor DAD nor any associated delays. In theory, a single AF_INET6 UDP socket could use the aforementioned sendmsg(2) with IPV6_PKTINFO goodness to source requests from a randomly generated IPv6 address for each request. Using the IP_FREEBIND socket option in Linux, it ought to be possible to make TCP requests from these random addresses as well. (I'm unsure, but it seems like the IP_BINDANY option in FreeBSD might behave similarly.)

UPDATE: I think perhaps the only way to make this truly scalable might be to use a single raw socket, actually...not sure.

If it works...

If any of these approaches do in fact work there are likely to be extra things needed like appropriate permissions or routing configuration—exactly the kinds of things I should have sorted out by doing some implementations first. But the bottom line is that n more bits, where n ≥ 64 and ≤ "128 minus the prefix length routed to the resolver node", of randomness could theoretically be added to increase the difficulty of spoofing responses.

Note that this is essentially one process that an attacker might go through to set up a Denial of Service attack. This technique is available to any attacker with IPv6 connectivity though, so there's nothing new here. The idea is simply to require that the received answer to a given query also be sent to the correct IPv6 address used to source that query.