IPv6 Privacy Extensions

Linode Staff

Does Linode allow enabling privacy extensions for Stateless Address Autoconfiguration, as proposed in RFC4941?

1 Reply

With the security measures we have in place to prevent IP spoofing, and the fact that it would be a huge administrative headache to manage and troubleshoot a network of constantly changing devices, IPv6 privacy extensions are not supported on our platform. Furthermore, RFC4941 was written from the perspective of physical devices on a LAN, not virtual devices in the cloud. It’s not really applicable here, even though the concerns pertain to Stateless Address Autoconfiguration (SLAAC). To understand why, we need a basic understanding of how SLAAC works.

Just like with IPv4, there is both a network segment and host segment of the address. The network segment or prefix is the first 64 bits.

2600:3c01:0000:0000

The host segment or Interface Identifier (IID) is the remaining 64 bits. This is calculated by taking the Linode’s 48 bit MAC address and putting ff:fe in the middle.

# 48 bit MAC address
f2:3c:92:08:4b:73

# Put ff:fe in the middle to make it 64 bits long
f2:3c:92:ff:fe:08:4b:73

Then we flip the 7th bit (known as the universal/local bit) to 0, which changes the leading f2 to f0. This may be easier to understand if we look at it in binary.

# before
echo "ibase=16; obase=2; F2" | bc
11110010
      ^

# after
echo "ibase=16; obase=2; F0" | bc
11110000
      ^

# result
f0:3c:92:ff:fe:08:4b:73
 ^

Regroup our bits into quartets and we have the EUI-64 formatted host segment of the IPv6 address.

f03c:92ff:fe08:4b73

Add fe80:: in front of it and we have the full 128 bit link-local address. Add the network prefix and we have the full 128 bit global address. One set of consecutive zeros can be omitted with a double colon (::) for shortening.

# short format
Link-local: fe80::f03c:92ff:fe08:4b73
Global: 2600:3c01::f03c:92ff:fe08:4b73

# long format
Link-local: fe80:0000:0000:0000:f03c:92ff:fe08:4b73
Global: 2600:3c01:0000:0000:f03c:92ff:fe08:4b73

The concerns outlined in RFC4941 are collectively described in sections 1.2 and 2.3. To summarize, the most troubling concern relates to the use of SLAAC on mobile devices (e.g. laptops, cell phones, tablets). As these devices connect to different networks, only the prefix changes, the interface identifier stays the same since it comes from the MAC address. This can enable an adversary to track the device’s movement across different LANs.

Another concern has to do with the MAC address itself. The first 24 bits, known as the Organizationally Unique Identifier (OUI), is what identifies the device manufacturer. If this information is “leaked” via the SLAAC IPv6 address, an adversary can learn the device type to tailor a more specific attack.

Since an attacker can perform these correlations by sniffing traffic in the path, or by compromising the other end of the connection (e.g. web server), I believe the concerns of RFC4941 are legitimate and encourage the use of privacy extensions on your physical client devices. Privacy extensions work by generating pseudo-random interface identifiers to make temporary addresses for outbound connections. It’s important to note however, this simply provides more privacy, not total privacy, because the network prefix itself is also an identifier. Although the larger the network, the less helpful a prefix is for correlation of an individual user.

When it comes to a virtual server in the cloud, such as a Linode, there is no added benefit from privacy extensions. A Linode’s MAC address doesn’t contain a real OUI for an attacker to gain from reconnaissance. It's also not a mobile device that is constantly changing networks, or a desktop computer on your small home network. All that said, if you’d like the effect of privacy extensions for your Linode (temporary addresses to prevent correlation of your activities), a workaround may be to write a script that appends pseudo-random interface identifiers to the prefix of your own /64 pools, which can run periodically as a cron job. I wrote a simple bash script to demonstrate the idea.

#!/bin/bash

# overwrite /etc/network/interfaces with template
# simple way to flush out expired pool addresses
cat << EOF > /etc/network/interfaces
# /etc/network/interfaces

auto lo
iface lo inet loopback

auto eth0
allow-hotplug eth0

iface eth0 inet6 auto

iface eth0 inet static
    address 72.14.180.202/24
    gateway 72.14.180.1
    up   ip addr add 192.168.179.124/17 dev eth0 label eth0:1
    down ip addr del 192.168.179.124/17 dev eth0 label eth0:1

iface eth0 inet6 static
    address 2600:3c00::f03c:92ff:fe55:b2c3/64
    gateway fe80::1
EOF

# generate and append random addresses to pool prefix
for i in {1..10}; do
    IP=$(printf "2600:3c00:e000:029b:%s"; openssl rand -hex 8 | sed 's/\(....\)/\1:/g; s/.$//');
    echo -e "\niface eth0 inet6 static\n    address $IP/64" >> /etc/network/interfaces;
done

# restart networking
systemctl restart networking

# randomly rotate pool addresses for outbound connections
ip6tables -t nat -F
for i in `ip a | grep e000 | awk '{print $2}' | awk -F / '{print $1}'`; do
    ip6tables -t nat -I POSTROUTING -m state --state NEW,ESTABLISHED,RELATED -o eth0 -m statistic --mode nth --every 10 --packet 0 -j SNAT --to-source $i
done

# make sure slaac doesn't sneak in
x=$(ip a | grep 2600:3c00:: | awk '{print $2}' | awk -F / '{print $1}')
z=$(ip a | grep e000 | awk '{print $2}' | awk -F / '{print $1}' | tail -n 1)
ip6tables -t nat -A POSTROUTING -s $x -o eth0 -j SNAT --to-source $z

exit 0

Plugin your own /64 prefix and tune for your distribution and firewall, using any scripting language you like. Have fun with it!

Reply

Please enter an answer
Tips:

You can mention users to notify them: @username

You can use Markdown to format your question. For more examples see the Markdown Cheatsheet.

> I’m a blockquote.

I’m a blockquote.

[I'm a link] (https://www.google.com)

I'm a link

**I am bold** I am bold

*I am italicized* I am italicized

Community Code of Conduct