抱歉,如果这个问题已经有人问过了。我找不到它,我有以下设置:
+---------------------------------------------------------------------------------------------+
|HOST |
| |
| +-------------------------------------------------+ |
| | UBUNTU-VM | |
| | | |
| | +-------------------+ | |
| | |UBUNTU-LXC | | +------------------+ |
| | | 10.0.0.3/24 | 10.0.0.1/24 | |OTHER VM | |
| | | eth0-----lxcbr0----------eth0-----------br0----------eth0 | |
| | | | 192.168.100.2/24| 192.168.100.1/24 |192.168.100.3/24 | |
| | +-------------------+ | +------------------+ |
| +-------------------------------------------------+ |
+---------------------------------------------------------------------------------------------+
当我从 UBUNTU-LXC ping 192.168.100.3 时,源 IP 地址会被 UBUNTU-VM 自动更改为 192.168.100.2。这就像有一个 NAT,而我真正想要的是让我的 UBUNTU-LXC 与其自己的 IP 地址通信。有什么办法吗?
编辑:这些信息可能是相关的:
- 我正在使用 KVM +libvirt 来设置我的虚拟机
- 以下是我在 UBUNTU-VM 中创建界面的方法
:
<interface type='bridge'>
<mac address='52:54:00:cb:aa:74'/>
<source bridge='br0'/>
<model type='e1000'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x09' function='0x0'/>
</interface>
答案1
将 libvirt 网络的网络描述更改为不执行 nat。
从 VM 主机运行virsh net-list
。
然后virsh net-edit
虚拟机所在的网络删除natting。
答案2
终于解决了。下面是解决方法。抱歉,这篇文章太长了,但我花了很多时间,我想有些人可能会对详细的解决方案感兴趣。
设置
+---------------------------------------------------------------------------------------------+
|HOST |
| |
| +-------------------------------------------------+ |
| | UBUNTU-VM | |
| | | |
| | +-------------------+ | |
| | |UBUNTU-LXC | | +------------------+ |
| | | 10.0.0.3/24 | 10.0.0.1/24 | |OTHER VM | |
| | | eth0-----lxcbr0----------eth0-----------br0----------eth0 | |
| | | | 192.168.100.2/24| 192.168.100.1/24 |192.168.100.3/24 | |
| | +-------------------+ | +------------------+ |
| +-------------------------------------------------+ |
+---------------------------------------------------------------------------------------------+
1. 删除 UBUNTU-VM 上的 NAT
我的数据包从 UBUNTU-VM 传出的原因192.168.100.2
是由于iptables
启动容器时创建的默认规则:
root@UBUNTU-VM# iptables -nL -t nat
Chain PREROUTING (policy ACCEPT)
target prot opt source destination
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
Chain POSTROUTING (policy ACCEPT)
target prot opt source destination
MASQUERADE all -- 10.0.3.0/24 !10.0.3.0/24
此规则基本上表示“如果数据包来自子网10.0.3.0/24
,而目的地在另一个子网中,则更改源 IP”。因此,如果我删除此规则,我应该能够使用我的容器 IP 地址 ping 外部。让我们删除此规则:
root@UBUNTU-VM# iptables -D POSTROUTING 1 -t nat
现在,如果我192.168.100.1
从我的 LXC 容器 ( 10.0.3.233
) 执行 ping 操作,将发生以下情况:
root@HOST# tcpdump -i br0 -n
12:51:56.174009 IP 10.0.3.233 > 192.168.100.1: ICMP echo request, id 498, seq 1, length 64
12:51:56.174072 ARP, Request who-has 10.0.3.233 tell 192.168.100.1, length 28
ICMP 请求来自我的 LXC IP 地址:) 但是br0
似乎无法回答。
2.在HOST上添加默认路由
root@HOST# ip route add 10.0.0.0/8 via 192.168.100.2
10.0.0.0/8
现在子网的默认网关eth0
在 UBUNTU-VM 上。让我们尝试 ping 一下:
root@HOST# tcpdump -i br0 -n
14:14:33.885982 IP 10.0.3.233 > 192.168.100.1: ICMP echo request, id 660, seq 14, length 64
14:14:34.884054 ARP, Request who-has 10.0.3.233 tell 192.168.100.1, length 28
它仍然不起作用。不幸的是,我对此没有任何解释。最糟糕的是,为什么要br0
对不在其子网中的 IP 发出 ARP 请求?至少,我希望 ICMP 请求会被默默忽略,但用 ARP 请求回答就很奇怪了。
3.配置 libvirt
3.1. 当前配置
br0
是我在主机上手动配置的桥接器,使用netctl
。在我的 UBUNTU-VM 模板中,我有以下内容:
<interface type='bridge'>
<mac address='52:54:00:cb:aa:74'/>
<source bridge='br0'/>
<model type='e1000'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x09' function='0x0'/>
</interface>
当 UBUNTU-VM 被创建时,kvm
(或者libvirt
?)创建一个 veth 对并将它们附加到桥上。
root@HOST# brctl show
bridge name bridge id STP enabled interfaces
br0 8000.fe0000000001 no vnet1
vnet2
由于某种原因,这不起作用(欢迎编辑/评论)
解决方案是配置一个routed network
而不是仅仅一个bridged network
。
3.2. 定义网络
为您的网络创建一个 xml 模板:
<network>
<name>vms</name>
<uuid>f3e18be1-41fe-4f34-87b4-f279f4a02254</uuid>
<forward mode='route'/>
<bridge name='br0' stp='on' delay='0'/>
<mac address='52:54:00:86:f3:04'/>
<ip address='192.168.100.1' netmask='255.255.255.0'>
</ip>
<route address='10.0.0.0' prefix='8' gateway='192.168.100.2'/>
</network>
注意默认路由节。然后获取它并启动它
virsh # define vms.xml
virsh # net-start vms
3.3. 编辑虚拟机
界面现在看起来应该是这样的:
<interface type='network'>
<mac address='52:54:00:cb:aa:74'/>
<source network='vms'/>
<model type='e1000'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x09' function='0x0'/>
</interface>
最后一个考试
重新启动虚拟机和容器后,我终于可以br0
使用 LXC 容器 IP 进行 ping 操作了:
root@HOST# tcpdump -i br0 -n
14:24:00.349856 IP 10.0.3.233 > 192.168.100.1: ICMP echo request, id 468, seq 16, length 64
14:24:00.349900 IP 192.168.100.1 > 10.0.3.233: ICMP echo reply, id 468, seq 16, length 64
剩余问题
- 为什么会有这个 ARP 请求
2.
? - 为什么我的设置不工作,除非我让 libvirt 处理桥接和路由本身?我的手动配置(使用 netctl 创建桥接,并使用 添加默认路由
ip route add
)是非常类似于 libvirt 所做的:一座桥,连接两个 vnet 接口,以及一条默认路由...libvirt 在这里做了一些黑魔法吗? - 我是否可以使用此设置来扩展容器的数量(这是我的最终目标)。
有帮助的资料来源
- libvirt 网络文档
- 当我拥有足够的声誉时,我将编辑并添加其他链接(需要 10......)