故事
我有以下虚拟 Docker 网络配置:
...10.2 ...10.3 ...100.3 ...100.2
+------+ +-------+ +------+
| so_A +--so_net_a--+ so_AB +--so_net_b--+ so_B |
+------+ ...10.0/24 +-------+ ..100.0/24 +------+
使用问题末尾的设置脚本进行构建。这里so_A
,so_AB
和so_B
是 Debian 容器;so_net_a
并且so_net_b
是 Docker 网络(最近添加的功能)。
我想用中间容器做一个路由器so_AB
。为此,我将默认网关替换为so_A
以下 IP so_AB
:
docker exec --privileged so_A ip route del default
docker exec --privileged so_A ip route add default via $AB_A_IP dev eth0
然后我继续运行tcpdump
(so_AB
在一个额外的终端窗口中):
docker attach so_AB
/# tcpdump -i eth0 -n
并从 ping 一些地址so_A
。我不明白,为什么当我从一个完全不相关的网络 ping 一个 IP 地址时,例如:
docker attach so_A
/# ping 192.168.200.2
so_AB
接收 ICMP 数据包(尽管出于某种原因来自默认网关192.168.10.1
,而我希望它们来自so_A
ip ),当我从子网192.168.10.2
ping 任何地址时,例如:so_net_b
/# ping 192.168.100.15
so_AB
仅接收 ARP 请求,例如ARP, Request who-has 192.168.10.3 tell 192.168.10.2, length 28
.
ip route get
显示so_A
将so_AB
用作两个地址的第一跳。
问题
为什么相关 IP 地址的 ping 数据包无法到达自定义设置的默认网关,而不相关的 IP 地址却可以?
设置
我使用最新的 Docker 版本:1.9.1, build a34a1d5
在我的 64 位 ubuntu 上14.04
。
这是重现该问题的安装脚本:
docker network create --driver=bridge --subnet=192.168.10.0/24 so_net_a
docker network create --driver=bridge --subnet=192.168.100.0/24 so_net_b
# Network topology:
# +------+ +-------+ +------+
# | so_A +--so_net_a--+ so_AB +--so_net_b--+ so_B |
# +------+ +-------+ +------+
docker run -itd --name=so_A --net=so_net_a debian /bin/bash
docker run -itd --name=so_B --net=so_net_b debian /bin/bash
docker run -itd --name=so_AB --net=so_net_a debian /bin/bash
docker network connect so_net_b so_AB
docker exec so_AB sh -c 'apt-get update && apt-get install -y tcpdump'
AB_A_IP=`docker inspect -f '{{.NetworkSettings.Networks.so_net_a.IPAddress}}' so_AB`
B_IP=`docker inspect -f '{{.NetworkSettings.Networks.so_net_b.IPAddress}}' so_B`
# Change the default gateway to so_AB
docker exec --privileged so_A ip route del default
docker exec --privileged so_A ip route add default via $AB_A_IP dev eth0
# Normally should be 192.168.100.2
echo $B_IP