背景信息
我有一个运行Docker的两个networking接口的服务器。 与一些虚拟化工具一样,Docker创build了一个名为docker0的Linux桥接接口。 此接口默认configuration为IP为172.17.42.1 ,所有Docker容器与此接口作为其网关进行通信,并为相同的/16范围内的IP地址分配IP地址。 据我了解,所有进出容器的networkingstream量都通过一个NAT,因此出站看起来来自172.17.42.1 , 172.17.42.1站则发送到172.17.42.1 。
我的安装看起来像这样:
+------------+ / | | | +-------------+ Gateway 1 +------- | | 10.1.1.1 | / +------+-------+ +------------+ | | eth0 | / | 10.1.1.2 | | | | | | DOCKER HOST | | | | | Internet | docker0 | | | (bridge) | | | 172.17.42.1 | | | | | | eth1 | | | 192.168.1.2 | \ +------+-------+ +------------+ | | | | \ +-------------+ Gateway 2 +------- | 192.168.1.1| | +------------+
问题
我想将所有来自/从第二个eth1 192.168.1.2接口的Docker容器的stream量路由到默认网关192.168.1.1 ,而来自/去往主机的所有stream量都从eth0 10.1.1.2接口到达一个10.1.1.1默认网关。 到目前为止,我已经尝试了各种各样的事情,但是我认为最接近正确的是使用iproute2,如下所示:
# Create a new routing table just for docker echo "1 docker" >> /etc/iproute2/rt_tables # Add a rule stating any traffic from the docker0 bridge interface should use # the newly added docker routing table ip rule add from 172.17.42.1 table docker # Add a route to the newly added docker routing table that dictates all traffic # go out the 192.168.1.2 interface on eth1 ip route add default via 192.168.1.2 dev eth1 table docker # Flush the route cache ip route flush cache # Restart the Docker daemon so it uses the correct network settings # Note, I do this as I found Docker containers often won't be able # to connect out if any changes to the network are made while it's # running /etc/init.d/docker restart
当我提出一个容器时,我完全不能从这个容器中ping出来。 我不确定桥接口是否与物理接口用于这种路由相同的方式处理,只是想要一个理智的检查,以及任何提示,我可能会完成这个看似简单的任务。
一个朋友和我遇到了这个问题,我们希望docker支持多个networking接口服务请求。 我们特别使用AWS EC2服务,在这里我们还附加/configuration/启用了其他接口。 在这个项目中 ,有比你所需要的更多的东西,所以我会试着只包含你在这里需要的东西。
首先,我们所做的是为eth1创build一个单独的路由表:
ip route add default via 192.168.1.2 dev eth1 table 1001
接下来我们configurationmangle表来设置一些来自eth1连接标记:
iptables -t mangle -A PREROUTING -i eth1 -j MARK --set-xmark 0x1001/0xffffffff iptables -t mangle -A PREROUTING -i eth1 -j CONNMARK --save-mark --nfmask 0xffffffff --ctmask 0xffffffff
最后我们为所有fwmark添加这个规则来使用我们创build的新表。
ip rule add from all fwmark 0x1001 lookup 1001
下面的iptables命令将恢复连接标记,然后允许路由规则使用正确的路由表。
iptables -w -t mangle -A PREROUTING -i docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j CONNMARK --restore-mark --nfmask 0xffffffff --ctmask 0xffffffff
我相信这就是我们更复杂的例子所需要的,就像我说的那样,我们的项目在开机时连接/configuration/启动eth1接口。
现在这个例子不会停止从服务请求到docker0 eth0连接,但我相信你可以添加一个路由规则来防止这种情况。
化装舞会不是172.17.42.1而是
-A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE
这意味着这个规则将无法正常工作。
ip rule add from 172.17.42.1 table docker
改为尝试
ip rule add from 172.17.0.0/16 table docker
您可能还需要更多地查看iptables安装程序。 Docker将来自容器子网的所有stream量(比如172.17.0.0/16)伪装成0.0.0.0。 如果你运行iptables -L -n -t nat ,你可以看到nat表下的POSTROUTING链,
连锁POSTROUTING(政策接受) 目标人select源目的地 MASQUERADE全部 - 172.17.0.0/16 0.0.0.0/0
现在,你可以删除这个规则,并用一个伪装所有来自容器子网的stream量的规则replace它到你的第二个接口的IP – 192.168.1.2,这就是你所期望的。 删除规则将是,假设它是POSTROUTING链下的第一条规则 –
iptables -t nat -D POSTROUTING 1
然后你添加这个自定义规则 –
iptables -t nat -A POSTROUTING -s 172.17.0.0/16 -j SNAT - to-source 192.168.1.2