事情的起因还是项目需求.因为我们当下的系统所采用的认证方式是 OAuth2.0, 但是需要接入的另一个接口则是要求使用 MTLS 进行认证. 可能有人要说了, OAuth2.0 和 MTLS 是两个不一样的东西啊.
确实, 从单体的用户出发, MTLS 应该是不会涉及, 但是对于 Service to Service 的角度, 则是另一个故事了. 首先我们得明确, 对于 S2S 的服务调用, 第一点就是安全. 实现安全的手段有很多种, 比如常用的 OAuth2.0, 通过在 Token 中明确用户的信息和采用的权限, 来保证该次调用的正确性. 但是 MTLS 则是完全另一个故事.
首先, 我们得了解什么是 MTLS. 要了解什么是 MTLS, 则首先要了解什么是 TLS.
什么是 TLS
了解什么是 TLS, 需要有计算机网络, 密码学等相关学科的知识. 不过因为众所周知的原因, 作为一个合格的计算机从业人员以上都不在话下. 首先以 OSI 网络协议为例, TLS 是实现在表示层的协议,也就是在 HTTP, SMTP 等常用协议的下层, 这意味着, 我们可以很轻易的将 HTTP, SMTP 等架设在 TLS 协议上从而实现安全的通信. 事实上也是如此, 将 HTTP 架设在 TLS 上, 也就是 HTTPS 协议.
但是,真实世界中普遍使用的是 TCP/IP 协议, 所以通俗点说, TLS 也是一个应用层协议. 究竟是哪一层, 其实并不重要,只要明确在 HTTP 等最上层协议之下, TCP 协议之上就好. 刚刚也提到了, TLS 可以保证通信的安全性, 那又是如何保证的呢? 这一部分就是密码学相关的知识. 通俗点讲, 就是采用了非对称加密的思路. 众所周知, 在密码使用中, 我们有如下的一个加密方式, 我们可以通过密码 A 对文本进行加密, 然后通过密码 B 对文本进行解密, 其中密码 A != 密码 B. 这样的加解密方式就是非对称加密. 这样的密码 A 和 密码 B 则根据是否被公开称之为公私钥.
设想这样的一个场景, 用户 A 和用户 B 进行通信, A 和 B 首先交换了各自的公钥. 然后 A 将所要传达的信息通过自己的私钥加密, 然后发给 B, B 则通过之前 A 传出的公钥进行解密, 这样网络上传输的就是加密之后的信息, 在不知道公钥的情况下, 坏蛋 C 则需要暴力解密来获得答案, 但是这个暴力解密通常需要耗费巨额的时间, 所以从工程上认为是安全的. 但是我们知道, 非对称加解密是非常耗费 CPU 资源的, 如果全篇使用该方式, 服务器的 CPU 就会爆炸. 为了解决这个问题, 工程上通常使用非对称加密的手段生成一个通信密码, 然后之后的通信则使用该通行密码进行对称加密, 虽然安全程度降低了些, 但是性能大大提高.
中间人攻击
虽然我们使用了公私钥的机制, 但是还是处理不了一个中间人攻击的问题.简单的说, 如果我劫持了用户 A, B 的网络, 所有通信都是 A => C => B
这样的模式, 那么 C 只需要将自己的公钥发给 B, 以自己的公私钥与 B 通信, 然后将结果用自己的私钥加密发给 A, 理论上就能获得 A, B 通信的所有内容. 为了解决这个问题, CA 诞生了. 通过数学的手段, 我们生成了这样的一个文件 用户信息, CA机构, 公私钥, 签名
. 这就是我们常规意义上的证书. 从数学上保证了唯一性. 因为有用户信息的存在, 所以 C 无法将自己伪装成 B, 即使伪装成了 B, 因为签名的存在, 他无法伪造 CA 的签名, 因为 A 也能察觉到该证书是无效的. 从这个角度看, 通过 CA 的引入, 确保了中间人攻击不会发生. 当然, CA 被攻击, 以及私钥被窃取不再讨论范围.
MTLS 是什么
通过上述描述, 我们应该知道了什么是 TLS 以及他的安全性, 那么问题就到了 MTLS 是什么呢. 众所周知, 在常见的 HTTPS 中, 一般而言只有用户会去检查服务器的证书是否有效,而服务器则默认信任所有用户的数据. 那么如果双方都验证对方的证书有效性呢? 这就是 MTLS 认证方式.
简单的说, 就是通过证书, 双方的服务器都能明确的知道对方是谁. 这样的好处就是避免了第三方进行访问特定的接口. 在我们内部的某些团队则是通过这种手段保证该 API 只能被公司内部的服务访问.
本来以为自己对 TLS 和 HTTPS 已经很熟悉了, 但是一到真正做项目的时候, 还是发现了自己有好多地方不清楚. 比如最简单的也是最难的, 如何存储私钥. 因为私钥是一个非常重要的东西, 可以认为是身份认证, 正因为证书的唯一和可靠, 如果被其他人拿到了该私钥, 则可以肆无忌惮的伪装, 后果不堪设想. 为了防止这种事情发生, 内部开发了很多的安全设施. 这一部分涉及到商业机密也就不能写出来了…
正如项目之初, 我和 Sandeep 说, 这个任务应该是一个比较简单的任务, Sandeep 对我说, 不要小看他, 可能比预计的困难很多…事实也确实如此…果然商业公司没有简单的业务啊…