更安全的本地Docker网络


【编者的话】本文主要是解决了上一篇探索本地Docker桥接网络提出的问题。我们可以在Docker启动时设置icc=false参数来禁止任意的跨容器通信。

上周我写了《探索本地Docker桥接网络》。在这篇文章中我介绍了如何使用nmap探索由同一桥接网络上的其它容器公开的服务,并展示了在这些服务没有映射到主机的公有接口的端口的情况下如何去访问这些服务。这是一个问题,因为大多数镜像的工具、数据库以及微服务都带有不安全的默认配置。较为变通的工程师或管理员可能会把这些镜像放到可以保护他们的防火墙或网络拓扑结构中。这只适用于配置了防火墙和网络拓扑的环境。

默认情况下,Docker允许任意的跨容器通信,在我看来这是一件好事,它不仅可以降低应用复杂度而且还降低了学习曲线。对于任何一个技术来说,能让用户快速上手,同时又有清晰的学习路径是非常重要的。在Docker中,我们需要知道如何加强它们的容器网络。人们应该学会的第一件事就是如何禁用任意的跨容器通信:启动Docker守护进程时设置icc=false
docker -d --icc=false ....

当以这种方式启动Docker时,它将配置iptables(防火墙):在桥接网路中移除所有容器间的通信,这将禁止容器之间的通信。
Chain FORWARD (policy ACCEPT)
target prot opt source    destination  
DROP   all  --  0.0.0.0/0 0.0.0.0/0 
ACCEPT all  --  0.0.0.0/0 0.0.0.0/0   ctstate RELATED,ESTABLISHED
ACCEPT all  --  0.0.0.0/0 0.0.0.0/0

如果你不想让你的容器间直接通信,那我们推荐你这样做。但是需要注意的是这样做无法阻止主机的公共接口与可以公开访问的映射到另一个容器的端口之间的通信(译者注:当然无法阻止,映射的端口主机肯定可以访问啦)。
1-_QyJABSe1WUQfVIXFHCw_w.png


这可以满足很多人的需求,但故事并没有到此结束。

当跨容器通信被禁用时,你可以在容器创建时使用容器连接来确保指定容器间的通讯。当你创建一个容器并指定另一个作为连接的目标时,Docker建立相应的连接。例如:
docker run -d --name ex_a busybox /bin/sh
docker run -d --name ex_b --link ex_a:other busybox /bin/sh

如果今天我对Docker所有的部分都缺乏激情,很可能使用容器连接只是为了服务发现。当你连接两个容器时,Docker为了使用此容器会设置带有“位置”信息的环境变量,此处有太多隐藏的问题。程序或者用户创建的容器可以指定连接的别名。但是容器内的软件必须与别名一致,否则它不知道要寻找什么。即使我认为连接提供了端口信息以及网络地址信息,我依然更喜欢DNS。幸运的是,连接不仅仅是为了服务发现。

当你禁用了跨容器通信时,为了使连接的容器之间得以通信Docker会输出异常。以下是摘自有这样异常的iptables。
Chain FORWARD (policy ACCEPT)
target prot opt source     destination 
ACCEPT tcp  --  172.17.0.3 172.17.0.4  tcp spt:80
ACCEPT tcp  --  172.17.0.4 172.17.0.3  tcp dpt:80
DROP   all  --  0.0.0.0/0  0.0.0.0/0 
ACCEPT all  --  0.0.0.0/0  0.0.0.0/0   ctstate RELATED,ESTABLISHED
ACCEPT all  --  0.0.0.0/0  0.0.0.0/0


这是容器连接的最强大的应用。连接允许你用简单的断言来定义容器之间的关系。就轻量级而言,Docker确实比任何我用过的其他工具都更好。

原文链接:Safer Local Docker Networks (翻译:田浩浩 校对:李颖杰)

===========================
译者介绍
田浩浩悉尼大学USYD硕士研究生,目前在珠海从事Android应用开发工作。业余时间专注Docker的学习与研究,希望通过DockerOne把最新最优秀的译文贡献给大家,与读者一起畅游Docker的海洋。

0 个评论

要回复文章请先登录注册