概述

近期,Hacker News上有人提出Docker的网络配置存在问题,即使你使用类似-p 127.0.0.1:80:80这样的选项来试图将容器内服务端口暴露在本地,外部实际上仍然能够访问该服务。

严格来说,这算是一个安全问题,从2016年开始被人发现,但Docker一直没有修复它,具体见GitHub issue。这不是操作人员的错误配置,其实按照惯例应该是可以算作漏洞的,只是Docker一直没有修,也没有给它分配漏洞编号。与之相比,K8s相关的网络边界绕过问题都会获得一个CVE编号,从而认定为漏洞。

漏洞分析

漏洞影响是本地局域网中其他机器上的潜在攻击者能够访问容器映射到宿主机127.0.0.1上的服务。

这个问题在于Docker提供了把容器端口映射到127.0.0.1本地端口的功能,但宿主机所在局域网的其他机器实际上也能访问这个所谓的本地监听服务,这是超出配置人员预期的,是不安全的。其原因在于Docker在配置这个本地端口映射功能时,向本地iptables表中添加了一条允许任何网络可达的地址访问容器在docker0网桥上的地址(如172.17.0.2)的功能,这样一来,理论上任何能够访问宿主机的攻击者都能够访问172.17.0.2容器地址。然而,由于172.17.0.2是一个局域网地址,所以不在本地局域网的攻击者并不能直接进行远程访问,因为172.17.0.2不会在互联网上进行路由。

下图是复现效果:

缓解方案

目前Docker并不支持任何选项限制这样的访问,本身这个问题是在局域网内,影响有限;如果之前容器内有某些重要的服务是通过映射到本地端口的方式限制远程访问的,建议检查这些服务的访问控制(密码、授权、证书等)是否充分;另外,如果主要用的是K8s,建议直接采用K8s对接containerd等最新版推荐的方式部署,不采用K8s->Docker-shim->containerd的方式部署;如果必须要用Docker部署容器,且容器内有重要服务映射到本地127.0.0.1端口,且脆弱性未知或缺乏访问控制,建议将其与其他机器网络隔离。