
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 10
Obige 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-persistent
um diesen Status zu speichern (aber Sie müssen auf jeden Fall die Libvirt-Ketten aus dem Dump löschen).
Oder Sie verwenden ufw
hierfü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/