KVM-NAT-Befehlszeile

KVM-NAT-Befehlszeile

Wie richte ich ein NAT-Netzwerk zwischen KVM-VM und Host richtig ein?

KVM-VM:

Keine Firewall installiert

$ sudo arp-scan -r 5 -t 1000 --interface=eth0 --localnet

10.0.2.2     52:55:0a:00:02:02    locally administered
10.0.2.3     52:55:0a:00:02:03    locally administered

$ ip r

default via 10.0.2.2 dev eth0 proto dhcp metric 100
10.0.2.0/24 dev eth0 proto kernel scope link src 10.0.2.15 metric 100

ifconfig

eth0: inet 10.0.2.15 netmask 255.255.255.0 broacast 10.0.2.255
      ether 52:54:00:12:34:56
lo: inet 127.0.0.1 netmask 255.0.0.0
      inet6 ::1

Gastgeber:

:~$ ip r

0.0.0.0/1 via 10.211.1.10 dev tun0 
default via 192.168.1.1 dev wlan0 proto dhcp metric 600 
10.21xxxxxxxx dev tun0 proto kernel scope link src 10.21xxxxx 
xxxxxxxxxxxx dev wlan0 
128.0.0.0/1 via 10.211.1.10 dev tun0 
192.168.1.0/24 dev wlan0 proto kernel scope link src 192.168.1.172 metric 600 
192.168.4.0/22 dev eth0 proto kernel scope link src 192.168.4.8 metric 100 

:~$ ifconfig

 eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
    inet 10.0.2.3  netmask 255.0.0.0  broadcast 10.255.255.255
    inet6 fe80::76c8:79b4:88d4:7f5c  prefixlen 64  scopeid 0x20<link>
    ether ec:8e:b5:71:33:6e  txqueuelen 1000  (Ethernet)
    RX packets 1700  bytes 194730 (190.1 KiB)
    RX errors 0  dropped 0  overruns 0  frame 0
    TX packets 2862  bytes 246108 (240.3 KiB)
    TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
    device interrupt 16  memory 0xe1000000-e1020000  

 lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
    inet 127.0.0.1  netmask 255.0.0.0
    inet6 ::1  prefixlen 128  scopeid 0x10<host>
    loop  txqueuelen 1000  (Local Loopback)
    RX packets 13251  bytes 7933624 (7.5 MiB)
    RX errors 0  dropped 0  overruns 0  frame 0
    TX packets 13251  bytes 7933624 (7.5 MiB)
    TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

tun0: flags=4305<UP,POINTOPOINT,RUNNING,NOARP,MULTICAST>  mtu 1500
    inet 10.211.1.69  netmask 255.255.255.255  destination 10.211.1.70
    inet6 fe80::a920:941c:ffa8:5579  prefixlen 64  scopeid 0x20<link>
    unspec 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00  txqueuelen 100  (UNSPEC)
    RX packets 4348  bytes 2242726 (2.1 MiB)
    RX errors 0  dropped 0  overruns 0  frame 0
    TX packets 3823  bytes 404190 (394.7 KiB)
    TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

wlan0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
    inet 192.168.1.172  netmask 255.255.255.0  broadcast 192.168.1.255
    inet6 fe80::651b:5014:7929:9ba3  prefixlen 64  scopeid 0x20<link>
    ether d8:55:a3:d5:d1:30  txqueuelen 1000  (Ethernet)
    RX packets 114455  bytes 117950099 (112.4 MiB)
    RX errors 0  dropped 0  overruns 0  frame 0
    TX packets 67169  bytes 14855011 (14.1 MiB)
    TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0 

~$ sudo arp-scan -r 5 -t 1000 --localnet

just hangs......

Host kann 10.0.2.2 nicht pingen

Keine Firewall aktivieren

Versucht

$ sudo ip route add default via 10.0.2.0
$ sudo ip route add default via 10.0.2.2
$ sudo ip route add default via 10.0.2.0/24

Kann NAT ohne Virsh funktionieren?

Kann NAT nur über die Befehlszeile repariert werden?

Aktualisieren:

$ sudo ip link add natbr0 type bridge
$ sudo ip link set dev natbr0 up
$ sudo ip link set dev eth0 up
$ sudo ip link set dev eth0 master natbr0

das funktioniert, um eth0 Slave zu kvm zu überbrücken - vm kann andere Computer im Netzwerk anpingen. aber nicht den Host @Tom Yan Antwort kombiniert mitArchlinux-Netzwerkbrückeerstellte oben Befehle, die andere Netzwerk-IPs anpingen können

Also habe ich versucht, die funktionierende Bridge-Verbindung zu ändern, um die Kommunikation zwischen Host und KVM zu ermöglichen.

Goal: host$ ping kvm

$ sudo ip link add natbr0 type bridge
$ sudo ip link set dev natbr0 up
$ sudo ip a add 10.0.2.1/24 dev natbr0
$ sudo kvm -m 3G -hdb /dev/sde  -nic bridge,br=natbr0
kvm$ sudo ip link add natbr0 type bridge
kvm$ sudo ip a add 10.0.2.2
kvm$ sudo ip link set dev natbr0 up
kvm can ping it self 

$ ping 10.0.2.2

PING 10.0.2.2 (10.0.2.2) 56(84) bytes of data
64 bytes from 10.0.2.2: icmp_seq=1 ttl=64 time=0.027 ms

aber kvm$ping 10.0.2.1

Destination Host Unreachable

Host$ Ping 10.0.2.2

(just hangs)

Bevorzugen Sie die Befehlszeile, um die Belastbarkeit von Prozess-/System-Grundlagen zu testen, gegenüber einer Menge Skripten, die anfälliger für Fehler sein können. - Die Befehlszeile funktioniert oder nicht und Fehler sind leichter zu verfolgen, zu isolieren und zu reproduzieren. Je nach Linux-Variante können bestimmte Skripte/Teile von Skripten (wie jene, die in den angebotenen XML-Alternativlösungen enthalten sind) funktionieren oder nicht. Wenn Bridging mit KVM auf jeder Linux-Variante durch Befolgen der obigen Befehle reproduziert werden kann... dann scheint es möglich, dass KVM-NAT auch mithilfe von CLI-Befehlen erreicht werden kann - nur um den Punkt dieses Beitrags zu verdeutlichen: CLI-Schritte zum NAT von KVM werden standardisierter sein und sind daher vorzuziehen.

im Allgemeinen @NikitaKipriyanov Antwort war der richtige Weg, dies war die Antwort, aber erforderte eine Anpassung an Befehl

$ sudo kvm -m 3G -hdb /dev/sde -net nic -net user,hostfwd=tcp::1810-:22

Mit dem Befehl „Tweak“ kann die VM wie üblich mit dem Internet kommunizieren und auch per SSH mit dem Host kommunizieren. Dank an @NikitaKipriyanov und @cnst für den Tweakhttps://stackoverflow.com/a/54120040

Der Benutzer muss eine SSH-Verbindung über Port 1810 unter Verwendung der Localhost-Adresse herstellen.

$ ssh p@localhost -p 1810

Antwort1

Die allgemeine Idee von NAT ist, dass Siesehe nichtübersetzte Adressen. Sie haben keine Routen zu ihnen. Sie existieren für Sie nicht. Sie sehen nur die Adressen, in die diese übersetzt wurden.

Im Fall von QEMU ist es nicht anders. In diesem Fall ist Ihr Host „draußen“, Ihre VM ist „drinnen“, sodass die VM niemals über die ihr zugewiesene Adresse aufgerufen werden kann. Sie haben die Adresse 10.0.2.2/24 der VM, aber wenn sie das Internet erreicht, werden ihre Pakete in 192.168.1.172 übersetzt.durch den QEMU-Prozess, daher betrachtet der Host diese Pakete als vom QEMU-Prozess erstellt und behandelt sie wie alle anderen Pakete, beispielsweise von einem lokal laufenden Webbrowser oder ähnlichem.

Wie greife ich vom Host aus auf eine VM zu? Wenn wir NAT haben, installieren wir, um dahinter versteckte Hosts zu erreichenDNATRegeln. Und auch hier ist der Fall von QEMU nicht anders, Sie müssen einige Regeln darin einrichten und können dann vom Host (oder von anderen Hosts, wenn Sie möchten) aus mit der VM kommunizieren, indem Sie Pakete an ausgewählte Ports desGastgeberAdresse.

Entsprechend derQEMU-Dokumentation, um DNAT-Regeln in seinem Benutzermodus-NAT einzurichten, verwenden Sie die hostfwdKlausel. Lassen Sie uns Folgendes in die Befehlszeile einfügen:

    -netdev user,id=usernet0,hostfwd=tcp::11111-:22 \
    -device virtio-net-pci,netdev=usernet0,mac=08:00:27:92:B0:51

Dann wird der TCP-Port 11111 durch den qemu-system-x86_64Prozess auf meiner Maschine belegt, und wenn Sie sich mit demlokaler HostPort 11111, die Verbindung wird zum Port 22 der VM hergestellt.

Die allgemeine Form ist hostfwd=hostip:hostport-guestip:guestport, aber wenn Sie weglassen hostip, ist es localhost, und wenn Sie weglassen guestip, ist es die erste „Nicht-Gateway“-Adresse innerhalb des Gastnetzwerks.

Mir ist aufgefallen, dass Sie erwähnt werden virsh. Laufen Sie libvirt? Dann handelt es sich um eine doppelte Frage. Siehe Kommentare.

Antwort2

Sie können eine Brücke verwenden, ohne eine Ihrer physischen Ethernet-Schnittstellen auf dem VM-Host ihr zu unterordnen.

Nehmen wir an, wir bleiben bei der Wahl des Subnetzes 10.0.2.0/24(was NICHT notwendig ist):

# ip l add natbr0 type bridge
# ip a add 10.0.2.1/24 dev natbr0

Erstellen Sie dann die folgende Datei:

$ echo 'allow natbr0' | sudo tee /etc/qemu/bridge.conf 
allow natbr0

Starten Sie dann qemu beispielsweise mit -nic bridge,br=natbr0oder -netdev bridge,br=natbr0,id=nb0 -device virtio-net,netdev=nb0, wodurch tapIhre VM dynamisch mit der Brücke verbunden wird (d. h. die tapSchnittstelle wird entfernt, sobald die VM heruntergefahren wird).

Sie müssen auch auf der VM eine statische IP konfigurieren:

# ip a add 10.0.2.2/24 dev ens3
# ip r add default via 10.0.2.1

Sofern Sie nicht auch einen DHCP-Server (z. B. mit dnsmasq) auf dem Host einrichten. Vergessen Sie nicht, den DNS-Server auch für die Verwendung innerhalb der VM zu konfigurieren.

Beachten Sie, dass VMs, die dieselbe Brücke verwenden, miteinander kommunizieren können, sofern Sie diese Kommunikation nicht auf irgendeine Weise blockieren (z. B. ebtables).

Die defaultRoute (und der zu verwendende DNS-Server) sind nur erforderlich, wenn die VM nach „außen“ gelangen soll. Wenn Sie sie nur benötigen, um mit dem VM-Host kommunizieren zu können, sollten Sie den zweiten Befehl überspringen und mit dem Lesen aufhören. (Nun, lesen Sie das P.S.)


Wenn Sie in der VM keinen bestimmten „öffentlichen“ DNS-Server verwenden möchten, wäre es wahrscheinlich am besten, z. B. dnsmasq auf dem Host als DNS-Weiterleitung zu konfigurieren, obwohl die Verwendung von DNAT zum Weiterleiten von DNS-Anfragen an z. B. 192.168.1.1für einfache Anfragen funktionieren sollte.

Dann müssen Sie die IP-Weiterleitung aktivieren:

# sysctl -w net.ipv4.ip_forward=1
net.ipv4.ip_forward = 1

Wenn Sie die IP-Weiterleitung von/zu bestimmten Netzwerkschnittstellen vermeiden möchten (z.B tun0) müssen Sie aus Sicherheitsgründen eine Firewall einrichten.Zum Beispiel:

# iptables -A FORWARD -i tun0 -j DROP
# iptables -A FORWARD -o tun0 -j DROP

Da Sie (VPN-)Tunnelrouten haben, die die defaultRoute praktisch außer Kraft setzen, wird der Verkehr von der VM zum Internet ebenfalls durch den Tunnel geleitet (es sei denn, Sie haben die obigen Beispielregeln hinzugefügt). Wenn Sie möchten, dass der Verkehr z. B. über Ihren Router geleitet wird, benötigen Sie Policy-Routing. Beispiel:

# ip ru add iif natbr0 lookup table 123
# ip r add 192.168.1.1 dev wlan0 table 123 # probably optional
# ip r add default via 192.168.1.1 table 123

Sie können auch verhindern, dass Ihre VMs Ihre LAN-Hosts erreichen können:

# iptables -A FORWARD -i natbr0 -d 192.168.1.0/24 -j DROP

Machen Sie Ausnahmen (beachten Sie das -I), wenn Sie DNS-Anfragen an Ihren Router umleiten möchten:

# iptables -I FORWARD -i natbr0 -d 192.168.1.1 -p tcp --dport 53 -j ACCEPT
# iptables -I FORWARD -i natbr0 -d 192.168.1.1 -p udp --dport 53 -j ACCEPT

Konfigurieren Sie abschließend iptables so, dass SNAT dynamisch (gemäß der ausgehenden Schnittstelle) für Ihr VM-Subnetz ausgeführt wird:

# iptables -t nat -A POSTROUTING -s 10.0.2.0/24 -j MASQUERADE

Beachten Sie, dass dies NICHT dazu gedacht ist und auch nicht verhindern wird, dass bestimmter Datenverkehr von „außen“ (Ihre physischen LAN-Hosts oder das Internet; der VM-Host zählt nicht) Ihre VMs erreichen kann. Es unterbricht lediglich als Nebeneffekt die Kommunikation, wenn die Quelladresse des antwortenden Datenverkehrs von den VMs geändert wird, bevor dieser weitergeleitet wird. Für eine ordnungsgemäße Isolierung benötigen Sie (zusätzliche) geeignete Regeln in der FORWARDKette. Erwägen Sie dort eine „zustandsbehaftete“ Einrichtung, wenn Sie dies benötigen.

Darüber hinaus können Sie DNS-Anfragen an den Host von den VMs an Ihren Router umleiten:

iptables -t nat -A PREROUTING -d 10.0.2.1 -p udp --dport 53 -j DNAT --to-destination 192.168.1.1
iptables -t nat -A PREROUTING -d 10.0.2.1 -p tcp --dport 53 -j DNAT --to-destination 192.168.1.1

10.0.2.1Dadurch können Sie es mehr oder weniger als DNS-Server in der VM verwenden .


PS: Alle oben genannten Manipulationen (außer der Erstellung von / write to /etc/qemu/bridge.conf) sind flüchtig, d. h. sie sind nach einem Neustart verschwunden (es sei denn, Ihre Distribution macht etwas Dummes). Ich werde nicht näher darauf eingehen, wie Sie sie dauerhaft machen können, da es verschiedene Möglichkeiten/Ansätze gibt und dies distributionsspezifisch sein kann.

verwandte Informationen