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

没有 virsh NAT 还能工作吗?

可以仅从命令行修复 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 网络上的其他计算机。但不能 ping 主机@Tom Yan 的答案结合archlinux-Network_bridge上面创建的命令可以 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 

$ 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

但 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 用户,hostfwd=tcp::1810-:22

使用命令 tweak vm 可以像默认一样与互联网通信,也可以通过 ssh 与主机通信。感谢@NikitaKipriyanov 和@cnst 对 tweak 的贡献https://stackoverflow.com/a/54120040

用户需要使用本地主机地址通过端口 1810 进行 ssh

$ ssh p@localhost -p 1810

答案1

NAT 的常见想法是看不到已翻译的地址。您没有通往这些地址的路线。它们对您来说并不存在。您只能看到这些地址被翻译成的地址。

QEMU 的情况也没什么不同。在这种情况下,您的主机在“外部”,您的虚拟机在“内部”,因此虚拟机永远无法通过其分配的地址进行访问。您有虚拟机的 10.0.2.2/24 地址,但当它到达互联网时,其数据包会被转换为 192.168.1.172通过 QEMU 进程,因此主机将这些数据包视为由 QEMU 进程创建的,并将它们视为任何其他数据包(例如,来自本地运行的 Web 浏览器或类似的东西)。

如何从主机访问虚拟机?当我们有 NAT 时,为了访问隐藏在其后面的主机,我们安装基因转移酶规则。同样,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,将连接到虚拟机的端口 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

然后使用例如-nic bridge,br=natbr0或启动 qemu -netdev bridge,br=natbr0,id=nb0 -device virtio-net,netdev=nb0,它将tap以动态方式将您的虚拟机连接到桥接器(即,tap一旦虚拟机关闭,接口将被删除)。

您还需要在虚拟机上配置静态 IP:

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

除非您还在主机上设置了 DHCP 服务器(例如使用 dnsmasq)。不要忘记配置在 VM 内部使用的 DNS 服务器。

请注意,使用相同网桥的虚拟机可以相互通信,除非您通过某种方式(例如 ebtables)阻止这种通信。

default仅当您希望 VM 能够访问“外部”时,路由(和要使用的 DNS 服务器)才是必需的。如果您只需要它能够与 VM 主机通信,则应跳过第二条命令并停止阅读。(好吧,阅读P.S.


如果您不想在虚拟机中使用特定的“公共”DNS 服务器,那么最好将主机上的 dnsmasq 配置为 DNS 转发器,尽管使用 DNAT 将 DNS 请求转发到 eg 应该192.168.1.1适用于基本 DNS 请求。

然后您需要启用 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。当来自 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.1VM 中的 DNS 服务器。


PS 上述所有操作(除了创建 / 写入/etc/qemu/bridge.conf)都是易失性的,也就是说,一旦您重新启动,它们就会消失(除非您的发行版做了一些愚蠢的事情)。我不会深入研究如何使它们持久化,因为有不同的方法/方法,并且它可能特定于发行版。

相关内容