IPv6 Support für OpenVZ Gäste auf Debian-basis

Ich habe eine Weile gekämpft, um den IPv6 Support für meine OpenVZ Gäste auf einem Debian Lenny zum Laufen zu kriegen. Im Wesentlichen, ist es auch garkeine Raketenwissenschaft, wenn man erstmal weiß, wo denn genau das Problem liegt.

Meine gesammelten Erkenntnisse möchte ich euch nicht vorenthalten.


Ausgangsszenario

Zugrunde liegendes Betriebssystem ist ein Debian Lenny (funktioniert vermutlich auch mit späteren Releases), auf dem bereits grundsätzlicher IPv6 Support eingerichtet ist.

Am Einfachsten überprüft man dies mit dem Kommando:

# ip -0 a

In der Ausgabe sollten IPv6 Link-Local Adressen zu sehen sein, die mit dem Block fe80 beginnen, bspw. fe80::2a0:86ef:ff2d:93a4/64.

Selbstverständlich muss IPv6 Support auf dem Internet-Uplink anliegen und geroutet werden, unabhängig davon, ob es sich um nativen Support oder einen Tunnel handelt.

Desweiteren gehen wir in diesem Fallbeispiel davon aus, dass es auf dem Host ein physikalisches Interface eth0, sowie ein virtuelles Interface venet0 gibt, und ansonsten keine weiteren Interfaces vorhanden sind.

Der Prefix, von dem hier ausgegangen wird, lautet:

2a02:bace:bace::/48

Unser Default-Gateway ins Internet ist ein DSL-Router irgendwo im LAN. Wir folgen der Konvention und konfigurieren hier die erste Host-IP des Prefixes.

2a02:bace:bace::1/64


Konfiguration des Hosts

Wenn der IPv6 Support im Betriebssystem fertig eingerichtet ist, beginnen wir mit der Konfiguration von OpenVZ.

Hierfür editiert man die Datei /etc/vz/vz.conf und fügt folgende Zeilen hinzu:

IPV6="yes"
IP6TABLES="ip6_tables ip6table_filter ip6table_mangle ip6t_REJECT"

Anschließend muss der Daemon durchgestartet werden.

# /etc/init.d/vz restart

Auf dem Host wird irgendeine zufällige Host-IP aus unserem Prefix konfiguriert und eine Default-Route eingerichtet.

# ip a a 2a02:bace:bace::bace/64 dev eth0
# ip r a default via 2a02:bace:bace::1

Damit diese IP auch nach jedem Neustart zur Verfügung steht, muss sie in die Datei /etc/network/interfaces eingetragen werden.

iface eth0 inet6 static  
    address 2a02:bace:bace::bace  
    netmask 64  
    gateway 2a02:bace:bace::1

Ein kurzer Test, ob das Internet via IPv6 erreichbar ist und weiter geht`s.

# ping6 -c3 google.de

Damit der Host IPv6 Packete seiner Gäste forwarded, müssen einige Sysctl Parameter gesetzt werden. Diese werden am Besten direkt ans Ende der Datei /etc/sysctl.conf geschrieben...

net.ipv4.conf.eth0.proxy_arp=1
net.ipv6.conf.default.forwarding = 1
net.ipv6.conf.all.forwarding = 1
net.ipv6.conf.default.proxy_ndp = 1
net.ipv6.conf.all.proxy_ndp = 1

... und dann geladen...

# sysctl -p /etc/sysctl.conf

Konfiguraiton der Gäste

IPv6 Adresen werden genau so konfiguriert, wie IPv4 Adressen.

# vzctl set $VEID --ipadd 2a02:bace:bace::2 --save

Host und Gast sollten sich nun erreichen können.

#host# ping6 -c3 2a02:bace:bace::2
#gast# ping6 -c3 2a02:bace:bace::bace

Pitfall

Wenn die Gäste nicht in der Lage sind das Internet zu erreichen, liegt es daran, dass die ARP-Requests, die vom Router stammen, vom Host nicht an seine Gäste weitergeleitet werden. Somit weiß der Router nicht wohin er die Antwortpackete leiten soll. Vom Gast aus stellt sich die Situation so dar, als ob es keine Route vom Host ins Internet gäbe, was aber nicht den Tatsachen entspricht. Die Route ist da, aber die Rueckroute nicht.

Damit der Host ARP-Requests, die für seine Gäste bestimmt sind, durchreicht, muss er als Neighbor-Proxy für alle seine Gäste konfiguriert werden.

# ip -6 n add proxy 2a02:bace:bace::2 dev eth0

Hierbei ist die IPv6-Adresse die des Gastes und das Device das physische Interface des Hosts.

Um auch diese Konfiguration persistent gegen Neustarts zu kriegen, habe ich ein kleines if-up Script geschrieben, das sich stumpf alle IPv6-Adressen aller Gäste holt und als Proxy konfiguriert.

Hierzu legt man die Datei /etc/network/if-up.d/ipv6vzneighproxy an und schreibt folgende Zeilen hinein.

prefix="${1:-2a02}"
ext_iface="${2:-eth0}"

guests="$(grep -r "$prefix" /etc/vz/conf/*.conf | sed 's/.*\(2a02\)/\1/' | tr '"' ' ')"
for ip in $guests; do
    ip -6 n add proxy ${ip} dev ${ext_iface}
done

Done.