我肝没了!1 万字帮你学会 HTTPS
The following article is from 技术角落 Author 满天星
前言
一、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/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 代表返回的响应码,表示这个响应是符合预期的。另外还有非常常见的返回码 404 NOT FOUND ,大家应该或多或少听说过,它表示服务器告诉你你访问的这个资源不存在
后面 7 行全部是 HTTP header,同样每一个 header 包含 name 和 value,之间用冒号分隔开。
最后是 HTTP Body,也就是响应体,即服务器返回给你的内容主体,浏览器正是根据响应体来渲染页面的
二、为什么需要 HTTPS
战场上军队之间是提前约定好加密方案的,但是咱们任意一个浏览器都可以随时访问网页,没有办法提前约定加密方案呀,那是怎么做到的呢?
战场上经常出现敌军对另一方部队之间的电台加密进行破解的事情,破解完成之后,还是能够窃听到数据,那 HTTPS 的这个加密方案到底安全吗,会被破解吗?
三、HTTP + SSL = HTTPS !
定义:SSL(Secure Sockets Layer)是一种安全协议,用于在互联网上保护数据的传输安全。它工作在传输层,主要功能是通过加密技术,保护不同计算机之间的数据传输过程,防止敏感数据被黑客窃取和篡改。SSL 协议可以用于保护网站的用户登录、信用卡支付、网上银行等敏感信息的传输,以及企业之间的机密数据的传输。SSL 协议目前已经被继承为 TLS(Transport Layer Security),是一种安全性更高的传输层协议。所以,下面我将统一以 TLS 为名称进行讲解。
四、对称加密、非对称加密
五、中间人攻击
六、数字证书与 CA
数字证书如何保证不能伪造呢,难道中间人不能伪造一个数字证书发送给用户吗?
即使数字证书不能被伪造,从概念上看他是公开的,难道中间人不能直接把这个证书颁发给用户吗?
颁发对象:这个证书是颁发给百度的,并且只对域名 (www.)baidu.com 有效
颁发者:这个证书是由 GlobalSign 颁发的。(GlobalSign是一家全球知名的证书权威机构)
有效期:这个证书的有效期是从 2022 年 7 月到 2023 年 8 月。(一旦过期,证书将不被信任)
指纹:指纹是整张证书经过哈希计算后得到的特征值,主要与后面会提到的签名一起工作,起到防篡改的作用
$ 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
服务器端的公钥,即上面 RSA Public-Key 下面的那一长串数字,就是百度的公钥了。
签名,证明数字证书有效的关键信息。如果把数字证书类比成一张合同的话,我们知道合同需要老板签字才算有效,同样,数字证书是需要 CA 签名才算有效的,这里的一长串字符就是 CA 对该证书的“签名”了。
问
数字证书如何保证自身不会被伪造?
问
如果中间人直接把真实的数字证书返回给我,它能够成功与我建立连接吗?
七、TLS 握手具体过程
客户端向服务器发送 Client Hello 信息,告知自己想要建立一条 TLS 连接,并告知自己支持的加密算法。
服务器向客户端发送一个 Server Hello 的回应,并选择一个加密算法,同时给客户端发送自己的数字证书(包含服务器的公钥)。
客户端验证服务器发来的数字证书,验证通过后,在心里默默想出一个 pre-master 密钥(预主密钥),然后使用服务器的公钥,将预主密钥进行加密后,发送给服务器。
服务器用自己的私钥进行解密,得到预主密钥。
客户端和服务器都通过预主密钥,进行相同的计算后,得到后续通信时使用的对称加密密钥,称为 shared secret。
客户端和服务器端都分别用生成的 shared-secret 加密一段报文后,发送给对方,以验证对方能够成功收到信息并解密。
八、总结
数据传输过程中的安全问题,因为它对数据进行了加密,只有浏览器和服务器可以对其进行解密。
浏览器对服务器的信任问题,数字证书以及其中的数字签名,保证了我们访问的就是我们想要访问的服务器,不可能被钓鱼网站欺骗,也不可能被中间人攻击所欺骗。
附录一: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/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 后,就可以看到完整的响应体了。
curl -v httpbin.org
附录二:数字证书实战
首先利用 openssl工具,模拟一个证书权威机构(CA),生成 CA 证书以及密钥。
然后利用 openssl工具,模拟 techcorner.cn网站的维护者,向上面的 CA 机构申请一个数字证书
使用 Nginx 搭建自己的 HTTPS 服务器,并使用上面生成的服务器证书。
使用浏览器访问自己搭建的 HTTPS 服务器,体会全加密流程。
Mac / Linux 服务器
安装 openssl 工具、以及 Nginx 。
1. 生成 CA 证书
# 生成 CA 私钥
openssl genrsa -out ca.key 2048
# 生成证书签发申请文件(.csr)
openssl req -new -key ca.key -out ca.csr -subj '/C=CN/ST=Zhejiang/L=Hangzhou/O=Tech_Corner/CN=ROOTCA'
# 自签一个根证书
openssl x509 -req -days 365 -sha256 -extensions v3_ca -signkey ca.key -in ca.csr -out ca.cer
ca.key:CA 私钥
ca.csr:CA 为自己签发证书的请求。(该文件的作用是生成 CA 证书,生成之后不会再用到)
ca.cer:CA 为自己签发的证书
$ 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. 生成服务器证书
# 生成 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'
openssl x509 -req -extfile <(printf "subjectAltName=DNS:techcorner.cn,DNS:www.techcorner.cn") -days 365 -in server.csr -CA ca.cer -CAkey ca.key -CAcreateserial -out server.cer
$ openssl x509 -in server.cer -text -noout
Certificate:
Data:
Version: 1 (0x0)
Serial Number:
80:56:02:4d:21:ff:5e:60
Signature Algorithm: sha256WithRSAEncryption
Issuer: C=CN, ST=Zhejiang, L=Hangzhou, O=Tech_Corner, CN=ROOTCA
Validity
Not Before: Apr 11 15:52:10 2023 GMT
Not After : Apr 10 15:52:10 2024 GMT
Subject: C=CN, ST=Zhejiang, L=Hangzhou, O=Tech_Corner, CN=techcorner.cn
...以下省略
3. 启动 Nginx,并使用证书
server {
listen 443 ssl;
server_name techcorner.cn;
ssl_certificate /path/to/server.cer;
ssl_certificate_key /path/to/server.key;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
location / {
root html;
index index.html index.htm;
}
}
ssl_certificate的值修改为上一步生成的 server.cer 的绝对地址
ssl_certificate_key 的值修改为上一步生成的 server.key 的绝对地址
这个 CA 证书是我们自己生成的,只要我们自己不泄漏其私钥,那么将是安全的
127.0.0.1 techcorner.cn
往期推荐