我有硬件节点 (HN),它有 2 个物理接口 (eth0、eth1)。我正在使用 OpenVZ,想让我的容器 (CT) 可以访问这两个接口。我使用的是基本配置 - venet。CT 可以访问 eth0(公共接口)。但我无法让 CT 访问 eth1(私有网络)。我试过:
# on HN
vzctl set 101 --ipadd 192.168.1.101 --save
vzctl enter 101
ping 192.168.1.2 # no response here
ifconfig # on CT returns lo (127.0.0.1), venet0 (127.0.0.1), venet0:0 (95.168.xxx.xxx), venet0:1 (192.168.1.101)
我认为主要问题是所有数据包都通过 HN 上的 eth0 流动(使用 tcpdump 发现)。因此问题可能出在 HN 上的路由上。
或者我的逻辑完全错误?我只需要从 CT 访问 HN 上的两个接口(网络)。没什么复杂的。
答案1
问题相同,但解决方案不同。两个端口未连接到同一网络,需要从虚拟机的 IP 地址显示,因此伪装不起作用。
这里的主要问题是 openvz 容器将 venet 上所有 ip 的子网设置为 255.255.255.255。没有一个接口的偏好。没有它应该通过哪个路由器的偏好,所以它有时使用 eth0,有时使用 eth1。结果是当请求从错误的接口发出时,某些 IP 地址会随机失败。
一个解决方案是添加一个指定源的路由,如下所示:
ip route add 10.20.0.0/16 dev venet0 src 10.20.0.xxx
ip route add a.b.c.241/24 dev venet0 src a.b.c.xxx
我发现目前最简单的解决方案是在子网启动后立即设置它们(在 /etc/network/if-up.d 中的 ubuntu/debian 容器中):
#!/bin/sh
if [ "$IFACE" = "venet0:1" ]; then
ifconfig venet0:1 netmask 255.255.0.0 up
fi
if [ "$IFACE" = "venet0:0" ]; then
ifconfig venet0:0 netmask 255.255.255.0 up
fi
exit 0
两种解决方案的效果应该相同。这两种解决方案都让我有点担心,当访问互联网(更新或 DNS)时,它可能会无意中使用没有路由到互联网的 10.xxx 地址。默认路由是default via 192.0.2.1 dev venet0
,所以我不太确定它是如何到达那里的,但在容器和主机多次重新启动后,它似乎按预期工作。
更新 为了获得更可靠的解决方案:我使用 bash 检查 IP 并确定将其添加到哪个子网。
Ubuntu/Debian(/etc/network/if-up.d):
#!/bin/bash
if [ "${IF_ADDRESS:0:6}" = "xx.yy." ]; then
echo "AlReece45: $IFACE, IP Address $IF_ADDRESS marked as internal"
ifconfig "$IFACE" netmask 255.255.0.0 up
fi
if [ "${IF_ADDRESS:0:11}" = "xxx.yy.zzz." ]; then
echo "AlReece45: $IFACE, IP address $IF_ADDRESS marked as external"
ifconfig "$IFACE" netmask 255.255.255.0 up
fi
exit 0
CentOS/Redhat (/sbin/ifup-local):
#!/bin/bash
IFACE="$1"
IF_ADDRESS=$(ifconfig $IFACE | grep "inet addr" | awk '{print $2}' | cut -d':' -f2);
if [ "${IF_ADDRESS:0:6}" = "xx.yy." ]; then
echo "AlReece45: $1, IP Address $IF_ADDRESS marked as internal"
ifconfig "$1" netmask 255.255.0.0 up
fi
if [ "${IF_ADDRESS:0:11}" = "xxx.yy.zzz." ]; then
echo "AlReece45: $1, IP address $IF_ADDRESS marked as external"
ifconfig "$1" netmask 255.255.255.0 up
fi
exit 0
答案2
问题出在椅子和键盘之间。我没有在另一台设备上设置伪装。因此,对于遇到相同问题的人:尝试在 HN 上的每个接口上设置伪装。
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
iptables -t nat -A POSTROUTING -o eth1 -j MASQUERADE # I forgot this line
我之所以能搞清楚这一点,得益于:OpenVZ 维基
答案3
我最近设置了一个 OpenVZ 服务器,该服务器有两个以太网网络适配器,每个适配器都在自己的子网上,并在 HN 上进行伪装。
发现以下内容:如果 CT 在不同的子网上有两个 IP,则在 vzid.conf 文件中设置的第一个 IP 必须是与 HN 共享默认网关的 IP。切换 IP 的顺序并重新启动 CT 解决了我的路由问题。
答案4
我有相同的配置,我的 HN 上的两个不同网卡中有两个不同的子网。
我观察到,每个第一个都venet0
工作正常,但如果第二个venet0:1
可以接收,他们似乎很难找到通往我的第二个子网的路由。
有趣的是:我可以从第二个子网 (从桌面 10.24.14.21 到我的虚拟主机:10.24.14.24) 通过 ssh 连接到我的虚拟主机,但是这不起作用:
# ping ${SSH_CONNECTION%% *}
PING 10.24.14.21 (10.24.14.21) 56(84) bytes of data.
好的,我确实需要做点什么venet0:1
,类似这样的事似乎可以完成工作:
# vzctl exec 777 ip address delete 10.24.14.24/32 dev venet0 label venet0:1
# vzctl exec 777 ip address add 10.24.14.24/24 dev venet0 label venet0:1
好吧,从那里我写了这个workaround-venet-netmask.sh
:
#!/bin/bash
(
export NEWMASK=24 # 255.255.255.0
export IFACE=venet0:1
export IP1
while IP1=$(
ip address show dev ${IFACE%*} label $IFACE |
sed -ne "s/^.*inet \([0-9.]\+\)\/32 .*$IFACE/\1/p"
); ! [ "$IP1" ] ;do
sleep 1
done
ip address delete $IP1/32 dev ${IFACE%*} label $IFACE
ip address add $IP1/$NEWMASK dev ${IFACE%*} label $IFACE
) </dev/null >/dev/null 2>&1 &
然后我为这个脚本创建了一个符号链接,链接到每个需要的 VE.start(目前,这个脚本位于/etc/vz/conf/workaround-venet-netmask.sh
.):
# ln -s workaround-venet-netmask.sh 777.start
# ln -s workaround-venet-netmask.sh 10001.start
# ln -s workaround-venet-netmask.sh 10012.start
目前,对我来说,这似乎很有效。希望这能帮到你。