OpenVZ VE mit in- und externer IP

stimpy

New Member
Ahoi!

Ich habe da ein Problem mit OpenVZ, welches ich gerade auf einem neuen Rootserver bei Hetzner einrichte. Bisher hatte ich dort (linux-)vserver(.org) im Einsatz und das hier sind meine ersten Gehversuche mit OpenVZ.
Entsprechend falsch und/oder daemlich kann es sein, was ich hier verzapfe. Habt Nachsicht.. ;)
Auch habe ich mein Problem ebenfalls im internen Hetzner support-forum beschrieben. Klassischer Doppelpost also - ich bin verzweifelt.. ;) Ich werde die richtige Antwort, wo auch immer ich sie finde, in beide Foren uebertragen, so dass alle etwas davon haben - keine Angst...

Aaalso:

Manche meiner VEs sollen 2 IPs haben. Eine interne und eine externe. Anfragen in's Internet sollen ueber die externe IP laufen und Anfragen an das interne subnet ueber die interne ip - und genau das ist mein Problem:
Ich kann zwar von VE101 auf die interne IP von VE102 verbinden, dabei wird jedoch immer die externe IP von VE101 verwendet. Wenn ich also z.B. mit ein "nc 192.168.35.102 22" mache, taucht im authlog von VE102 die externe IP von VE101 auf, nicht die 192.168.35.101. (Drehe ich in der $VEID.conf die beiden IP-Adressen um, ist er genau umgekehrt. Er verwendet also immer automatisch die erste angegebene IP aus der $VEID.conf.)

Um das zu umgehen, habe ich im Laufe des gestrigen Tages ein paar Howtos befolgt und Dinge ausprobiert.
Als erstes die Methode, die tatsaechlich zum Erfolg fuehrt. Allerdings kommt sie mir verdammt unschoen vor und bei meinen Recherchen habe ich von viel schoeneren Methoden gelesen, die bei mir allerdings nicht funktionierten.. (siehe unten..)

Was funktioniert:
Auf dem Host-Rechner ein dummy-interface mit einer IP aus dem gewuenschen internen subnet erstellen:

/etc/network/interfaces
Code:
(...)
auto dummy0
iface dummy0 inet static
        address 192.168.35.1
        netmask 255.255.255.0
        network 192.168.35.0
        broadcast 192.168.35.255
Und den VEs, z.B. ueber proxmox, weitere IPs aus diesem internen Subnetz geben.

Dann in den VEs jeweils folgenden Befehl ausfuehren:
Code:
ve101:/# ip route add 192.168.35.0/24 dev venet0 src 192.168.35.101
Ob es hierbei wichtig ist, dass auf dem Host-Rechner Masquerading fuer eth0 und dummy0 aktiviert war, weiss ich nicht - war es aber auf jeden Fall:

Code:
host:/#/sbin/iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
Das funktioniert. Ich komme raus, mit der externen IP und fuer's interne subnetz wird nun auch die interne IP verwendet. Super. Aber der letzte Schritt ist doch unschoen:
Das "ip route add foo.." kann ich in keinem der openvz startup-scripts unterbringen, da die alle zu frueh im Startprozess der VEs laufen. Also bliebe mir nur, das jeweils auf den VEs in irgendeiner Form im init-prozess unter zu bringen.. :/

Wesentlich schoener fand ich aber das, was auf der englischen proxmox-seite im Hetzner-Wiki steht - die scheint ja wesentlich aktueller zu sein, als die deutsche:

Genau so habe ich es umgesetzt. Also sieht meine aktuelle Konfiguration nun so aus:

/etc/network/interfaces
Code:
auto lo
iface lo inet loopback

# device: eth0
auto eth0
iface eth0 inet static
        address xxx.xxx.75.248                    # Main IP
        netmask 255.255.255.255
        gateway xxx.xxx.75.225                    # Gateway Main IP
        pointopoint xxx.xxx.75.225                # Gateway Main IP
        post-up echo 1 > /proc/sys/net/ipv4/conf/eth0/proxy_arp

auto vmbr0
iface vmbr0 inet static
        address xxx.xxx.75.248                    # Main IP
        netmask 255.255.255.255
        bridge_ports none
        bridge_stp off
        bridge_fd 0

auto vmbr1
iface vmbr1 inet static
        address  192.168.35.1
        netmask  255.255.255.0
        bridge_ports none
        bridge_stp off
        bridge_fd 0
        post-up echo 1 > /proc/sys/net/ipv4/ip_forward
        post-up iptables -t nat -A POSTROUTING -s '192.168.35.0/24' -o eth0 -j MASQUERADE
        post-down iptables -t nat -D POSTROUTING -s '192.168.35.0/24' -o eth0 -j MASQUERADE

ein "ip route list" auf dem Host zeigt alle gewuenschten Routen, sowohl fuer die internen IPs, als auch fuer die externen IPs aus dem zusaetzlichen Subnetz, die ich den VEs zugeordnet habe.
Code:
192.168.35.106 dev venet0  scope link 
192.168.35.104 dev venet0  scope link 
192.168.35.105 dev venet0  scope link 
xxx.xxx.75.225 dev eth0  proto kernel  scope link  src xxx.xxx.75.248 
xxx.xxx.110.85 dev venet0  scope link 
xxx.xxx.110.84 dev venet0  scope link 
xxx.xxx.110.83 dev venet0  scope link 
192.168.35.102 dev venet0  scope link 
192.168.35.103 dev venet0  scope link 
xxx.xxx.110.82 dev venet0  scope link 
xxx.xxx.110.81 dev venet0  scope link 
192.168.35.101 dev venet0  scope link 
192.168.35.0/24 dev vmbr1  proto kernel  scope link  src 192.168.35.1 
default via xxx.xxx.75.225 dev eth0
Funktioniert auch so weit, bis auf, dass wieder die externen IPs fuer Verbindungen auf interne IPs verwendet werden.. Alles beim Alten, also. Loesung wieder nur per ip route add, wie oben..

Ein weiterer, haeufiger auftauchender Loesungsvorschlag ist der, die subnetmasks der beiden venet-devices in der VE mittels eines if-up.d script zu verstellen, welches ungefaehr so aussieht:

/etc/network/if-up.d/routing
Code:
#!/bin/bash
logger foo # zum Test, ob das Script ueberhaupt ausgefuehrt wird. s.u...
if [ "${IF_ADDRESS:0:6}" = "xx.yy." ]; then
        echo "AlReece45: $IFACE, IP Address $IF_ADDRESS marked as internal"
        ifconfig "$IFACE" netmask 255.255.0.0 up
fi
if [ "${IF_ADDRESS:0:11}" = "xxx.yy.zzz." ]; then
        echo "AlReece45: $IFACE, IP address $IF_ADDRESS marked as external"
        ifconfig "$IFACE" netmask 255.255.255.0 up
fi
exit 0
Semi-schoen, wuerd ich sagen.. ;) Aber auch wurscht, denn scheinbar wird dieses script ueberhaupt nicht ausgefuehrt. (evtl. weil ich venet und nicht veth verwende?)
Auf jeden Fall hinterlaesst es keine Eintraege im syslog..

Ich bin verwirrt und verzweifelt.. ;) Waere schoen, wenn Ihr mir helfen koenntet.. :)

Gruss,
stimpy

*edit*
Sorry, durch das Rumkopieren sind ein paar Infos auf der Strecke geblieben, die ich zwar nicht fuer wichtig halte, da dieser Teil der config funktioniert, aber evtl. interessiert es den einen oder anderen geneigten Helfer ja doch:
Es handelt sich um einen EQ4 von Hetzner. Darauf laeuft Debian Squeeze mit OpenVZ und Proxmox.
Der Host-Rechner hat die Main-IP und die VEs bekommen IPs aus einem zusaetzlichen /27 Subnetz von Hetzner.. - Das funktioniert auch einwandfrei und steht hier nur nochmal der Komplettheit halber..
 
Last edited by a moderator:
Wah, hör auf mit diesem Bridge Gefrickel. ;)
Dein allererster Ansatz war schon richtig. venet + 2 IPs.

Die öffentliche IP wird als erste IP und die private als zweite IP eingetragen. Innerhalb der VE setzt du dann einfach nur noch eine Route ala
Code:
ip r a 10.0.0.0/24 src 10.0.0.2 dev venet0:1
Wobei 10.0.0.2 in dem Fall die private IP der VE ist. ;)
 
Boah, wie haesslich.. :(
Aber okay - dann hab ich das zumindest schonmal bestaetigt bekommen. Langt mir, um das jetzt erstmal so einzurichten.
Wenn sich hier aber noch einer befleissigt fuehlt, eine bessere Methode zu posten: Nur raus damit! ;)

So weit erstmal: Danke! :)
 
Es gibt nichts besseres oder einfacheres. Du hast ein System mit 2 Interfaces. Er muss immer innerhalb der VE entscheiden, für welches Ziel er welche Route nimmt. Somit hast du immer so eine Route in der VE.
Egal ob du nun mit venet oder veth und Bridges arbeitest. Letzteres macht das ganze nur unnötigt komplex und fehleranfällig. An dem eigentlichen Problem änderst du Prinzipbedingt aber überhaupt nichts. ;)

Edit:
Btw, in Virtuozzo ist seit letztem Sommer ein Feature enthalten, mit dem es möglich wird, nicht nur einzelne IPs sondern auch Subnetmasken zuzuweisen. Damit übernimmt Virtuozzo diese Route. In OpenVZ ist dies noch nicht enthalten.
 
Hey, cool, danke fuer diese komplette Erklaerung! :) Jetzt hab ich auch was daraus gelernt.. ;)

Hab mir eben ein kleines initscript gebastelt, was das uebernimmt:

Code:
#!/bin/bash

# -------------------------------------------------
# config start
# ------------------------------------------------

intsubnet="192.168.222.0/24"  # internes subnet
extsubnet="178.63.222.222/28"  # externes subnet

# -------------------------------------------------
# config end
# ------------------------------------------------

IFCONFIG=/sbin/ifconfig
IP=/bin/ip
GREP=/bin/grep
SED=/bin/sed


do_start() {
        $IP route add 192.168.35.0/24 dev venet0 src $intip
        return $?
}
do_stop() {
        $IP route del 192.168.35.0/24 dev venet0 src $intip
        return $?
}
do_status() {
        $IP route list
        return 0
}
do_restart() {
        do_stop
        case "$?" in
                0|1)
                        do_start
                        return "$?"
                ;;
                2) return 2 ;;
        esac
}


intcheck=$( echo "$intsubnet" |cut -d "." -f -3 )
extcheck=$( echo "$extsubnet" |cut -d "." -f -3 )

intip=$( $IFCONFIG |$GREP "$intcheck" |$SED 's/^.*inet addr:\([^\ ]*\).*$/\1/' )
extip=$( $IFCONFIG |$GREP "$extcheck" |$SED 's/^.*inet addr:\([^\ ]*\).*$/\1/' )

if [ -n "$intip" ] && [ -n "$extip" ]
then

        case "$1" in
                start)  
                        echo -n "Setting VZ Route.. "
                        do_start
                        case "$?" in
                                0|1) echo "done." ;;
                                2) echo "ERROR!" ;;
                        esac
                        exit "$?"
                ;;
                stop)   
                        echo -n "Unsetting VZ Route.. "
                        do_stop
                        case "$?" in
                                0|1) echo "done." ;;
                                2) echo "ERROR!" ;;
                        esac
                        exit "$?"
                ;;
                status)
                        echo "Current routes: "
                        do_status
                ;;
                restart|force-reload)
                        echo -n "Reloading VZ Route.. "
                        do_restart
                        case "$?" in
                                0|1) echo "done." ;;
                                2) echo "ERROR!" ;;
                        esac
                        exit "$?"
                ;;
                *)
                        echo "Usage: vzrouting {start|stop|restart|force-reload}" >&2
                        exit 3
                ;;
        esac
else
        echo "No route required..."
fi

Daran gekoppelt gleich die naechste Frage: Gibts nen besseren Platz, um das zu machen, als ein initscript? Ich hatte es mit nem Script in /etc/network/if-up.d/ versucht - das wird aber gar nicht erst ausgefuehrt. Ich nehme an, weil ich venet verwende und kein veth..
 
Back
Top