I am trying for quite a time now to solve a complex problem: how to use anonymous ipv6 addresses on public internet, while still using fixed ipv6 in a LAN.

What ?

The general idea

When browsing the web, you wish to be the least trackable possible. That is possible using randomized adresses from RFC 4941.

That is only a part of a true anonymization. Your web browser must also be untrackable.

But using those addresses is a bad idea in your local network, where you wish to know who or what gets a connection. Using a fixed address known in the local DNS, as described somewhere else in this blog, would permit to know it's Artur's computer which got connected to the mail server.

With ssh connections, the server make a reverse dns request. In case the address is unknown, the connection is really slowed down.

Theory

To solve this problem, the routing table should primarily use fixed address in a known network and otherwise the random addresses.

Another problem appears: when is the network safe enough? The computer itself does not know. It is the user who knows if he is at home or on a public wifi.

We notice that the user themselves should know about network safety, etc.

In Windows, there is an option that allows the user to report the current network to be public or private. It lets you change the firewall policy accordingly. This is also what should allow you to adjust the routing table.

Experimentations

Fixed address

We could use a dhcp(v6) address, but then it should be used in the route script.

I am going to use the SLAAC address, which can be calculated with ipv6calc. This is done by activating autoconf in kernel's parameters via sysctl, or /proc.

cat /proc/sys/net/ipv6/conf/all/autoconf 
1

Temporary addresses

Idem :

cat /proc/sys/net/ipv6/conf/all/use_tempaddr
2

The value 2 here means we favor temporary addresses.

Here is now my ipv6 addresses on my ethernet iface:

[stephane@Jabberwocky ~]$ ip -6 addr show eno1
2: eno1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 state UP qlen 1000
inet6 2001:…:c79/64 scope global temporary dynamic 
   valid_lft 3508sec preferred_lft 3508sec
inet6 2001:…:d709/64 scope global mngtmpaddr dynamic 
   valid_lft 3508sec preferred_lft 3508sec
inet6 fe80::…:d709/64 scope link 
   valid_lft forever preferred_lft forever

One can see that the first one is temporary and the third is the local-link address. The second is SLAAC, as its last bytes are the same as the local-link address.

Route

Here is the basic ipv6 routing table on my laptop:

[stephane@Jabberwocky ~]$ ip -6 route
2001:…:e2::/64 dev eno1  proto kernel  metric 256  expires 3598sec pref medium
fe80::/64 dev eno1  proto kernel  metric 256  pref medium
default via fe80:…:d709 dev eno1  proto ra  metric 1024  expires 598sec hoplimit 255 pref medium

You need either to add a route or change the first one.

Change the route :

(You need to set a low metric otherwise it is not this one route which will lead.)

[stephane@Jabberwocky ~]$ sudo ip -6 route add 2001:...:e2::/64 src 2001:...:e2:226:...:d709 dev eno1 metric 128

Result :

[stephane@Jabberwocky ~]$ ip -6 route
2001:...:e2::/64 dev eno1  src 2001:...:e2:226:...:d709  metric 128  pref medium
fe80::/64 dev eno1  proto kernel  metric 256  pref medium
default via fe80::20d:b9ff:fe3e:a812 dev eno1  proto ra  metric 1024  expires 594sec hoplimit 255 pref medium

Setting the metric at 128 (a number picked quite randomly, but under 256), I set the route higher in the table. Without setting a metric, the default value will be 1024, which makes sure the route will never be used.

Check it all

Take the ip address of one of your hosts and an ip address of a public network (Google or FB will make good victims) and check which address will be used when a connection is initiated.

Google

[stephane@Jabberwocky ~]$ host -t aaaa google.com
google.com has IPv6 address 2a00:1450:400f:808::200e

[stephane@Jabberwocky ~]$ ip route get 2a00:1450:4005:803::200e
2a00:1450:4005:803::200e from :: via fe80::20d:...:a812 dev eno1  proto ra  src 2001:...:e2:e5b4:...:c79  metric 1024  hoplimit 255 pref medium

The selected source address is the anonymous one.

Host in local network

[stephane@Jabberwocky all]$ ip route get 2001:...:e2::2
2001:...:e2::2 from :: dev eno1  src 2001:...:e2:226:...:d709  metric 128  pref medium

I get a fixed address.

Something concrete.

The trouble is now to set the routing table in this network (this computer being a laptop, I use it sometimes outside my network). Any other network should remain with the basic kernel and daemon maintained routing table.

For fixed computers (desktop), the problem stays the same.

As far as I know, no one as designed a routing policy this way, which means I had to deal with it by hand. I actually have a script that I launch manually when needed. It is not fixed, but dynamic, or dynamically fixed. There is also the problem that sometimes, the routing table gets updated, meaning your customized route won't be used anymore.

What is sure is that it should not be done this way and if you have any suggestion, your comments are welcome.