1 万字帮你学会 HTTPS

2023年 10月 1日 118.4k 0

1 万字帮你学会 HTTPS

以下文章来源于技术角落

本文尝试从 HTTP 开始,一步一步深入到 HTTPS,告诉你 HTTPS 到底是什么、为什么需要 HTTPS、以及 HTTPS 到底是怎么做的。相信你在阅读完本文后,一定会对 HTTPS 有深入的了解。

纸上得来终觉浅,除开原理部分外,本文还提供了 HTTP 和 HTTPS 的实战教程,帮助你从 0 开始搭建一个 HTTPS 加密的 Web 服务器,如果按照实战教程一步一步走下来,那么你将对 HTTPS 有更进一步的把握。

什么是 HTTPS ?一句话

HTTPS = HTTP + SSL

HTTPS 并不是一个全新的协议,而是在 HTTP 的基础上,通过 SSL 增加了一层加密协议,从而大大增加了 HTTP 协议的安全性。所以在正式了解 HTTPS 之前,我们需要先了解 HTTP。

一、HTTP

HTTP 全称 超文本传输协议(HyperText Transfer Protocol),是一种广泛用于互联网中浏览器与服务器之间的应用层传输协议。简单来说,浏览器向服务器发送 HTTP 请求,服务器向浏览器返回 HTTP 响应,两者之间通过这种方式进行“交流”,来使得我们的浏览器可以正常从服务器端获取数据,并展示在用户的电脑屏幕上

图片

以访问 httpbin.org网址为例,一个典型的 HTTP 请求如下所示:

GET / HTTP/1.1
Accept: text/html,...
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cache-Control: no-cache
Connection: keep-alive
Host: httpbin.org
Pragma: no-cache
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36
  • GET 表示请求方法,常见的 HTTP 请求方法有 GET、POST、PUT、DELETE 等...
  • GET 后面的 /表示请求路径,这里我们访问的根路径,所以显示为 /。如果你访问 httpbin.org/get的话,这里显示的就是 /get了
  • HTTP/1.1 表示使用的 HTTP 协议版本,现在常用的有 HTTP/1.1 和 HTTP/2,当然还有更先进的 HTTP/3,这里就不过多展开了
  • 下面的 9 行全部都是 HTTP header,每一个 header 包含 name 和 value,之间用冒号分隔开。

一个典型的 HTTP 响应如下所示

HTTP/1.1 200 OK
Date: Sat, 08 Apr 2023 16:28:43 GMT
Content-Type: text/html; 
Content-Length: 9593
Connection: keep-alive
Server: gunicorn/19.9.0
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true

Body...
  • HTTP/1.1 指的协议版本,响应和请求的协议版本是一致的
  • 200 OK 代表返回的响应码,表示这个响应是符合预期的。另外还有非常常见的返回码 404 NOT FOUND ,大家应该或多或少听说过,它表示服务器告诉你你访问的这个资源不存在
  • 后面 7 行全部是 HTTP header,同样每一个 header 包含 name 和 value,之间用冒号分隔开。
  • 最后是 HTTP Body,也就是响应体,即服务器返回给你的内容主体,浏览器正是根据响应体来渲染页面的

由于本文重点不在 HTTP,这里不再详细介绍各个部分的作用。

二、为什么需要 HTTPS

上面简单讲了一下 HTTP。在正式讲 HTTPS 之前,首先我们要搞清楚 HTTP 的缺点是什么,为什么需要 HTTPS。

我们知道,HTTP (除了最新的 HTTP/3 外),传输层是基于 TCP 协议的。TCP 建立连接时,有三次握手。三次握手完毕之后,TCP 连接就顺利建立了,接下来两端将会传输数据。

对于普通的 HTTP 协议,在建立完 TCP 连接之后,就直接开始传输数据了,这时候数据是明文传输的,这也是 HTTP 最不安全的地方。

明文传输是什么概念呢?我们知道,浏览器和服务器之间,是存在很长一条路线的,你在家里通过浏览器访问网页的时候,数据会从你的电脑,传到你家里的路由器,再到光猫,到运营商,到互联网....直到最后才到服务器。在明文传输下,理论上来讲,浏览器和服务器之间的任一节点,包括你家里的路由器、包括你购买宽带/流量的运营商,都可以“窃听”你们的数据,甚至还可以修改数据。

听起来不够直观?打个比方,近代时期,战场上打仗时,部队之间会通过电台进行交流。如果通过明文进行交流,那么非常危险,敌军可以打开电台进行窃听,偷取你的军事情报,这样的事也屡见不鲜了...那么他们是如何解决这个问题的呢?两个部队之间提前约定一个加密的方案,在传数据之前,先把它进行加密再传输,另一端收到数据之后,按照事先约定的方案进行解密,然后读取就可以了。这样即使敌军开始窃听,也只能听到加密后的情报,如果无法对其破解的话,得不到任何有效信息。

没错,这就是 HTTPS 的思想,浏览器在发送 HTTP 请求之前,先通过某种方式对其进行加密,然后再进行传输。服务器端收到数据之后,对其解密,读取真实内容,生成 HTTP 响应,同样对响应进行加密,然后传回给浏览器,浏览器收到数据之后,对其进行解密,得到真正的 HTTP 响应。这样就可以保证数据在传输过程中的安全性,无论是路由器还是运营商,都没有办法“窃听”你们的数据了。

说到这里,想必你已经知道 HTTPS 的一大作用了,它可以保证数据在互联网上传输的安全性,避免中间节点进行窃听和修改。

当然,聪明的你还可能会想到一些问题,例如:

  • 战场上军队之间是提前约定好加密方案的,但是咱们任意一个浏览器都可以随时访问网页,没有办法提前约定加密方案呀,那是怎么做到的呢?
  • 战场上经常出现敌军对另一方部队之间的电台加密进行破解的事情,破解完成之后,还是能够窃听到数据,那 HTTPS 的这个加密方案到底安全吗,会被破解吗?
  • 别急,这些问题,你都可以在本文中得到答案。

    三、HTTP + SSL = HTTPS !

    上面提到了对 HTTP 进行加密的思想。在 HTTPS 的具体实现中,这个加密方案即是大名鼎鼎的 SSL(Secure Sockets Layer)。

    定义:SSL(Secure Sockets Layer)是一种安全协议,用于在互联网上保护数据的传输安全。它工作在传输层,主要功能是通过加密技术,保护不同计算机之间的数据传输过程,防止敏感数据被黑客窃取和篡改。SSL 协议可以用于保护网站的用户登录、信用卡支付、网上银行等敏感信息的传输,以及企业之间的机密数据的传输。SSL 协议目前已经被继承为 TLS(Transport Layer Security),是一种安全性更高的传输层协议。所以,下面我将统一以 TLS 为名称进行讲解。

    首先,划重点,TLS 中有 Transport Layer,顾名思义,它一定是工作在传输层了。上面提到过,HTTP 是应用层协议,传输层和应用层的概念,想必大家应该知道吧,计算机网络的事实标准中,自顶向下可以分为五层:应用层、传输层、网络层、链路层、物理层...这是《计算机网络》的基础,这里不过多展开,不熟悉的同学,要回去重修一下课程了。

    我们知道,TCP 协议里有三次握手,三次握手成功后连接才算建立,接下来才会真正开始传输数据。传统的 HTTP 协议中,三次握手成功之后,就会直接开始明文传输 HTTP 数据了。

    那么 TLS 是什么时候开始发挥作用的呢?答案很简单,在三次握手之后,传输数据之前。

    也就是说,在 TCP 协议中加入 TLS 之后,三次握手成功之后就不会再立刻开始传输数据了,而是紧接着开始 TLS 的建立过程,也被称为 TLS 握手。

    TLS 握手是干嘛呢?或者说为什么需要 TLS 握手呢?上面提到,在战场上,两个部队之间会提前约定好加密的方案,例如面对面用纸互相写下加密方案,然后在一段时间之内的电台通信统一用这个加密方案,这样能一定程度上保证电台通信的安全性。但是 TLS 中我们并没有这样一个“面对面”的机会,咱们总不可能在访问网页之前,人肉跑到服务器的维护者那边去跟他约定加密方案吧。出于这个目的,TLS 握手便出现了。所以我们可以说,TLS 握手的目的是给通信双方约定一个安全的加密方案(可以理解为商量一个只有双方知道的加密密钥)

    知道了 TLS 握手的目的,接下来我们需要知道它具体是怎么做的。首先,我们肯定不能直接明文传输加密方案(密钥),不然这个密钥在传输过程中就直接被第三方获取了,那么加密将没有任何意义。也就是说,TLS 握手需要做到:通信双方可以约定一个共同的加密方案(密钥),并且这个约定的过程(即 TLS 握手过程),即使被任何第三方窃听到,也无法解析出这个加密方案(密钥)。

    是不是听起来很神奇,那到底是怎么做到的呢?这就不得不提到密码学中非常经典的两个概念:对称加密和非对称加密。

    四、对称加密、非对称加密

    对称加密的特点是:约定一个共同的密钥,这个密钥可以用来加密数据,也可以用来解密数据,有点类似于上面提到的战场上的加密方案。

    图片

    对称加密是 TLS 握手成功后,通信双方之间采用的数据加密方案。现在的主要问题是:通信双方如何安全的商量好这个对称密钥,防止密钥被其他人窃取?

    这时就需要轮到非对称加密出场了。什么是非对称加密呢?与对称加密不同,非对称加密方案中,用户手握两把密钥,一把称为公钥,一把称为私钥,其中公/私钥都可以用来加密/解密数据,其特点为:用公钥加密后的数据,只有用私钥才能将其解开;用私钥加密后的数据,只有用公钥才能将其解开!

    图片

    这里只介绍了非对称加密的特点,并没有介绍其原理,因为这属于密码学的范畴了,展开来讲又是一篇文章。

    简单说说其思想吧,目前流行的非对称加密算法 RSA 基于的原理其实就一句话:我们目前还没有很好的办法对一个很大的数做因式分解,例如你在心里默默想一个很大的质数 p 和 质数 q,算出其乘积 n,那么向外公开 n 的话,外部人员是很难找出 p 和 q 的(只能暴力尝试,而当这样的数够大够多的时候,以现在的计算机算力也需要几百上千年的时间才能破解了)。对密码学感兴趣的同学,可自行进一步了解。

    有了非对称加密,事情就变得有意思起来了。见下图,服务器端用非对称加密方案生成一对公/私钥,私钥掌握在自己手里,谁也不告诉;在 TLS 握手的过程中,服务器将自己的公钥交给浏览器端,浏览器端在心里默默想出一个对称加密的密钥后,将这个密钥用服务器端的公钥进行加密,然后再传回给服务器端;服务器器端收到这个数据之后,用自己的私钥将其进行解密,就能够得到刚才浏览器心里默念的那个对称密钥了。这样这个问题就完美的解决了,两边可以心有灵犀的拿到这个对称密钥,而不用担心被任何第三方窃取到了。

    图片

    这就是 TLS 握手的过程吗?不,当然没这么简单了,我们还没有考虑一个非常巧妙的攻击手段:中间人攻击。

    五、中间人攻击

    具体什么是中间人攻击呢?看下面这张图

    图片

    假设现在我们从电脑上访问百度,如果有一个中间人在我的路由器端,或者运营商端,或者任何一个中间节点上截取了我的请求,刚不是提到服务器端需要返回给我们公钥吗,中间人他自己也生成一套公/私钥,然后将自己的公钥返回给我,这样我就与中间人之间建立了一条我以为“安全”的连接了,此时我以为我连接的是百度服务器,其实我连接的是中间人...那么此时中间人可以做任何事情了,如果他人品比较好的话,他可以默默当一个代理,我要访问百度,他就去帮我访问百度,然后把结果返回给我,勤勤恳恳做一个“中间商”。

    当然,我们知道做这种攻击的人人品往往不会太好,所以他们可以做更坏的事情,例如伪造一个银行网页返回给我,让我填写账号和密码,这样的话...后果就不堪设想了。

    那么如何防止中间人攻击呢?其中的核心就是:我们需要保证我们访问的就是目标服务器,例如,当我们访问百度时,我们需要确保在 TLS 握手时,给我们公钥的人就是百度,而不是任何其他人。

    那么这个应该如何去保证呢?这就不得不提到接下来的几个概念了,数字证书,以及证书权威机构(Certificate Authority,简称 CA)。

    六、数字证书与 CA

    数字证书是由证书权威机构(CA)颁发的一个用于证明身份的证书,当然其中还包含了该用户的公钥等信息。

    例如还是以百度为例,假设百度需要给 www.baidu.com 这个域名申请一个数字证书,他需要在生成公钥/私钥后,将自身的信息(包括域名、公司名称、公钥信息等)发给某个证书权威机构(CA),让 CA 给自己颁发一个数字证书。

    CA 需要验证百度的真实身份,并且他确实拥有 www.baidu.com 这个域名,一切都验证通过后,CA 才会给百度颁发这么一个数字证书。那么之后,不管是谁用浏览器访问 www.baidu.com 的时候,百度都会将刚才那个 CA 颁发的数字证书发送给用户,既可以用来自证身份,同时还顺便告诉了用户自己的公钥。

    到这里你可能还会有几个疑问:

  • 数字证书如何保证不能伪造呢,难道中间人不能伪造一个数字证书发送给用户吗?
  • 即使数字证书不能被伪造,从概念上看他是公开的,难道中间人不能直接把这个证书颁发给用户吗?
  • 下面会一一回答这几个问题。正式回答之前,先来看看数字证书里究竟有哪些内容。

    既然上面提到百度,我们就以百度为例,我们使用浏览器访问百度,可以在地址栏左边看到一个小锁,点击后,就可以查看百度的数字证书

    图片

    (浏览器地址栏上的“锁”图标)

    图片

    (查看数字证书)

    上图中可以看到该证书的一些基本信息:

    • 颁发对象:这个证书是颁发给百度的,并且只对域名 (www.)baidu.com 有效
    • 颁发者:这个证书是由 GlobalSign 颁发的。(GlobalSign是一家全球知名的证书权威机构)
    • 有效期:这个证书的有效期是从 2022 年 7 月到 2023 年 8 月。(一旦过期,证书将不被信任)
    • 指纹:指纹是整张证书经过哈希计算后得到的特征值,主要与后面会提到的签名一起工作,起到防篡改的作用

    当然,一张数字证书的内容远远不止于此,例如还包含了服务器的公钥,可以在“详细信息”中进行查看。

    下面我们在证书详细信息中点击“导出”,将证书导出为 Base64 编码的单一证书,然后使用 openssl 对其进行解析和查看

    $ openssl x509 -noout -text -in baidu.com.cer
    Certificate:
        Data:
            Version: 3 (0x2)
            Serial Number:
                44:17:ce:86:ef:82:ec:69:21:cc:6f:68
        Signature Algorithm: sha256WithRSAEncryption
            Issuer: C=BE, O=GlobalSign nv-sa, CN=GlobalSign RSA OV SSL CA 2018
            Validity
                Not Before: Jul  5 05:16:02 2022 GMT
                Not After : Aug  6 05:16:01 2023 GMT
            Subject: C=CN, ST=beijing, L=beijing, OU=service operation department, O=Beijing Baidu Netcom Science Technology Co., Ltd, CN=baidu.com
            Subject Public Key Info:
                Public Key Algorithm: rsaEncryption
                    RSA Public-Key: (2048 bit)
                    Modulus:
                        00:aa:2f:cc:41:8d:25:ae:83:e9:f4:27:c4:00:b3:
                        39:6f:0e:98:2a:55:7d:07:e5:80:49:82:fa:d3:d3:
                        85:98:b5:df:7b:6f:bb:02:dd:ed:78:e4:0c:07:2b:
                        9e:1e:86:4b:f6:6a:86:58:d7:57:6f:21:59:11:d8:
                        6f:96:6e:d2:de:36:28:f6:b4:e3:ce:95:32:29:00:
                        c1:65:8e:69:b0:00:fe:52:37:f4:88:3f:8b:6d:0f:
                        bb:f0:ec:c5:c0:31:ef:ad:b5:0c:06:66:ad:be:dc:
                        43:13:c4:66:b0:5d:cf:56:53:e2:d1:96:82:1c:06:
                        bb:9b:5f:ed:60:8d:d2:ed:f3:d2:50:ee:bb:cd:b2:
                        36:97:c8:ce:7b:d2:4b:b7:5c:b4:88:ca:37:6e:8b:
                        ce:f9:96:fd:b4:f5:47:b5:20:77:bb:fc:a8:9d:81:
                        b2:6c:f8:c7:09:6a:dd:22:6e:83:3f:a7:53:df:f1:
                        da:2f:29:6b:22:c3:e9:1d:65:e8:c5:a0:ba:13:4e:
                        16:3f:03:93:f0:a5:59:8a:1a:80:e8:27:7d:49:23:
                        df:d1:f9:4b:97:b7:01:c4:19:f5:f1:c5:ff:91:33:
                        d0:a1:74:c6:ee:d4:cf:f6:38:0c:ed:bd:5e:aa:44:
                        fb:88:f7:7b:99:70:76:34:55:7e:55:d2:0f:9e:bf:
                        94:93
                        
        ... (中间省略)
       
        Signature Algorithm: sha256WithRSAEncryption
             63:21:07:23:47:06:eb:b3:7c:77:6c:df:bc:55:12:b9:f1:5e:
             6a:04:60:16:be:d0:0b:18:9c:94:0c:a8:82:08:25:0d:26:fb:
             dd:cb:fc:8c:27:d9:0c:fa:4a:b6:31:b6:67:f0:26:2c:0d:96:
             96:39:65:3f:d9:a1:ee:de:9c:10:4d:54:e1:c8:d6:a9:0e:77:
             db:00:e2:37:e3:3f:b4:9c:31:4f:ac:74:d3:22:12:53:36:d0:
             ef:18:07:2d:8e:d0:e6:91:b2:6c:4a:5e:39:53:14:58:4e:d1:
             50:04:c9:83:7e:0d:7b:15:96:87:11:d7:5d:4a:17:ac:aa:9f:
             84:e3:a8:24:9d:d6:17:77:26:8c:9f:7a:7b:18:da:39:2f:77:
             f7:2b:c7:23:b8:97:6f:c3:d1:72:4c:7e:fc:c6:0d:cc:73:38:
             19:81:fb:e7:c1:7a:e8:b9:1d:3a:05:dc:36:04:9b:f1:f0:e1:
             a6:47:a0:30:4f:55:90:6c:da:cf:9e:b2:76:12:11:a1:5c:b6:
             61:8d:15:a4:68:65:9a:57:2f:7a:6e:a3:1f:f5:b4:92:5a:3c:
             df:71:0a:cd:57:d4:d0:15:36:7e:ba:d5:03:25:27:45:b4:60:
             cd:2e:02:c1:0f:0a:e7:41:6f:58:69:20:9e:ad:47:52:1a:b5:
             e6:e5:8d:1d
    

    可以看到,除了上面 Chrome 里显示的一些基本信息外,证书里还包含了几个重要信息:

    • 服务器端的公钥,即上面 RSA Public-Key 下面的那一长串数字,就是百度的公钥了。
    • 签名,证明数字证书有效的关键信息。如果把数字证书类比成一张合同的话,我们知道合同需要老板签字才算有效,同样,数字证书是需要 CA 签名才算有效的,这里的一长串字符就是 CA 对该证书的“签名”了。

    我们知道合同上的签名是靠笔迹鉴定来确认真伪的,很明显这一长串字符里没有笔迹,那它是如何保证该签名是 CA 颁发的,而不是被其他人伪造的呢?

    上面我们提到,每一张数字证书有一个指纹,是将整张证书经过哈希运算后得到的特征值。CA 作为权威机构,其本身也是有一对公钥/私钥的,它在颁发数字证书的时候,会用自己的私钥对证书的指纹进行加密,生成的这段加密数据,就是该证书的签名了!那么我们浏览器是如何验证证书的真伪呢?我们只需要使用 CA 的公钥对签名进行解密,看看得到的值是不是跟证书的指纹是一样的,这样就 OK 了,只要是一样,说明这个证书一定是 CA 颁发的。

    那么,又有问题来了:我们浏览器是从哪里拿到 CA 的公钥呢?总不能还是通过网络传输吧,这样就有“套娃”的中间人攻击风险了。所以啊,我们的浏览器或操作系统已经内置了世界权威的 CA 的数字证书(证书里就包含了其公钥)了,点击浏览器的 设置 -> 隐私设置和安全性 -> 安全 -> 管理设备证书,可以查看当前系统内置的所有 CA 证书。

    图片

    上图是我的电脑中内置的 CA 证书。刚刚提到了百度的数字证书是由 GlobalSign 颁发的,这里也可以验证,GlobalSign 是被我们的操作系统所信任的 CA,并且我们已经将它的证书内置在操作系统中了。因此现在我们可以认定说,这个证书是值得信任的,与我们建立连接的就是百度,不是别人。

    你可能会想,如果中间人将百度真实的数字证书返回给我呢?中间人是没有百度的私钥的,所以当我们提取出证书中的公钥,并对心里想的密钥进行加密后,中间人是解不开这个密钥的,所以中间人无论如何也无法与我们建立连接。

    好了,数字证书的内容已经全部讲述完毕了,最后回过头来复习下前面提到的两个问题:

    问:数字证书如何保证自身不会被伪造?

    数字证书中有一段签名,该签名是 CA 使用其私钥对证书指纹进行加密后得到的值,我们浏览器使用 CA 的公钥对该签名进行解密后,与该证书的指纹进行对比,就可以知道证书是否被篡改或者伪造了。

    当然,这里要多提一嘴,我们作为客户端,需要保证自己的电脑里保存的都是值得信任的 CA 根证书,因为信任某 CA 就代表信任了该 CA 颁发的所有数字证书,如果有人/软件想在你的电脑里安装来历不明的 CA 证书,那你就要保持警惕了...

    问:如果中间人直接把真实的数字证书返回给我,它能够成功与我建立连接吗?

    答案是不行的。这个问题其实比较简单,刚刚提到,服务器端除了公钥外,自身还保存有一份私钥的,而中间人是拿不到这个私钥的,因为它被服务器雪藏起来,不会发送到互联网中的...那么如果中间人用服务器的证书返回给用户,用户采用服务器的公钥对自身默念出来的对称密钥进行加密后,返回给中间人的时候,中间人就一脸懵逼了,因为这个密钥它解不开呀,它没有私钥的,所以这个问题就完美解决了。

    七、TLS 握手具体过程

    最后,我们再完完整整讲一下 TLS 握手的具体流程。

    图片

    上图来自 www.ssl.com ,展示了整个握手流程,我用大白话解释一下:

  • 客户端向服务器发送 Client Hello 信息,告知自己想要建立一条 TLS 连接,并告知自己支持的加密算法。
  • 服务器向客户端发送一个 Server Hello 的回应,并选择一个加密算法,同时给客户端发送自己的数字证书(包含服务器的公钥)。
  • 客户端验证服务器发来的数字证书,验证通过后,在心里默默想出一个 pre-master 密钥(预主密钥),然后使用服务器的公钥,将预主密钥进行加密后,发送给服务器。
  • 服务器用自己的私钥进行解密,得到预主密钥。
  • 客户端和服务器都通过预主密钥,进行相同的计算后,得到后续通信时使用的对称加密密钥,称为 shared secret。
  • 客户端和服务器端都分别用生成的 shared-secret 加密一段报文后,发送给对方,以验证对方能够成功收到信息并解密。
  • 然后 TLS 就建立成功了,接下来双方都用这个 shared-secret 进行加密通信。

    总结一下,HTTPS 的加密过程中其实既用到了非对称加密也用到了对称加密,其中握手过程使用的是非对称加密,主要目的是双方可以安全的协商一个统一的密钥,而真正的数据传输过程则使用的是对称加密,正是使用刚才商量的这个密钥。

    你可能会问,为什么不全程使用非对称加密呢?因为对称加密效率更高,尤其是在大量数据的时候,对称加密比非对称加密整整快几个数量级,所以真正数据传输的过程选用了对称加密。

    到这里,HTTPS 的原理就已经全部介绍完毕了。如果还有什么疑问,欢迎私信我或在留言区讨论。

    八、总结

    最后,我们总结一下,HTTPS 解决了两个问题:

  • 数据传输过程中的安全问题,因为它对数据进行了加密,只有浏览器和服务器可以对其进行解密。
  • 浏览器对服务器的信任问题,数字证书以及其中的数字签名,保证了我们访问的就是我们想要访问的服务器,不可能被钓鱼网站欺骗,也不可能被中间人攻击所欺骗。
  • 当然,保证以上安全的前提是我们的电脑本身没有被攻破,如果你的电脑被黑客攻击,装上了来历不明的根证书,那么 HTTPS 也不能保障你的安全了。

    附录一:HTTP 实战

    HTTP 实战部分针对不太熟悉 HTTP 的同学,熟悉的同学请直接跳过。

    在浏览器(建议 Chrome)中访问 httpbin.org,并使用开发者工具进行观察

    图片

    点击 Request Headers 后面的 View source,可以看到原始的 HTTP 请求报文,摘抄如下

    GET / HTTP/1.1
    Accept: text/html,...
    Accept-Encoding: gzip, deflate
    Accept-Language: zh-CN,zh;q=0.9
    Cache-Control: no-cache
    Connection: keep-alive
    Host: httpbin.org
    Pragma: no-cache
    Upgrade-Insecure-Requests: 1
    User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36
    

    其中:

    • GET 表示请求方法,常见的 HTTP 请求方法有 GET、POST、PUT、DELETE 等...
    • GET 后面的 /表示请求路径,这里我们访问的根路径,所以显示为 /。如果你访问 httpbin.org/get的话,这里显示的就是 /get了
    • HTTP/1.1 表示使用的 HTTP 协议版本,现在常用的有 HTTP/1.1 和 HTTP/2,当然还有更先进的 HTTP/3,这里就不过多展开了
    • 下面的 9 行全部都是 HTTP header,每一个 header 包含 name 和 value,之间用冒号分隔开。

    当然,点击 Response Headers 后面的 view source,你就可以看到服务器返回给你的 HTTP 响应头是怎么样的了

    HTTP/1.1 200 OK
    Date: Sat, 08 Apr 2023 16:28:43 GMT
    Content-Type: text/html; charset=utf-8
    Content-Length: 9593
    Connection: keep-alive
    Server: gunicorn/19.9.0
    Access-Control-Allow-Origin: *
    Access-Control-Allow-Credentials: true
    
    body...
    
    • HTTP/1.1 指的协议版本,响应和请求的版本肯定是一样的了
    • 200 OK 代表返回的响应码,表示这个响应是 OK 的。另外还有非常常见的返回码 404 NOT FOUND ,表示服务器告诉你你访问的这个资源不存在...
    • 后面 7 行全部是 HTTP header,同样每一个 header 包含 name 和 value,之间用冒号分隔开。
    • 最后是 HTTP Body,也就是响应体,在 Response Header 里是看不到了,不过点击上面 Tab 页的 Response 后,就可以看到完整的响应体了。

    由于本篇文章的重点不在 HTTP,这里就不再过多展开,非常建议大家平时使用浏览器访问网页的时候,有事没事多打开下上面的开发者工具,看看 HTTP 到底是怎么工作的,说不定,还能找到一份工作呢...

    图片

    (访问百度时,开发者工具中的小彩蛋)

    当然,作为程序员,还是希望有更“极客”的方式来了解 HTTP 协议,这时候就要用到 curl命令了

    终端里输入

    curl -v httpbin.org
    

    可以看到整个 HTTP 交互的流程

    图片

    附录二:数字证书实战

    这部分实战教程将带你体验 HTTPS 的全流程,从证书生成、到 HTTPS 服务器建设、到最后的浏览器访问。教程将从以下三个方面进行:

  • 首先利用 openssl工具,模拟一个证书权威机构(CA),生成 CA 证书以及密钥。
  • 然后利用 openssl工具,模拟 techcorner.cn网站的维护者,向上面的 CA 机构申请一个数字证书
  • 使用 Nginx 搭建自己的 HTTPS 服务器,并使用上面生成的服务器证书。
  • 使用浏览器访问自己搭建的 HTTPS 服务器,体会全加密流程。
  • 值得一提的是,网上也有不少利用 openssl 生成证书的教程,但是它们质量参差不齐,绝大多数都无法生成一个浏览器识别的、能够真正用在生产环境中的证书。而本教程是我查阅官方文档、并且亲自试验过的教程,绝对有效。

    实战前,你需要准备:

    • Mac / Linux 服务器
    • 安装 openssl 工具、以及 Nginx 。

    1. 生成 CA 证书

    我们知道服务器拿到的数字证书都是从 CA 那边颁发的,所以首先我们需要模拟出一个 CA 机构,即生成 CA 证书以及密钥。

    首先生成 CA 私钥(公钥可以从私钥中提取而来)

    # 生成 CA 私钥 
    openssl genrsa -out ca.key 208
    

    然后生成证书签发申请文件

    # 生成证书签发申请文件(.csr)
    openssl req -new -key ca.key -out ca.csr -subj '/C=CN/ST=Zhejiang/L=Hangzhou/O=Tech_Corner/CN=ROOTCA'
    

    -subj 后面的参数代表了生成证书的基本信息,包括国家、省份、城市、公司名称等。CN=ROOTCA,代表是准备申请一个根证书。

    然后根据上面生成的私钥和证书申请文件,自签一个根证书

    # 自签一个根证书
    openssl x509 -req -days 365 -sha256 -extensions v3_ca -signkey ca.key -in ca.csr -out ca.cer
    

    总结一下,以上命令,一共生成了三个与 CA 有关的文件:

    • ca.key:CA 私钥
    • ca.csr:CA 为自己签发证书的请求。(该文件的作用是生成 CA 证书,生成之后不会再用到)
    • ca.cer:CA 为自己签发的证书

    可以用 openssl 命令,查看下申请的证书信息

    $ openssl x509 -in ca.cer -text -noout
    Certificate:
        Data:
            Version: 1 (0x0)
            Serial Number:
                92:63:8f:e3:23:97:e1:c6
        Signature Algorithm: sha256WithRSAEncryption
            Issuer: C=CN, ST=Zhejiang, L=Hangzhou, O=Tech_Corner, CN=ROOTCA
            Validity
                Not Before: Apr 11 15:39:56 2023 GMT
                Not After : Apr 10 15:39:56 2024 GMT
            Subject: C=CN, ST=Zhejiang, L=Hangzhou, O=Tech_Corner, CN=ROOTCA
            ... 以下省略
    

    2. 生成服务器证书

    接下来,我们模拟网站 techcorner.cn 的维护者,想要为自己的网站申请一个数字证书,所以我们需要向上面模拟的 CA 来申请证书。

    同样,我们首先生成一个自己的私钥 。

    # 生成 CA 私钥 
    openssl genrsa -out server.key 2048
    

    然后,生成一个证书签发申请文件

    openssl req -new -key server.key -out server.csr -subj '/C=CN/ST=Zhejiang/L=Hangzhou/O=Tech_Corner/CN=techcorner.cn'
    

    注意,这里 -subj中有一个很重要的参数是 CN=techcorner.cn,它代表我们生成的证书,只签发给这个域名。换句话说,其他的域名如果使用这个证书,会被浏览器判断为无效。

    以上证书签发申请文件(server.csr) 发送给 CA 后,CA 会对其做一些验证,例如验证申请者本身是不是符合资质,是不是确实拥有这个域名,等等。都确认完毕后,CA 才会决定给用户颁发这个证书。(CA 必须维护自己的权威性,随便颁发证书的 CA 将被世界所抛弃,已经有这样的先例了)

    CA 为其颁发证书的命令,可模拟如下

    openssl x509 -req -extfile

    相关文章

    服务器端口转发,带你了解服务器端口转发
    服务器开放端口,服务器开放端口的步骤
    产品推荐:7月受欢迎AI容器镜像来了,有Qwen系列大模型镜像
    如何使用 WinGet 下载 Microsoft Store 应用
    百度搜索:蓝易云 – 熟悉ubuntu apt-get命令详解
    百度搜索:蓝易云 – 域名解析成功但ping不通解决方案

    发布评论