KVM nat命令列

KVM nat命令列

在 KVM 虛擬機器和主機之間設定 NAT 網路的正確方法是什麼?

KVM虛擬機器:

未安裝防火牆

$ 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 資源

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

如果配置

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

主持人:

:~$ 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......

主機無法 ping 通 10.0.2.2

沒有啟用防火牆

嘗試過

$ 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

NAT 可以在沒有 virsh 的情況下工作嗎?

NAT 只能透過命令列修復嗎?

更新:

$ 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

它可以將 eth0 從屬設備橋接到 kvm - vm 可以 ping 通網路上的其他電腦。但不是主持人@Tom Yan 的回答結合archlinux-網路橋上面建立的命令可以 ping 其他網路 ip

所以我嘗試更改工作橋接連接以允許主機和 kvm 進行通訊。

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 

$ 平 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

但 kvm$ping 10.0.2.1

Destination Host Unreachable

主機$ ping 10.0.2.2

(just hangs)

喜歡用命令列來測試流程/系統的彈性,而不是使用許多可能更容易失敗的腳本。 - 命令列是否有效,錯誤更容易追蹤、隔離和重現。根據 Linux 的風格,某些腳本/腳本的一部分(例如那些包含在所提供的 xml 替代解決方案中的腳本)可能有效,也可能無效。如果透過執行上面的命令可以在任何 Linux 風格上重現 kvm 橋接...那麼 kvm NAT 似乎也可以使用 cli 命令來實現 - 只是為了澄清這篇文章的要點,NAT kvm 的 cli 步驟將是更標準化,所以更可取。

一般來說@NikitaKipriyanov 的答案是正確的道路,這就是答案,但需要調整命令

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

使用指令tweak vm可以像預設一樣與網路通信,也可以透過ssh與主機通訊。感謝 @NikitaKipriyanov 和 @cnst 的調整https://stackoverflow.com/a/54120040

使用者需要使用本機主機位址使用連接埠 1810 進行 ssh

$ ssh p@localhost -p 1810

答案1

NAT 的共同想法是:沒看到翻譯後的地址。你沒有通往他們的路線。他們不為你而存在。您只能看到被轉換成的位址。

QEMU 的情況也沒有什麼不同。在這種情況下,您的主機位於“外部”,您的虛擬機器位於“內部”,因此虛擬機器永遠無法透過其指派的位址存取。您的虛擬機器位址為 10.0.2.2/24,但當它到達 Internet 時,其封包會轉換為 192.168.1.172透過 QEMU 進程,因此主機認為這些資料包是由 QEMU 進程創建的,並像對待任何其他資料包一樣對待它們,例如來自本地運行的 Web 瀏覽器或類似的資料包。

如何從主機存取虛擬機器?當我們有 NAT 時,為了存取隱藏在其後面的主機,我們安裝DNAT規則。再說一遍,QEMU 的情況沒有什麼不同,您必須在其中設定一些規則,然後您可以透過將封包傳送到選定的連接埠來從主機(如果需要,也可以從其他主機)與虛擬機器進行通訊。主持人地址。

根據QEMU 文檔,要將 DNAT 規則設定到其使用者模式NAT 中,請使用該hostfwd子句。讓我們在其命令列中引入以下內容:

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

那麼,tcp埠11111就會被我機器上的進程佔用qemu-system-x86_64,如果你連接到本機連接埠 11111,將連接到 VM 的連接埠 22。

一般形式是hostfwd=hostip:hostport-guestip:guestport,但如果省略hostip,它將是 localhost ,如果省略guestip,它將是訪客網路內的第一個「非網關」位址。

我注意到有人提到了你virsh。你在跑步嗎libvirt?那麼問題就重複了;看評論。

答案2

您可以使用網橋,而無需將 VM 主機上的任何實體乙太網路介面從屬於它。

假設我們堅持選擇子網10.0.2.0/24(這不是必要的):

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

然後建立以下文件:

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

然後使用eg-nic bridge,br=natbr0或啟動qemu -netdev bridge,br=natbr0,id=nb0 -device virtio-net,netdev=nb0,這將以tap動態方式將您的VM連接到橋接器(tap即一旦VM關閉,該介面將被刪除)。

您還需要在虛擬機器上設定靜態 IP:

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

除非您也在主機上設定了 DHCP 伺服器(例如 dnsmasq)。不要忘記配置 DNS 伺服器以在虛擬機器內部使用。

請注意,使用同一橋接器的虛擬機器可以相互通信,除非您以某種方式(例如 ebtables)阻止此類通信。

default只有當您希望虛擬機器能夠到達「外部」時,才需要路由(以及要使用的 DNS 伺服器)。如果您只需要它能夠與VM主機通信,則應該跳過第二個命令並可以停止閱讀。 (好吧,請閱讀P.S.


如果您不想在虛擬機器中使用特定的「公共」DNS 伺服器,最好將主機上的 example dnsmasq 配置為 DNS 轉發器,儘管使用 DNAT 將 DNS 請求轉送至eg應該192.168.1.1適用於基本請求。

然後您需要啟用 IP 轉送:

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

如果您想避免從/到某些網路介面的 IP 轉發(例如 tun0)出於安全原因,您需要設定防火牆。例如

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

由於您擁有實際上覆蓋路由的 (VPN) 隧道路由default,因此從虛擬機器到 Internet 的流量也將進入隧道(除非您新增了上面的範例規則)。如果您希望流量透過路由器等進行,則需要政策路由。例如:

# 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

您也可以阻止虛擬機器存取 LAN 主機:

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

-I如果您要將 DNS 請求重新導向到路由器,請例外(請注意):

# 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

最後,設定 iptables 為您的 VM 子網路動態執行 SNAT(根據出站介面):

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

請注意,這並不是為了也不會完全阻止來自「外部」(您的實體 LAN 主機或 Internet;VM 主機不計算在內)的某些流量能夠到達您的 VM。當來自虛擬機器的回覆流量的來源位址在轉送出去之前發生變更時,它只會中斷通訊作為副使用。為了正確隔離,您將需要鏈中的(附加)適當規則FORWARD。如果您有這樣的需要,請考慮在那裡進行「有狀態」設定。

此外,您可以將對主機的 DNS 請求從虛擬機器重新導向到路由器:

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.1在虛擬機器中用作 DNS 伺服器。


PS 上面的所有操作(除了創建 / 寫入/etc/qemu/bridge.conf)都是易失性的,即一旦您重新啟動,它們就會消失(除非您的發行版做了一些愚蠢的事情)。我不會深入探討如何使它們持久存在,因為有不同的方式/方法,而且它可能是特定於發行版的。

相關內容