当前,电商平台会采用基于 Docker 的容器技术来承载 618 大促期间的一些关键业务版块,包括最简单的商品图片展示、订单详情页面等等。
通过容器化改造,电商平台的每个业务版块解耦,可以独立开发、部署和上线,从而让后台业务系统具备更高的稳定性、可扩展性和安全性,即便某个环节出现问题,也能保障平台高峰值期间的平稳运行。
镜像是 Docker 容器的基石,只有通过它才可以创建容器,而 Registry 是存放 Docker 镜像的仓库。但在实际应用中,由于需要频繁地从 Registry 下载镜像运行容器应用(比如发布新版本,打补钉等情形),其间的文件传输成为镜像分发的瓶颈,
P2P 加速镜像下载是有效的解决方案,但如何确保用户数据在公有云环境下的 P2P 传输安全性尤为关键,本文主要从链路层和业务层的安全加固,阐述了公有云 Docker 镜像 P2P 加速的安全性。
问题:
在使用 Docker 运行容器化应用时,宿主机通常先要从 Registry 服务(如 Docker Hub)下载相应的镜像 (image)。这种镜像机制在开发环境中使用还是很有效的,团队成员之间可以很方便地共享同样的镜像。然而在实际的生产环境中,当大量主机需要同时从 Registry 下载镜像运行容器应用时(比如发布新版本,打补钉等情形),Registry 服务往往会成为镜像分发的瓶颈,应用镜像需要较长时间才能传送到所有主机上,使得应用发布的周期大大延长。
不少企业提出了 P2P 加速镜像下载的解决方案,但都是私有云及内部环境的使用场景,在公有云未得到使用。其中很大一部分原因是公有云使用 P2P 的安全性问题,如何确保用户数据在 P2P 传输中是安全的成为了其中的难点。我们就该问题设计实现了确保用户数据安全的 P2P 镜像分发系统。本文就其安全性展开阐述。
架构:
华为 P2P 容器镜像分发系统示例图
华为 P2P 容器镜像分发系统包含 3 个组件:客户端代理(Proxy)、BT 客户端和 BT Tracker。
客户端代理(Proxy)
客户端代理部署在集群的每个节点中,配置为 Docker 的 Http Proxy,截获 Docker Daemon 的镜像下载请求,通知 Client 下载,并最终将镜像导入到 Docker daemon 中。
BT 客户端
部署在集群节点的 BT 客户端和 Tracker 共同组成了一个完整的 P2P 文件传输系统。在整个镜像的分发过程中,它们利用 BT 协议完成镜像下载。
BT Tracker
Tracker 是 BT 系统的一部分,它存储了 BT 客户端下载过程中所需要的元数据信息和种子信息,并协助各个 BT 客户端完成整个通信过程。
安全:
首先,我们限制了跨集群的 P2P 下载,最大限度防止租户间的数据泄露。
之后,在链路层面的安全性和业务层面的安全性做了增强。
链路安全
一想到链路安全,我们首先会想到的是加密。
对称加密服务端和客户端采用相同的秘钥加密和解密,只要这个秘钥不公开,并且秘钥足够安全,那么链路就是安全的。但是在网络中都使用相同的对称加密秘钥,无异于公开传输,如果秘钥被劫持,那么就可以篡改链路的所有数据。
然后我们肯定会想到 HTTPS,它是怎么实现安全的?我们先来了解下 HTTPS 的实现方式。
在具体的数据传输过程中,HTTPS 采用的是对称加解密的方式,但是它在连接建立时增加了握手协商的过程。
什么是公钥:
公钥是非对称加密中的概念。非对称加密算法方式基于一个秘钥对,数据通过一个秘钥加密,只有通过另外一个秘钥才能解密。服务端保存私钥,公钥发给客户端。
我们假设一个场景,我们生成秘钥对,客户端通过公钥加密数据,服务端通过私钥解密。那么即使用户劫持到公钥,他无法劫持篡改用户的数据。然而从服务端到客户端的链路还是不安全的。
HTTPS 借助了非对称加密的这个特性,确保对称机密秘钥的传输是安全的,最后采用对称加密传输数据。
证书的意义:
然而,这又产生了一个新的问题,公钥被劫持了怎么办?
HTTPS 当然不会这么简单就被劫持,为了解决上诉问题,它引入了数字证书和第三方机构。证书是由第三方认证机构通过公钥签发的,其中不仅包含公钥,还包含签名(由签发节点的私钥加密产生)、有限期、签发机构、网址、失效日期等。
HTTPS 返回的不在是私钥,而是证书。当客户端接收到证书,会对证书做一个校验。在各个机器中都会维护一个权威的第三方机构列表(包括它们的公钥),当客户端需要公钥时,可根据颁发机构信息本地查找到公钥。客户端通过颁发机构的公钥验证签名的有效性和证书的完整性,保证公钥未被篡改。
HTTPS 通过私钥、证书、和 CA(签发机构)确保了链路的安全性。在 P2P 场景下,BT Client 之间是对等的,他们相互传输数据,更应该是服务端校验客户端,而不是 HTTPS 的客户端校验服务端。并且由于 BT Client 是部署在用户的节点,还需要考虑证书和私钥都被劫持的风险。
我们是怎么做的
- Client 之间
BT Client 间传输数据肯定是需要加密的,防止链路的数据被劫持。但是只增加 HTTPS,虽然链路被加密,但是客户端可能会被假冒,只要假冒者不校验服务端的证书,直接和服务端握手,就能从其他 BT Client 获取到他想要的数据。
我们借鉴 HTTPS 的实现,采用了双向验证的模式。
需要有证书,首先需要一个统一的 CA(签发机构),因此我们在 Tracker 中保存证书和私钥做为签发机构,Proxy 获取种子的同时返回 CA,用户校验客户端的证书。
然后,只使用一个证书对并且放在 Bt Client 是危险的,很有可能性被入侵截获到证书,因此我们获取证书的方式改为从 Tracker 获取,获取种子的同时获取 Tracker 生成的临时证书私钥对,把它加入 BT Client 的下载队列。在 BT Client 开始相互连接时,首先相互确认对方的证书的有效性(签名、签发机构等信息),校验通过后才能请求并相互下载数据。
这种方式下,Client 之间的链路是安全的。
(1)链路经过证书加密,直接截获链路是不可行的
(2)即使仿照 BT Client 的方式,由于 Client 每个连接都需要进行双向的证书校验,想通过这个方式截获数据就必须请求 Tracker 去获取,而访问 Tracker 首先是 HTTPS 的,然后我们还做了业务层的安全校验(下文业务层安全会提及),也是不可行的。
- Docker Daemon 到 Proxy
我们在 Proxy 中需要劫持 Docker 的请求,因为 Docker 在不配置时访问 Registry 采用的是 HTTPS,因此 Proxy 劫持 Docker 请求就必须和 Docker 保持 HTTPS 连接。
我们让客户端代理只监听 localhost 端口,杜绝外部使用该代理的可能性。同时,客户端代理绑定一套临时生成的签发给 registry 域名的自签名证书和 CA 证书,用于劫持 Docker Daemon 的请求,并将 CA 证书添加到机器的信任证书当中。
代理绑定的证书只保存在内存中,即使通过特定方式获取到当前节点的 CA 证书和服务端证书,也无法截取其他节点数据。
- 从用户节点到 Registry、Tracker
首先,为了确保链路的安全,Regstry、Tracker 都绑定从权威第三方机构购买的 HTTPS 证书私钥对。Proxy 和 BT Client 在访问它们的时候都会去校验证书的有效性,只要在证书有效的情况下才发送请求,这从根源上杜绝了 Regstry、Tracker 被假冒的可能。
业务加密
在确保链路安全后,我们还做了一层业务安全加固。首先我们先了解下 JWT Token。
Json web token(JWT)是为了网络应用环境间传递声明而执行的一种基于 JSON 的开发标准(RFC 7519),该 Token 被设计为紧凑且安全的,特别适用于分布式站点的单点登陆(SSO)场景。JWT 的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,也可以增加一些额外的其它业务逻辑所必须的声明信息,该 token 也可直接被用于认证,也可被加密。
在我们使用 Docker 命令下载镜像时,Docker 首先会到 Registy 获取 Token,在之后的获取镜像层的过程中,多会带上该 Token 用于鉴权。其中 Token 时组要包含以下信息:
(1)用户信息
(2)资源信息,为操作的镜像和 namespace 的名称
(3)权限信息:是否有 PULL/PUSH 权限
(4)用于解析 Token 签名的证书
利用 JWT Token 中自带解析 Token 证书这个特性,我们在 BT Client 间通信又增加了 Token 的校验。在前文中的证书校验通过后,客户端需要发送 Token 给服务端用于校验。为了防止 Token 被假冒,入侵者采用第三方生成,我们使用服务端截从 Docker 截取的 Token 中的证书解析校验客户端的 Token,杜绝这种情况。
同时,Proxy 访问 Tracker 的接口也会带上这个 Token,Tracker 会校验 Token 的权限,完成业务层的安全验证,防止证书和种子被盗取。
通过以上链路层和业务层的安全加固,用户数据被盗取的可能性已几乎为零。如果大家有更好的建议,欢迎点评。
点击关注,第一时间了解华为云新鲜技术~