在 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
)都是易失性的,即一旦您重新啟動,它們就會消失(除非您的發行版做了一些愚蠢的事情)。我不會深入探討如何使它們持久存在,因為有不同的方式/方法,而且它可能是特定於發行版的。