在 KVM vm 和主机之间设置 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 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
如果配置
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 slave 桥接到 kvm - vm 可以 ping 网络上的其他计算机。但不是主机@Tom Yan 的回答结合上面创建的可以ping其他网络IP的命令的archlinux-Network_bridge
所以我试图改变工作桥连接以允许主机和 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 的桥接......那么似乎也可以使用 cli 命令实现 kvm NAT - 只是为了澄清这篇文章的重点,NAT kvm 的 cli 步骤将是更标准化,所以更可取。
通常@NikitaKipriyanov 的答案是正确的道路,这是答案,但需要调整命令
$ sudo kvm -m 3G -hdb /dev/sde -net nic -net user,hostfwd=tcp::1810-:22
使用命令调整 vm 可以像默认一样与互联网通信,也可以通过 ssh 与主机通信。感谢@NikitaKipriyanov 和@cnst 的调整https://stackoverflow.com/a/54120040
用户将需要使用 localhost 地址使用端口 1810 进行 ssh
$ ssh p@localhost -p 1810
NAT 的常见想法是您看不到已转换的地址。你没有通往他们的路线。它们不为你而存在。您只能看到被翻译成的地址。
QEMU 案例没有什么不同。在这种情况下,您的主机在“外部”,您的虚拟机在“内部”,因此分配给它的地址永远无法访问虚拟机。您有虚拟机的 10.0.2.2/24 地址,但是当它到达 Internet 时,它的数据包被QEMU 进程转换为 192.168.1.172 ,因此主机认为这些数据包是由 QEMU 进程创建的,并将它们视为任何其他数据包,比如说,从本地运行的网络浏览器或类似的东西。
如何从主机访问虚拟机?当我们有 NAT 时,为了到达隐藏在它后面的主机,我们安装DNAT规则。同样,QEMU 的情况也不例外,您必须在其中设置一些规则,然后您可以通过将数据包发送到主机的选定端口来从主机(如果需要,可以从其他主机)与 VM通信地址。
根据QEMU 文档,要将 DNAT 规则设置到其用户模式 NAT 中,请使用该
hostfwd
子句。让我们在其命令行中引入以下内容:然后,tcp 端口 11111 将被我机器上的进程占用
qemu-system-x86_64
,如果你连接到localhost端口 11111,则会连接到 VM 的 22 端口。一般形式是
hostfwd=hostip:hostport-guestip:guestport
,但如果省略hostip
,它将是 localhost ,如果省略guestip
,它将是访客网络中的第一个“非网关”地址。我注意到你被提到了
virsh
。你在跑步libvirt
吗?那么问题是重复的;看评论。您可以使用网桥,而无需将 VM 主机上的任何物理以太网接口奴役到它。
假设我们坚持选择子网
10.0.2.0/24
(这不是必需的):然后创建以下文件:
-nic bridge,br=natbr0
然后使用 eg或启动 qemu-netdev bridge,br=natbr0,id=nb0 -device virtio-net,netdev=nb0
,这将使tap
您的 VM 以动态方式连接到桥接器(即,tap
一旦 VM 关闭,该接口将被删除)。您还需要在 VM 上配置静态 IP:
除非您还在主机上设置了 DHCP 服务器(例如 dnsmasq)。不要忘记配置 DNS 服务器以在 VM 内部使用。
请注意,使用同一网桥的 VM 可以相互通信,除非您通过某种方式(例如 ebtables)阻止此类通信。
仅当
default
您希望 VM 能够到达“外部”时,才需要路由(和要使用的 DNS 服务器)。如果只需要它能够与 VM 主机通信,则应跳过第二条命令并停止读取。(好吧,阅读P.S.
)如果您不想在虚拟机中使用特定的“公共”DNS 服务器,最好将主机上的例如 dnsmasq 配置为 DNS 转发器,尽管使用 DNAT 将 DNS 请求转发到例如
192.168.1.1
应该适用于基本请求.然后您需要启用 IP 转发:
如果您出于安全原因想要避免从/到某些网络接口(例如
tun0
)的 IP 转发,则需要设置防火墙。例如:由于您拥有实际上覆盖
default
路由的 (VPN) 隧道路由,因此从 VM 到 Internet 的流量也将进入隧道(除非您添加了上面的示例规则)。如果您希望流量通过您的路由器,例如,您将需要策略路由。例如:您还可以阻止您的虚拟机访问您的 LAN 主机:
-I
如果您要将 DNS 请求重定向到您的路由器,请例外(注意):最后,配置 iptables 为您的 VM 子网动态执行 SNAT(根据出站接口):
请注意,这并非旨在也不会完全阻止来自“外部”(您的物理 LAN 主机或 Internet;VM 主机不计算在内)的某些流量能够到达您的 VM。当来自 VM 的回复流量的源地址在转发出去之前发生更改时,它只会中断通信作为副作用。为了正确隔离,您将需要(附加)
FORWARD
链中的适当规则。如果您有这种需要,请考虑在那里进行“有状态”设置。此外,您可以将 DNS 请求从 VM 重定向到主机到您的路由器:
这将或多或少允许您
10.0.2.1
用作 VM 中的 DNS 服务器。PS 上面的所有操作(除了创建 / 写入
/etc/qemu/bridge.conf
)都是不稳定的,即一旦你重新启动它们就会消失(除非你的发行版做了一些愚蠢的事情)。我不会深入研究如何使它们持久化,因为有不同的方式/方法,而且它可以是特定于发行版的。