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.