Update 04.03.2011: Das unten Beschriebene ist nicht nötig, wenn man im Robot für die IP-Adresse eine MAC-Adresse konfiguriert. Dafür gibt es (inzwischen?) einen recht unauffälligen Button in der IP-Konfiguration unter oder neben der IP-Adresse.
Gestern und heute habe ich versucht, auf einem neuen Server bei Hetzner eine KVM aufzusetzen. Das ging auch alles ganz gut von der Hand, es war ja nicht das erste mal. Verwendet habe ich diese Anleitung. Schwierig wurde es aber, als ich versuchte, das Netzwerk einzurichten. Bemerkbar machte sich das schon bei der Installation. Der Gast konnte keinen Timeserver erreichen, und auf die Paketquellen konnte nicht zugegriffen werden. Über die Probleme bei der Intsallation habe ich erst einmal hinweggesehen und mich auf dem neuen Gast eingeloggt. Gast und Wirt konnten sich gegenseitig erreichen, aber nach und von draußen ging nichts. Der erste eher intuitive Handgriff, den ich vorgenommen habe, war, das IP-Forwarding auf dem Wirt einzuschalten. Danach funktionierte scheinbar alles. Also schnell mit iptables einen Paketfilter hochziehen, dann sollte es gut sein. Ein wenig stutzig wurde ich dabei schon, da eine Bridge ja einen Layer unter IP arbeitet, IP-Forwarding sollte deshalb gar keine Rolle spielen. Es wurde dann auch eine langwierige Geschichte. Ich habe hin- und herkonfiguriert, um letztendlich festzustellen, dass nach 10 Pings grundsätztlich Schluss ist. Egal, wie das Forwarding und der Paketfilter konfiguriert sind.
Etwas klarer wurde die Sache, als ich mir mal mit tcpdump den Netzwerkverkehr im Detail angeguckt habe. Wenn ich vom Gast nach draußen gepingt habe, waren die ausgehenden Pakete auf allen relevanten Interfaces zu sehen. Die eingehenden kamen aber nur bis zum Wirt. Hetzner verwendet wohl gemanagte Switches, bei denen die Ports an IP- und an MAC-Adresse gebunden sind. Das üblich Setup mit der Bridge konnte ich also vergessen. Nun war der Punkt gekommen, Google anzuschmeißen. Und siehe, da gibt's schon eine Anleitung. Richtig gefallen hat mir die nicht, weil sie viel individuelle Konfiguration pro Maschine erfordert. Ich will möglichst nah an den Defaults bleiben, einfach, um mir Arbeit zu sparen. Als Inspiration hat die Aneitung aber durchaus getaugt.
Ich hab's also etwas anders gelöst. eth0 auf dem Host habe ich wie folgt konfiguriert (/etc/network/interfaces). wirts-adresse, hetzner-gateway und gast-adresse sind im Folgenden jeweils durch die IP-Adressen zu ersetzen.
auto eth0
iface eth0 inet static
address wirts-adresse
netmask 255.255.255.255
gateway hetzner-gateway
pointopoint hetzner-gateway
Hetzner schreibt bei der Installation eine Regel in die Netzwerkkonfiguration, mit der eine Extraroute gesetzt wird. Die kann man sich damit schon einmal sparen.
Statt eine Bridge aufzubauen, die eth0 mit umfasst, habe ich eine leere Bridge ergänzt:
auto br0
iface br0 inet static
address wirts-adresse
netmask 255.255.255.255
bridge_ports none
bridge_fd 9
bridge_hello 2
bridge_maxage 12
bridge_stp off
„bridge_ports none” ist möglicherweise nicht erlaubt, aber ohne diese Anweisung startet die Bridge nicht, und ohne das Argument „none” wird die Konfigurationsdatei als fehlerhaft bemängelt. Mit „none” erhalte ich eine leere Bridge, ohne dass irgendwelche Meldungen erscheinen.
Nun ist fast alles beim Alten. Die Virtuelle Maschine hängt sich ohne weitere Konfiguration beim Start in die Bridge, an der in diesem Setup eth0 nicht teilnimmt. Um die virtuelle Maschine zu erreichen, habe ich eine Route auf die Extra-IP-Adresse eingerichtet, indem ich an den Block für das Interface br0 angehängt habe:
up route add gast-adresse br0
Die neue IP-Adresse irgendwo anzugeben, bleibt mir sowieso nicht erspart, sobald Hetzner mir eine neue IP-Adresse zuordnet. Insofern ist der Aufwand zu vernachlässigen. Jetzt muss nur noch die Netzwerkkonfiguration des Gastes angepasst werden, ebenfalls in /etc/network/interfaces:
iface eth0 inet static
address gast-adresse
netmask 255.255.255.255
gateway wirts-adresse
pointopoint wirts-adresse
Das mit den Nameservern lasse ich hier mal aus. Nach einem Neustart des Netzwerks können sich Gast und Wirt gegenseitig erreichen.
Da die Pakete jetzt nich mehr über eine Bridge laufen sondern geroutet werden müssen, muss auf dem Wirt IP-Forwarding eingeschaltet werden. Dazu ändert man eine Zeile in /etc/sysctl.conf:
net.ipv4.ip_forward=1
Danach kann man neu booten, es genügt aber auch „/etc/init.d/procps start” aufzurufen, „sysctl -p /etc/sysctl.conf” auszuführen oder die 1 direkt in die Datei im proc-Dateisystem zu schreiben. Nun lässt sich die virtuelle Maschine auch von außen erreichen.
Damit niemand böses IP-Spoofing betreibt, sollte man nun noch auf dem Wirt mit iptables einen Paketfilter einrichten, der zumindest den Verkehr blockt, der auf dem Wirt über eth0 reinkommt und da auch wieder raus will. Ein kurzer Regelsatz kann so aussehen:
iptables -F OUTPUT
iptables -F INPUT
iptables -F FORWARD
iptables -P OUTPUT DROP
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A OUTPUT -m state --state NEW -j ACCEPT
iptables -A INPUT -i lo -m state --state NEW -j ACCEPT
iptables -A INPUT -p icmp -j ACCEPT
iptables -A INPUT -p tcp --dport ssh -m state --state NEW -j ACCEPT
iptables -A FORWARD -i br0 -o eth0 -m state --state NEW -j ACCEPT
iptables -A FORWARD -i eth0 -o br0 -m state --state NEW -j ACCEPT
iptables -A FORWARD -i br0 -o br0 -m state --state NEW -j ACCEPT
Ansonsten gibt genug detaillierte Anleitungen im Netz. Auf jeden Fall sollte man dafür sorgen, dass das Regelwerk den nächsen Reboot überlebt.