Weiterleiten von Ports an Gäste in libvirt / KVM

Weiterleiten von Ports an Gäste in libvirt / KVM

Wie kann ich bei Verwendung von NAT Ports auf einem Server, auf dem libvirt/KVM läuft, an angegebene Ports auf VMs weiterleiten?

Beispielsweise hat der Host eine öffentliche IP von 1.2.3.4. Ich möchte Port 80 an 10.0.0.1 und Port 22 an 10.0.0.2 weiterleiten.

Ich gehe davon aus, dass ich iptables-Regeln hinzufügen muss, bin mir aber nicht sicher, wo das angebracht ist und was genau angegeben werden muss.

Ausgabe von iptables -L

Chain INPUT (policy ACCEPT)
target     prot opt source               destination         
ACCEPT     udp  --  anywhere             anywhere            udp dpt:domain 
ACCEPT     tcp  --  anywhere             anywhere            tcp dpt:domain 
ACCEPT     udp  --  anywhere             anywhere            udp dpt:bootps 
ACCEPT     tcp  --  anywhere             anywhere            tcp dpt:bootps 

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         
ACCEPT     all  --  anywhere             10.0.0.0/24         state RELATED,ESTABLISHED 
ACCEPT     all  --  10.0.0.0/24          anywhere            
ACCEPT     all  --  anywhere             anywhere            
REJECT     all  --  anywhere             anywhere            reject-with icmp-port-unreachable 
REJECT     all  --  anywhere             anywhere            reject-with icmp-port-unreachable 

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         

Ausgabe von ifconfig

eth0      Link encap:Ethernet  HWaddr 00:1b:fc:46:73:b9  
          inet addr:192.168.1.14  Bcast:192.168.1.255  Mask:255.255.255.0
          inet6 addr: fe80::21b:fcff:fe46:73b9/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:201 errors:0 dropped:0 overruns:0 frame:0
          TX packets:85 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:31161 (31.1 KB)  TX bytes:12090 (12.0 KB)
          Interrupt:17 

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:16436  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

virbr1    Link encap:Ethernet  HWaddr ca:70:d1:77:b2:48  
          inet addr:10.0.0.1  Bcast:10.0.0.255  Mask:255.255.255.0
          inet6 addr: fe80::c870:d1ff:fe77:b248/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:6 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:0 (0.0 B)  TX bytes:468 (468.0 B)

Ich verwende Ubuntu 10.04.

Antwort1

Die neueste stabile Version von libvirt für Ubuntu ist Version 0.7.5. Sie verfügt nicht über einige neuere Funktionen (z. B. Skript-Hooks und Netzwerkfilter), die die automatische Netzwerkkonfiguration erleichtern. Hier erfahren Sie, wie Sie die Portweiterleitung für libvirt 0.7.5 unter Ubuntu 10.04 Lucid Lynx aktivieren.

Die folgenden iptables-Regeln sollten funktionieren:

iptables -t nat -I PREROUTING -p tcp -d 1.2.3.4 --dport 80 -j DNAT --to-destination 10.0.0.1:80
iptables -t nat -I PREROUTING -p tcp -d 1.2.3.4 --dport 22 -j DNAT --to-destination 10.0.0.2:22
iptables -I FORWARD -m state -d 10.0.0.0/24 --state NEW,RELATED,ESTABLISHED -j ACCEPT

Die standardmäßige KVM-NAT-Konfiguration bietet eine ähnliche Regel wie die dritte, die ich oben angegeben habe, lässt jedoch den Status „NEW“ aus, der für die Annahme eingehender Verbindungen wichtig ist.

Wenn Sie ein Startskript schreiben, um diese Regeln hinzuzufügen, und dabei nicht vorsichtig sind, überschreibt libvirt 0.7.5 diese, indem es seine eigenen einfügt. Um sicherzustellen, dass diese Regeln beim Start richtig angewendet werden, müssen Sie sicherstellen, dass libvirt initialisiert wurde.VorSie fügen Ihre Regeln ein.

Fügen Sie vor der Zeile die folgenden Zeilen zu /etc/rc.local hinzu exit 0:

(
# Make sure the libvirt has started and has initialized its network.
while [ `ps -e | grep -c libvirtd` -lt 1 ]; do
        sleep 1
done
sleep 10
# Set up custom iptables rules.
iptables -t nat -I PREROUTING -p tcp -d 1.2.3.4 --dport 80 -j DNAT --to-destination 10.0.0.1:80
iptables -t nat -I PREROUTING -p tcp -d 1.2.3.4 --dport 22 -j DNAT --to-destination 10.0.0.2:22
iptables -I FORWARD -m state -d 10.0.0.0/24 --state NEW,RELATED,ESTABLISHED -j ACCEPT
) &

Das sleep 10Obige ist ein Hack, um sicherzustellen, dass der Libvirt-Daemon die Möglichkeit hatte, seine iptables-Regeln zu initialisieren, bevor wir unsere eigenen hinzufügen. Ich kann es kaum erwarten, bis sie Libvirt Version 0.8.3 für Ubuntu veröffentlichen.

Antwort2

Es gibt eine Möglichkeit, die Portumleitung im laufenden Betrieb einzurichtenwenn der Gast das User-Mode-Networking nutzt, ich habe hier darüber gebloggt:

http://blog.adamspiers.org/2012/01/23/port-redirection-from-kvm-host-to-guest/

Dort können Sie die Einzelheiten sehen, aber der Einfachheit halber ist hier die Lösung, die ich herausgefunden habe:

virsh qemu-monitor-command --hmp sles11 'hostfwd_add ::2222-:22'

Dieser Einzeiler ist viel einfacher als die anderen Antworten, funktioniert aber nur in einigen Szenarien (Netzwerkstapel im Benutzermodus).

Antwort3

Eine „offiziellere“[1] Möglichkeit hierfür ist die Erstellung eines Hook-Skripts, wie es auf der libvirt-Website beschrieben wird:

http://wiki.libvirt.org/page/Networking#Forwarding_Incoming_Connections

... grundsätzlich wird dieses Skript aufgerufen, wenn ein KVM-Gast hochgefahren wird. Das Skript selbst fügt die entsprechenden iptable-Regeln hinzu (ähnlich wie Isaac Sutherlands Antwort oben) und fügt den Verbindungsstatus „NEU“ korrekt hinzu. Beachten Sie, dass Sie das Skript mit den richtigen Werten für Ihre Hosts und Ports ändern müssen.

[1] obwohl die libvirt-Dokumentation selbst sagt, dass dies eine Art Hack ist, stellen Sie sich vor

Antwort4

Unter Ubuntu 20.04 habe ich mir folgendes Skript erstellt, das als /etc/libvirt/hooks/allow-portfw(chmod +x) gespeichert wird:

#!/bin/bash

CHAIN=LIBVIRT_FWI
IPTCMD="iptables -L $CHAIN -vn"
FILTERCMD="grep -v -e Chain -e pkts -e reject-with -e DNAT"

while $IPTCMD | grep ESTABLISHED | grep -v DNAT >/dev/null
do
    IF=$($IPTCMD | $FILTERCMD | awk '{print $7}' | head -n1)
    NET=$($IPTCMD | $FILTERCMD | awk '{print $9}' | head -n1)
    iptables -D $CHAIN -o $IF -d $NET -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
    iptables -I $CHAIN 1 -o $IF -d $NET -m conntrack --ctstate DNAT,RELATED,ESTABLISHED -j ACCEPT
done

die Einstiegssituation ist, dass uns NEW übrigens das DNAT-Flag für die FORWARDING-Kette fehlt, welches automatisch erstellt wird.

sudo iptables -L LIBVIRT_FWI -vn
Chain LIBVIRT_FWI (1 references)
 pkts bytes target     prot opt in     out     source               destination         
1741K 2661M ACCEPT     all  --  *      virbr0  0.0.0.0/0            192.168.122.0/24     ctstate RELATED,ESTABLISHED
   38  1972 REJECT     all  --  *      virbr0  0.0.0.0/0            0.0.0.0/0            reject-with icmp-port-unreachable

Mein Skript fügt allen Definitionen das DNAT-Flag hinzu.

Auf diese Weise habe ich einfach die Portweiterleitung in iptables hinzugefügt mit

iptables -A PREROUTING -i mylanIF -p tcp --dport 3389 -j DNAT --to-destination 192.168.122.110:3389

Sie können die Pakete verwenden, iptables-persistentum diesen Status zu speichern (aber Sie müssen auf jeden Fall die Libvirt-Ketten aus dem Dump löschen).

Oder Sie verwenden ufwhierfür ein anderes Firewall-Skript.

Mein Skript basiert auf den Erkenntnissen aus dieser Adressehttps://www.cyberciti.biz/faq/kvm-forward-ports-to-guests-vm-with-ufw-on-linux/

verwandte Informationen