Some Operating Systems enable IPv6 privacy extensions by default. They make IPv6 link-local address unpredictable and not possible to determine from the outside. Your VM communicates with Onidel's IPv6 gateway (`fe80::1`) via link-local and is only allowed to do so from an [EUI-64](https://www.catchpoint.com/benefits-of-ipv6/eui-64) address.

Despite the Guest OS having IPv6 set up properly according to the address you see in [Onidel Cloud Panel](https://cloud.onidel.com), the IPv6 connections time out.

```
$ traceroute google.com
traceroute to google.com (2607:f8b0:4006:802::200e), 30 hops max, 80 byte packets
 1  * * *
 2  * * *
 3  * * *
 4  * * *
...
```

```
$ ip a
...
2: ens18: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 0c:1d:e1:7d:40:60 brd ff:ff:ff:ff:ff:ff
    altname enp6s18
    altname enx0c1de17d4060
    inet 192.209.63.14/24 brd 192.209.63.255 scope global dynamic noprefixroute ens18
       valid_lft 3596sec preferred_lft 1796sec
    inet6 2602:f992:60:110::1/64 scope global 
       valid_lft forever preferred_lft forever
    inet6 fe80::2feb:d3b9:8b53:857b/64 scope link 
       valid_lft forever preferred_lft forever
$ ip -6 route
2602:f992:60:110::/64 dev ens18 proto kernel metric 256 pref medium
fe80::/64 dev ens18 proto kernel metric 256 pref medium
default via fe80::1 dev ens18 metric 1024 onlink pref medium
```

# Solutions

Here, we assume Debian OS is used as a guest and we showcase two possible ways of fixing the issue. Those are inspired by this [superuser answer](https://superuser.com/a/1297875).

## dhcpcd slaac hwaddr

If your OS uses DHCP to obtain IPv4 address, it's highly likely dhcpcd automatically manages [SLAAC](https://www.hpc.mil/solution-areas/networking/ipv6-knowledge-base/infrastructure/dhcp-and-slaac-on-ipv6-networks) and IPv6 generation as well.

Near the bottom of `/etc/dhcpcd.conf` file, verify the selected `slaac` option is "`hwaddr`", not "`private`":

```
# Generate SLAAC address using the Hardware Address of the interface
slaac hwaddr
# OR generate Stable Private IPv6 Addresses based from the DUID
#slaac private
```

Then you just need to restart networking and the lower 64 bits of link-local IPv6 address should match your interface's MAC address.

```
$ ip a | grep 'scope link\|ether'
    link/ether 0c:1d:e1:7d:40:60 brd ff:ff:ff:ff:ff:ff
    inet6 fe80::2feb:d3b9:8b53:857b/64 scope link 
$ systemctl restart networking
$ ip a | grep 'scope link\|ether'
    link/ether 0c:1d:e1:7d:40:60 brd ff:ff:ff:ff:ff:ff
    inet6 fe80::e1d:e1ff:fe7d:4060/64 scope link 
$ ping -6 google.com
PING google.com (2607:f8b0:4006:819::200e) 56 data bytes
64 bytes from pnlgaa-av-in-x0e.1e100.net (2607:f8b0:4006:819::200e): icmp_seq=1 ttl=116 time=2.41 ms
64 bytes from pnlgaa-av-in-x0e.1e100.net (2607:f8b0:4006:819::200e): icmp_seq=2 ttl=116 time=1.03 ms
64 bytes from pnlgaa-av-in-x0e.1e100.net (2607:f8b0:4006:819::200e): icmp_seq=3 ttl=116 time=1.05 ms
```

## sysctl addr_gen_mode

If the `dhcpcd` method did not work, it may indicate the kernel itself manages the generation of unique IPv6 link-local addresses. In such case, it may be required to set `addr_gen_mode` parameter of your network interface to 0 which forces kernel to use EUI-64 generated addresses.

According to [sysctl documentation](https://www.kernel.org/doc/Documentation/networking/ip-sysctl.txt):

> addr_gen_mode - INTEGER  
> Defines how link-local and autoconf addresses are generated.
>
> * 0: generate address based on EUI64 (default)
>
> * 1: do no generate a link-local address, use EUI64 for addresses generated from autoconf
>
> * 2: generate stable privacy addresses, using the secret from stable_secret (RFC7217)
>
> * 3: generate stable privacy addresses, using a random secret if unset

You can check the currently active address generation mode querying the `addr_gen_mode` parameter of given network interface as such:

```
$ sysctl net.ipv6.conf.ens18.addr_gen_mode
net.ipv6.conf.ens18.addr_gen_mode = 3
```

Then, to force address to be based on network interface MAC address (EUI-64):

```
$ sysctl -w net.ipv6.conf.ens18.addr_gen_mode=0
```

Changes should be applies instantly, without the need of restarting any network service.

```
$ ip a | grep 'scope link\|ether'
    link/ether 0c:1d:e1:7d:40:60 brd ff:ff:ff:ff:ff:ff
    inet6 fe80::2feb:d3b9:8b53:857b/64 scope link 
$ sysctl -w net.ipv6.conf.ens18.addr_gen_mode=0
net.ipv6.conf.ens18.addr_gen_mode = 0
$ ip a | grep 'scope link\|ether'
    link/ether 0c:1d:e1:7d:40:60 brd ff:ff:ff:ff:ff:ff
    inet6 fe80::e1d:e1ff:fe7d:4060/64 scope link proto kernel_ll 
    inet6 fe80::2feb:d3b9:8b53:857b/64 scope link 
$ ping -6 google.com
PING google.com (2607:f8b0:4006:801::200e) 56 data bytes
64 bytes from lga34s11-in-x0e.1e100.net (2607:f8b0:4006:801::200e): icmp_seq=1 ttl=116 time=1.30 ms
64 bytes from lga34s11-in-x0e.1e100.net (2607:f8b0:4006:801::200e): icmp_seq=2 ttl=116 time=1.04 ms
64 bytes from lga34s11-in-x0e.1e100.net (2607:f8b0:4006:801::200e): icmp_seq=3 ttl=116 time=1.02 ms
```