routing ipv6 from Hetzner to an OpenStack instance

The 2a01:4f8:162:12e3::2 IPv6 address is assigned to http://packaging-farm.dachary.org/ from the IPv6 subnet provided by Hetzner. The OpenStack host on which the instance running packaging-farm.dachary.org is running is configured as a proxy with

sysctl -w net.ipv6.conf.all.proxy_ndp=1
ip -6 neigh add proxy 2a01:4f8:162:12e3::2 dev eth0

and an OpenStack Essex bug is worked around by manually disabling hairpin_mode:

echo 0 > /sys/class/net/br2003/brif/vnet1/hairpin_mode

The page can then be retrieved with

$ curl --verbose -6 http://packaging-farm.dachary.org/
* About to connect() to packaging-farm.dachary.org port 80 (#0)
*   Trying 2a01:4f8:162:12e3::2...
* connected
* Connected to packaging-farm.dachary.org (2a01:4f8:162:12e3::2) port 80 (#0)
> Host: packaging-farm.dachary.org
> Accept: */*
>
...
<address>Apache/2.2.19 (Debian) Server at packaging-farm.dachary.org Port 80</address>
</body></html>
* Connection #0 to host packaging-farm.dachary.org left intact
* Closing connection #0

obtaining an IPv6 subnet from Hetzner

Chose the One IPv6 /64 subnet radio button after clicking the Ordering of additional IP, failover IP or subnet link from the IPs tab of the Hetzner control panel.

After clicking Apply the IPv6 subnet is immediately made available.

Hetzner does not provide an interface to route parts of the subnet to designated IPv6 link local addresses.

DNS definition

The IP 2a01:4f8:162:12e3::2 is associated with the hostname packaging-farm.dachary.org with the following bind9 zone definition:

packaging-farm.dachary.org. IN AAAA 2a01:4f8:162:12e3::2

The corresponding reverse DNS entry is added using the IPs tab of the Hetzner control panel.

fixing IPv6 duplicate address false positive

The dmesg command on the packaging-farm instance will show

[    2.852284] eth0: IPv6 duplicate address fe80::f816:3eff:fe12:80a detected!

which is not an actual duplicate (false positive). As a result, the instance interface is not properly configured

2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether fa:16:3e:12:08:0a brd ff:ff:ff:ff:ff:ff
    inet 10.145.3.3/24 brd 10.145.3.255 scope global eth0
    inet6 fe80::f816:3eff:fe12:80a/64 scope link tentative dad failed 
       valid_lft forever preferred_lft forever

It was fixed after Essex. Until the patch is backported to Essex, the hairpin mode can be deactivated for the corresponding instance with

echo 0 > /sys/class/net/br2003/brif/vnet1/hairpin_mode

on the host. It must be done manually each time to host is rebooted.
The instance is running on the host bm0007.the.re and the tenant private IP subnet is 10.145.3.0/24. The 3 matches the bridge br0003 to which the instance is connected.

root@bm0007 ~ # ip addr show dev br2003
12: br2003: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP
    link/ether fa:16:3e:79:4c:17 brd ff:ff:ff:ff:ff:ff
    inet 10.145.3.4/24 brd 10.145.3.255 scope global br2003
    inet6 fe80::7cea:6cff:feac:2238/64 scope link
       valid_lft forever preferred_lft forever

After reconfiguring the interface with

ifdown eth0 ; ifup eth0

the IPv6 address is properly configured

2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether fa:16:3e:12:08:0a brd ff:ff:ff:ff:ff:ff
    inet 10.145.3.3/24 brd 10.145.3.255 scope global eth0
    inet6 fe80::f816:3eff:fe12:80a/64 scope link
       valid_lft forever preferred_lft forever

And it can ping the IPv6 address of the bridge:

packaging-farm:~# ping6 fe80::7cea:6cff:feac:2238%eth0
PING fe80::7cea:6cff:feac:2238%eth0(fe80::7cea:6cff:feac:2238) 56 data bytes
64 bytes from fe80::7cea:6cff:feac:2238: icmp_seq=1 ttl=255 time=0.142 ms
...

The 2a01:4f8:162:12e3::2 is bound to the instance interface and the default gateway set to the IPv6 address of the bridge in /etc/network/interfaces.

iface eth0 inet6 static
   pre-up echo 0 > /proc/sys/net/ipv6/conf/$IFACE/accept_ra
   pre-up echo 0 > /proc/sys/net/ipv6/conf/$IFACE/autoconf
   address 2a01:4f8:162:12e3::2
   netmask 64
   gateway fe80::7cea:6cff:feac:2238

Which translates in the following address and route:

packaging-farm:~# ip -6 a show dev eth0
2: eth0:  mtu 1500 qlen 1000
    inet6 2a01:4f8:162:12e3::2/64 scope global
       valid_lft forever preferred_lft forever
    inet6 fe80::f816:3eff:fe12:80a/64 scope link
       valid_lft forever preferred_lft forever
packaging-farm:~# ip -6 r show dev eth0
2a01:4f8:162:12e3::/64  proto kernel  metric 256  mtu 1500 advmss 1440 hoplimit 0
fe80::/64  proto kernel  metric 256  mtu 1500 advmss 1440 hoplimit 0
default via fe80::7cea:6cff:feac:2238  metric 1  mtu 1500 advmss 1440 hoplimit 0

routing from eth0 to the br2003

The IPv6 packet for 2a01:4f8:162:12e3::2 is routed to eth0 by Hetzner. The host is configured to be an IPv6 proxy with:

echo 1 > /proc/sys/net/ipv6/conf/all/forwarding
echo 0 > /proc/sys/net/ipv6/conf/all/accept_ra
sysctl -w net.ipv6.conf.all.proxy_ndp=1

A route is added to go thru br2003 and via the link local address of the instance:

ip -6 route add  2a01:4f8:162:12e3::2/128 via fe80::f816:3eff:fe12:80a dev br2003
ip -6 neigh add proxy 2a01:4f8:162:12e3::2 dev eth0

The IPv6 gateway provided by Hetzner is fe80::1 and must be set as the default route on the host with:

ip -6 route add default via fe80::1 dev eth0

Notes on OpenStack IPv6 support (untested)

The OpenStack IPv6 support is not activated for the above to work. To activate IPv6 support the

--use_ipv6=True

must be added to /etc/nova/nova.conf. Each network must also be associated with an IPv6 subnet. For instance:

nova-manage network create --label=myown \
  --vlan=2511 \
  --fixed_range_v4=10.145.230.0/24 \
  --fixed_range_v6=2a01:4f8:161:5304::0/64 \
  --gateway_v6=fe80::1 \
  --num_networks=1

An instance of radvd will be run for each bridge with a configuration such as /var/lib/nova/networks/nova-ra-br2011.conf:

interface br2011
{
   AdvSendAdvert on;
   MinRtrAdvInterval 3;
   MaxRtrAdvInterval 10;
   prefix 2a01:4f8:161:5304::/64
   {
        AdvOnLink on;
        AdvAutonomous on;
   };
};

It will be run for every bridge, not just those associated with a network that was created with the –fixed_range_v6 option.
A single IPv6 floating IP can be defined with:

nova-manage floating create --pool=v6pool --ip_range=2a01:4f8:161:5304::10 --interface=eth0

and will be bound to eth0. However, it will be added as 2a01:4f8:161:5304::10/32 instead of 2a01:4f8:161:5304::10/128

3 Replies to “routing ipv6 from Hetzner to an OpenStack instance”

  1. Hi,
    I have configure openstack on the hetzner server. i have a subnet. and can associate subnet ip to the instance but i am unable to ping the instance from the internet. can please share how i can configure the server to access the instance from internet. As i have search and find hetzner doesn’t provide briddging only routing.
    i will be thankful for your kind and positive response.

    thanks

  2. Hetzner *does* provide routed IPv6 prefixes for e.g. the purpose of attaching VMs. You just have to ask them via a support request as they have no automatism for it yet.
    You will then receive a prefix like 2a01:4f8:162:fff3::/64 (allocation growing downwards from ffff) which is routed to your 2a01:4f8:12e3::2.

Comments are closed.