网线、光纤就好像铁轨:
你发出去的数据包封装在tcp/udp/ip报文里。每个报文就相当于一节车厢:
每节车厢装载着不同的货物、前往不同的目的地(ip)。
当它们到了路由器/交换机等设备时,就会重新编组、从而沿着正确的线路前往自己的目的地:
以上,是承载http/https的tcp/udp协议做的事。这个协议是不加密的,因此你的目标ip的确是可以知道的。
但,tcp/udp的载荷,也就是每节车厢里面的货,它们是可以加密的。
其中,http是不加密的,因此可以通过wireshark、tcpdump之类工具直接看到内容;而https是加密的——你可以知道它访问了哪台主机,但不可能知道它究竟传输了什么。
这是怎么做到的呢?
首先要给你科普一个知识:存在一种特殊的加密算法叫“非对称加密算法”,或者叫“公钥体系”。其中最著名的就是RSA算法。
这种算法有两个密钥,一个私钥,需要严格保密;一个公钥,应该让所有人都知道。
其中,公钥加密的东西,只有私钥能解开。
比如,你知道我的公钥,于是用RSA加密了一段信息。加密之后,哪怕你也无法解开这段信息了。只有拥有私钥的我可以解开。
然后,私钥“加密”的东西,所有人都可以用公钥解开——所以习惯上不叫它加密,而是签名。
这是因为,只有知道私钥的人,才能“加密”出一段可以用对应的公钥解开的信息。这就确保了信息的确来自私钥的持有者。
就好像签名一样,这样的信息是无法篡改、无法伪造也无法抵赖的。
然后,我们需要分成三步完成整个工作。
第一步,是建立一些CA,把他们的公钥内置于操作系统或者浏览器。
CA的任务是给域名持有者发证书,这个证书用于证明它的确持有某个域名。
比如,如果我申请/购买了一个域名,叫http://xttblog.com;那么域名服务商那里就有我的申请记录,包括邮件地址、用户名、密码等等。
然后,我可以在自己的主机上生成一对RSA密钥;然后把公钥提交给CA,再通过域名服务商向CA证明我确实拥有这个域名。CA验证通过,就可以给我一张证书,内容是:
❝
此证书证明域名http://xttblog.com的公钥为1234567。有效期至x年x月x日。
颁发者:let's encrypt
如果CA乱发证书,就会被用户、浏览器厂商、操作系统厂商把它的证书置于黑名单,再也不信任它。
第二步,当我们和一个主机连接时,它需要证明它的确是我的主机。
怎么证明呢?
没错,出示第一步颁发给它的证书——你要访问http://xttblog.com,这台主机就要给你一份证书。
你拿到证书后,先看颁发者,let's encrypt,可以,这个CA是可以信赖的。
然后,你的操作系统/浏览器就有let's encrypt的公钥——还记得前面刚科普给你的知识吗?
没错,这份证书是let's encrypt用自己的私钥“签名(加密)”过的;我们用它的公钥就可以解开它。
解开,发现内容是:
❝
此证书证明域名http://xttblog.com的公钥为1234567。有效期至x年x月x日。
于是,你确认了http://xttblog.com的公钥的确是1234567;现在需要这台主机证明自己的确是http://xttblog.com了。
怎么证明呢?
挑战-应答。也就是你要向它发起一个挑战:现在时间是2024年1月13日18:30:45:345,我的公钥是7654321;请用你的私钥签名“http://xttblog.com 7654321 2024年1月13日18:30:45:345”,然后把签名结果返回给我。
于是服务器就用http://xttblog.com的私钥加密以上信息,返回给你。你再用CA证明过的公钥1234567解密它,得到“http://xttblog.com 7654321 2024年1月13日18:30:45:345”,这就证明了这台服务器的确是合法的http://xttblog.com主机,没有被人冒充——同时也把你的公钥给了服务器。
注意这里一定要小心,所有信息都要验证。一个不小心就可能遭受中间人攻击。
挑战应答通过之后,就可以继续下一步了。
第三步,协商通信密钥。
公钥算法很好用,但并不适合拿来通信。因为它的加解密速度太慢了,消耗太大。
而相同安全级别的AES等对称加密算法没那么神奇,无法用来做这个CA身份验证体系;但它的加解密速度快,消耗低,更适合拿来加密所有通信信息。
因此,我们需要通过某种机制,协商一个只有你和主机知道的密钥,用来加密双方的通信。
注意,这三步全都是明文。那么我们如何在攻击者眼皮子底下,协商出一个只有你和主机知道、攻击者却不可能知道的密码呢?
答案是diffie-hellman密钥交换算法。
https://www.comparitech.com/blog/information-security/diffie-hellman-key-exchange。
这也是一个很神奇的算法。它的玩法是:
1、主机初始化一个diffie-hellman盒子
2、置入一个随机数A,把盒子状态搅乱
3、把搅乱的盒子发送给你
4、你得到盒子后,也往里面放进一个随机数B,然后算出来一个K
5、算出K后,把搅的更乱的盒子发送给主机
6、主机再次把随机数A放进盒子,也算出来一个K
你和主机算出来的K总是一模一样的;但攻击者不知道你们使用的随机数A和B,他就永远得不到这个K。
不过,单纯的diffie-hellman算法容易遭受中间人攻击;因此实际使用时需要一定的保护。
怎么保护呢?
前面提到,你和主机已经相互验证过了;那么接下来,你和它交换diffie-hellman盒子时,就要加上各自的私钥签名,从而确保信息的确来自之前验证过的双方。
注意这里的关键是双方的私钥签名,不要以为用对方的公钥加密就安全。后者没什么意义,因为攻击者也可以这样做;而diffie-hellman密钥交换算法只怕中间人攻击,并不怕被人看见双方的交换过程。
正确协商出密钥K之后,你和主机之间的所有通讯都会用密钥K加密;此时外部攻击者除了知道你和哪台主机联系(也就是写在火车皮上的ip地址),已经无法知道你们交换的任何内容了。
总结
HTTPS
=HTTP
+TLS/SSL
SFTP
=FTP
+TLS/SSL
- ......
这样做的好处,就是应用层协议可以保持不变,同时又通过TLS/SSL保证了安全性。
SSL(安全套接字层)或TLS(传输层安全)协议来加密通信,确保数据在传输过程中不被窃取或篡改。
至于 HTTPS 如何来保证安全问题。其实这个活就是由TLS/SSL来做的。
TLS/SSL协议核心就三大步骤:认证、密钥协商、数据加密。也就是我们常说的机密性、防伪造、防欺骗。