【学习笔记】HTTP

第一章:HTTP基础

一、HTTP历史

  1. 史前:建立ARPA网
  2. 创世纪:Tim Berners-Lee 提出了构建超链接文档系统。
    • URI:统一资源标识符
    • HTML:超文本标记语言
    • HTTP:超文本传输协议
  3. HTTP/0.9:只有GET请求,从服务器上获取HTML文档后,立即关闭连接。
  4. HTTP/1.0:加入HEAD、POST请求;增加响应状态码、标记可能错误原因;引入协议版本号;引入HTTP header投不概念;传输数据不仅限于文本。
  5. HTTP/1.1:增加PUT、DELETE等方法;增加缓存管理和控制;明确连接管理,允许持久连接;允许响应数据分块,有利于大文件传输;强制要求Host头,让互联网主机托管称为可能;
  6. HTTP/2:Google使用Chrome推出的SPDY协议发展而成的。注重性能改善,但还未普及;
  7. 特性:
    • 二进制协议
    • 可以发起多个请求
    • 使用专用算法压缩头部,减少数据量传输
    • 允许服务器主动向客户端推送数据
    • 增强安全性能,要求加密通信
  8. HTTP/3:Google使用Chrome推出的QUIC协议发展而成的。未来发展方向

二、HTTP全览

(一)HTTP超文本传输协议

  • 超文本:超约了普通文本的文本,传输文字、图片、音频、视频等。
  • 传输:HTTP是一个在计算机世界里专门用来在两点之间传输数据的约定和规范
    1、HTTP协议是一个“双向协议”
    2、不限定两个角色,允许有中转或接力A<=>X<=>Y<=>Z<=>B 
    
  • 协议:计算机之间交流通信的规范,以及相关的各种控制和错误处理方式。

(二)其他概念

  1. 浏览器:本质上是HTTP协议中的“请求方”。被称为“User Agent”用户代理。
  2. Web服务器:“应答方”,响应请求的主体。
  3. CDN:内容分发网络,应用了HTTP协议中的缓存和代理技术。
  4. 爬虫:自动访问Web资源的应用程序。
  5. HTML:超文本页面。
  6. WebService:基于Web(HTTP)的服务架构技术。
  7. WAF:网络应用防火墙。

(三)特点

  1. 灵活可扩展,可以任意添加头字段,实现功能;
  2. 可靠传输,基于TCPIP协议,尽量完成数据“送达”;
  3. 应用层协议,比FTP、SSH更通用,能够传输任意数据;
  4. “请求-应答”模式,客户端请求,服务端应答。
  5. 无状态,每个请求相互独立,不要求服务器记录信息。
    • 无状态是与TCP的状态相对应(Closed、Established等状态)
    • 轻松实现集群化,扩展性能。
    • 使用“cookie”实现有状态。
  6. 明文传输,方便研究,但造成不安全。
  7. 不安全>>HTTPS
  8. 性能:不算差,不够好>>“对头阻塞问题”

三、请求过程

如图所示,这是一个最简单的请求服务器的过程。

HTTP请求过程:

  1. 浏览器地址栏输入域名。
  2. 通过DNS获取域名对应的IP地址。
  3. 浏览器使用TCP的三次握手与服务器建立连接。
  4. 浏览器向服务器发送拼接好的报文。
  5. 服务器接收到报文后处理请求,同时拼好报文,再发送给浏览器。
  6. 浏览器解析报文,渲染输出页面。

这里主要涉及两个部分,一个是三次握手的过程,一次是传输过程。

首先,TCP三次握手:

  • 可以观察到,从第一行到第六行,是发送了两个TCP请求。这里同时发起两个是因为,HTTP连接成功率低,因此浏览器同时发起多个TCP请求,提高成功率。
  • TCP进行三次握手的过程:[SYN],Seq=0>>[SYN,ACK],Seq=0,Ack=1>>[ACK],Seq=1,Ack=1

  1. HTTP传输页面。

    • GET/HTTP/1.1>>ACK>>HTTP/1.1 200 OK >> ACK

四、报文结构

HTTP是一个纯文本协议,头部信息都是ASCII码的文本,可以轻松阅读。

大头儿子

在HTTP中的请求报文和响应报文,主要包括这样三个部分

  • 起始行:描述请求和响应的基本信息。(请求行与状态行)
  • 头部字段集合:使用key-value 形式,详细说明报文。
  • 消息正文:实际传输的数据,包括文本、图片、视频等二进制数据。
我们一般将起始行与头部字段集合统称为“Header”,而将消息正文称为实体“Body”。(大头儿子) ![](http://imgs.windranger.wang/http1_5.jpg) 如上图所示, - 第一个红框:起始行,包括请求行和状态行。 在请求报文中,称为“请求行”;响应报文中,称为响应行。 - 请求行:“GET / HTTP/1.1” 它主要由三部分组成,请求方法,请求目标, 版本号。 ![](http://imgs.windranger.wang/http1_8.jpg) - 状态行:“HTTP/1.1 200 OK”,“HTTP/1.1 404 Not Found” 它主要由三部分组成,版本号,状态码,原因(对状态码进行解释说明)。 ![](http://imgs.windranger.wang/http1_9.jpg) - 第二个红框:头部字段 以“Key:Value”的形式进行描述的。 需要注意的是: - 不区分大小写。 - 字段里不能出现空格,可以使用“-”,但是不能使用“_”。 - Key后面必须紧接着":",不得有空格。 - 无序,不重复(除非字段本身语意允许) HTTP中的头部字段有很多,大致可以分为以下四类。 - 通用字段:在请求头和响应头中均可出现。 - 请求字段:仅在请求头中出现。 - 响应字段:仅在响应头中出现。 - 实体字段:专门用于描述Body的额外信息。 常用的有: - 通用字段: - Host:请求的主机名,允许多个域名同处一个IP地址,即虚拟主机。(必须出现的字段) - User-Agent:描述HTTP请求的客户端。 - Date:HTTP报文创建时间。 - 响应字段: - Server:Web服务器的软件名称和版本号。 - 实体字段: - Content-Length:表示body的长度。 ## 五、请求方法 ### (一)规定的八种方法 1. GET:获取资源。获取数据 2. HEAD:获取资源的元信息。获取数据 - 与GET方法类似,但是服务器不会返回请求的实体数据,只会传回”Header“,也就是资源的”原信息“。 3. POST:想资源提交数据,相当于写入或上传数据。提交数据 4. PUT:类似于POST。提交数据 - 大多为修改的意思 5. DELETE:删除资源。 6. CONNECT:建立特殊的连接隧道。 7. OPTIONS:列出可对资源实行的方法。 8. TRACE:追踪请求--响应的传输路径。 仅有前4种比较常用。 在RESTFul风格种,常用这五个请求,表示不同状态。 - GET(SELECT):从服务器取出资源(一项或多项)。 - POST(CREATE):在服务器新建一个资源。 - PUT(UPDATE):在服务器更新资源(客户端提供改变后的完整资源)。 - PATCH(UPDATE):在服务器更新资源(客户端提供改变的属性)。 - DELETE(DELETE):从服务器删除资源。 ### (二)安全与幂等 **安全:请求方法不会”破坏“服务器上的资源,即不会对服务器上的资源造成实质性的修改。** - GET/HEAD方法是“安全”的。 - POST/PUT/DELETE操作会修改服务器上的资源,所以是“不安全的”。 **幂等:多次执行相同的操作,结果也是相同的。即多次“幂”后结果“相等”。** - GET/HEAD方法是“幂等”的。 - DELETE多次删除同一个资源也是“幂等”的。 - POST会新增数据,所以不是“幂等”。 - PUTS是更新同一个资源,所以是“幂等”。 ## 六、URI 规范 URI: Uniform Resource Identifier 统一资源标识符,它包含URL和URN - URL: Uniform Resource Locator 统一资源定位符 - URN: Uniform Resource Name 统一资源名称。 ![](http://imgs.windranger.wang/uri.jpg) ### (一)URI 格式 URI的最常用形式主要由 scheme,host:port, path, query这四部分组成。 - scheme:方案名,协议名。包括:http(80),https(443),ftp(20,21) 等协议。 - ://:用于将scheme与后面的部分分隔。 - host:port:表示资源所在的主机名与端口号。 - path:类似于文件系统的目录(路径),必须以“/”开始。 - ?query:表示对资源附加的额外要求。以“key-value”字符串组成。 ps:有的URI 可能还会出现"#frament",片段标识符。它是URI定位资源的锚点,浏览器获取资源后直接跳转到它指示的位置。 ![](http://imgs.windranger.wang/uri1.jpg) ### (二)浏览器中形式 当输入“http://www.chrono.com:8080/11-1?uid=1234&name=mario&referer=xxx”时, F12中显示: ![](http://imgs.windranger.wang/uri3.jpg) 在请求行中:请求方法和path+?query 在Query中:正常显示了Key-Value的查询参数 ### (三)URI的编码 将ASCII以外的字符集和特殊字符进行“转义”,直接将非ASCII码转换成十六进制的字节值,然后在前面加上一个% 例如: 请求“http://www.chrono.com:8080/11-1? 夸父逐日” >>“http://www.chrono.com:8080/11-1?%E5%A4%B8%E7%88%B6%E9%80%90%E6%97%A5” ## 七、响应状态码 在服务器返回的状态行中,如下图所示,由协议版本号、状态码和说明组成。 ![](http://imgs.windranger.wang/http1_7.jpg) 状态码主要分为了五类: - 1xx:提示信息,表示协议处理的中间状态,还需要后续操作; - 101 Switching Protocols:客户端使用Upgrade字段,要求服务端在HTTP协议的基础上改为其他协议进行,如果服务端返回101,则之后的传输不会再用HTTP协议。 - 2xx:成功; - 200 OK:一切正常 - 204 No Content:一切正常,但header后面body - 206 Partial Content:是HTTP分块下载或者断点续传的基础上,返回的是客户端请求资源的一部分。 - 通常会伴随着 Content-Range 字段,表示报文中body数据的具体范围,供客户端确认。例如“Content-Range:bytes 0-99/2000”,表示获取总计2000个字节的前100个字节。 - 3xx:重定向,资源位置发生变动,需要客户端重新发送请求; - 301 Moved Permanently :永久重定向,此资源已经不存在了,需改用新的URI访问。 - 302 Found:临时重定向。 - 304 Not Modified:资源未修改,用于缓存控制。它用于If-Modified-Since等条件请求,查看资源是否修改,是否要重新进行缓存。 - 4xx:客户端错误; - 400 Bad Request:请求报文有错误,没说明原因。 - 403 Forbidden:服务器禁止访问该资源,可能因为权限等问题。 - 404 Not Found:资源未找到。 - 405 Mehod Not Allowed:不允许使用某些方法操作资源,例如不允许使用Post。 - 408 Requst timeout:请求超时。 - 5xx:服务端错误; - 501 Not Implemented:客户端请求的功能还不支持。 - 502 Bad Gateway:服务器自身工作正常,访问后端服务器时发生错误,具体错误不知道。 - 503 Service Unavailable:服务器正忙,无法响应服务。 - 通常会带一个“Retry-After” 指示客户端可以多久后再发送请求。 # 第二章:HTTP进阶 ## 一、实体类型与编码 ### (一)实体数据 1. 实体类型 HTTP借用了 MMIE方案【Multipurpose Internet Mail Extensions 多用途互联网邮件扩展】。MMIE原用于电子邮件系统中,让电子邮件发送ASCII码外的任意数据。 常用的几个类别有: - test:文本格式的可读文件;包括text/html(超文本文档)、text/plain(纯文本)、text/css(样式表) - image:图像文件;有image/gif、image/jpeg、image/png - audio/video:音频和视频数据;如audio/mpeg、video/mp4 - application:数据格式不固定,可能是文本也可能是二进制,必须由上层应用来解释。常用的有:application/json、application/javascript、application/pdf、application/octet-stream(不透明的二进制数据) 实体类型相应的头字段是Accept和Content-Type
  1. 压缩格式

    • gzip:GNU zip压缩格式,最流行的。
    • deflate:zlib(deflate)压缩格式。
    • br:一种专门为HTTP优化的新压缩算法。
    相应的头字段是Accept-Encoding和Content-Encoding
  2. 自然语言格式

    Accept-Language: zh-CN, zh, en Content-Language: zh-CN

  3. 编码方式

    Accept-Charset: gbk, utf-8 Content-Type: text/html; charset=utf-8

  4. 内容协商质量

    在Accept中,常常会出现q字段,它是用于设置数据的优先级的。

    Accept: text/html,application/xml;q=0.9,*/*;q=0.8 它表示浏览器最希望使用的是 HTML 文件,权重是 1,其次 XML 文件,权重是0.9,最后是任意数据,权重是0.8

(二)协商方式

有了编码格式和压缩类型,无论是浏览器还是客户端都可以轻松识别出body类型,并处理数据了。当然,他们两要经过“内容协商”才能达成一致,具体过程是:

  1. 客户端使用Accept头告诉服务器希望收到什么样的数据。
  2. 服务器用Content头告诉客户端实际发送了什么样的数据。

编码格式:

1
2
Accept: text/html,application/xml,image/webp,image/png
Content-Type: text

二、解决大文件问题

(一)压缩

浏览器通过Accept-Encoding头字段告知服务端,浏览器支持的压缩格式列表,服务端选择一种压缩算法,放到Content-Encoding响应头中,把压缩后的数据发送给浏览器。

gzip 是针对文本文件有着较好的压缩率。

(二)分块传输

chunked分块传输编码:这是用于解决大文件传输的一种手段,即每次只收发一小部分,网络也不会被大文件长时间占用,内存、带宽资源也就节省下来了。

响应报文里的头字段为`Transfer-Encoding:chunked`,意思是说body部分不是一次性发送过来的,而是分成了很多块(chunked)逐个发送的。
  • 在响应报文中,Transfer-EncodingContent-Length是互斥的,响应报文中不可能同时出现。

分块传输的编码规则如下所示:

  • 每个分块含两个部分,长度头和数据块;
  • 长度头是以CRLF(\r\n)结尾的一行明文,用16进制数字表示长度;
  • 数据头紧跟着长度头后,最后页用CRLF结尾,但数据不包含CRLF
  • 最后用一个长度为0的块表示结束,即使0\r\n\r\n

(三)范围请求

跳过片头,看后面的视频。>> 范围请求。

  1. 响应方:
    • 在响应头里 使用 Accept-Ranges:bytes告知客户端,我是支持范围请求的。
    • 不支持: Accept-Ranges:none,或者干脆不发送这个字段。
  2. 请求方:使用Range:bytes=x-y请求x和y之间的数据。
  3. 响应方在收到请求后。
    • 一般先要检查范围的合法性。
    • 然后根据范围读取文件。
    • 最后在响应报文中添加一个Content-Range:bytes x-y/length的字段,发送给客户端。

(四)多端数据

范围请求是一次请求一个片段,多端请求可以一次请求多个片段。

Content-Type:multipart/byteranges;boundary=xxxx给出之间的分割标记。

发送数据:

1
2
3
GET /16-2 HTTP/1.1
Host: www.chrono.com
Range: bytes=0-9, 20-29

接收数据:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
HTTP/1.1 206 Partial Content
Content-Type: multipart/byteranges; boundary=00000000001
Content-Length: 189
Connection: keep-alive
Accept-Ranges: bytes


--00000000001
Content-Type: text/plain
Content-Range: bytes 0-9/96

// this is
--00000000001
Content-Type: text/plain
Content-Range: bytes 20-29/96

ext json d
--00000000001--

三、连接管理

HTTP的连接管理是一个老生常谈的问题,他影响了HTTP的性能。

RTT(Round-Trip Time): 往返时延。在计算机网络中它是一个重要的性能指标,表示从发送端发送数据开始,到发送端收到来自接收端的确认(接收端收到数据后便立即发送确认),总共经历的时延。

(一)短连接

客户端与服务器连接过程很短暂,不会与服务器长期保持连接状态。

  • 在建立连接时,需要1个RTT
  • 关闭连接时,需要2个RTT
  • 一次简单的“响应—应答”一般只需要4个包,2个RTT
  • 浪费 3/5 = 60% 的资源

(二)长连接

将连接的资源分摊到多个“请求—应答”上来,提高了整体传输的效率。

  • 请求头中使用Connectoin:keep-alive
  • 请求头中加上Connection:close在本次通信后,关闭连接。

但是同样会出现,长连接占用资源的问题,因此,服务器会有两种策略。

  • 使用keepalive_timeout设置超时时间;
  • 使用keepalive_request设置最大请求次数。

(三)队头阻塞

HTTP采用“请求—响应”的方式,并且它们是“串行”的队列,没有优先级,只有按入队的先后顺序。

如果队首的请求处理太慢,耽误时间了,队里后面的请求,就只能跟着一起等待,承担了不必要的时间成本。

解决办法:并发连接(多台机器),域名分片(cdn)

四、重定向

重定向:发送了两次HTTP请求,第一次返回302,第二次返回重定向后的地址。

第一次请求:状态码302,Location:标记服务器要求重定向的URI

使用Refresh:5;url=xxx告诉浏览器5秒后跳转新的url。

(一)重定向状态码

  • 301 永久重定向:URI永久的不存在了,今后所有的请求改用新的URI。
    • 通知浏览器和搜索引擎更新到新的地址。
  • 302 临时重定向:URI临时维护中。
    • 系统维护

(二)相关问题

  • 性能损耗:因为使用了两次“请求—应答”。

  • 循环跳转:“A>>B>>A”

    • 浏览器可以自行检测

五、Cookie

(一)作用

  • 身份识别

    Cookie是用于“身份识别”,保存用户的登录信息与会话实现。比如说你使用一个电商网站,登录成功后服务器会发送给浏览器一个Cookie(用于标明身份,name=“xxxxx”),你在进行每次操作时,浏览器会自动把身份Cookie发送给服务器,服务器就知道你的身份,进行身份保持了。

  • 广告追踪

    广告网站会“偷偷”为你贴上cookie标签,然后对你实现精准的“广告推送”。

(二)Cookie的运行机制

如图所示,浏览器第一次访问服务器后,服务器向客户端发送Set-Cookie:key=value字段,浏览器看到这一字段后,将键值对绑定到Cookie字段中,进行以后的请求。这使得服务器具有记忆功能了。

(三)Cookie的属性

如图所示,

  1. Cookie的生存周期,也就是它的有效期,可以使用Expires和Max-Age两个属性来设置。

    • Expires :过期时间,使用绝对时间,可以理解为“截至时间”。
    • Max-Age:相对时间,单位是秒,浏览器收到报文的时间点加上Max-Age时间,就是失效时间。
  2. Cookie的作用域:让浏览器仅发送给特定的服务器和URI,避免被盗用。

    • Domain:即host地址
    • Path:一般直接是“/”或者省略
  3. Cookie的安全域:尽量不让服务器以外的人看见,防止XSS与XSRF/CSRF攻击

    • XSS:第三方的JS读取到浏览器中A网站的Cookie,然后冒充“我”去访问A网站。
      • 设置HttpOnly:告诉浏览器,此Cookie仅可以通过HTTP协议传输,禁止使用其它方式访问。
    • XSRF/CSRF:例如在不安全论坛上的一张图片,它实际上是一个给你银行服务器发送提现的请求:<img src="http://bank.example.com/withdraw?account=bob&amount=1000000&for=mallory">当你打开含有了这张图片的HTML页面时,如果你之前已经登录了你的银行帐号并且Cookie仍然有效(还没有其它验证步骤),你银行里的钱很可能会被自动转走。
      • 设置SameSite=Strict:可以严格限制Cookie不能随着跳转链接跨站发送。
      • 设置SameSite=Lax:允许GET/HEAD等安全方法,但禁止POST跨站发送。

六、缓存控制

(一) 服务器端策略

浏览器缓存过程:

  1. 浏览器发现缓存无数据,于是发送请求,向服务器获取资源;
  2. 服务器响应请求,返回资源,同时标记资源的有效期;
  3. 浏览器缓存资源,等待下次重用。

需要注意的是,服务器标记资源有效期使用的头字段为Cache-Control,值为max-age=30,这指的是这个页面只能缓存30秒,过了30秒后就不能再使用了。当然,Cache-Control有其它属性可以更精确的指示浏览器的缓存情况。

  • no-store:不允许缓存(用于数据变化非常频繁的页面,例如秒杀页面。)
  • no-cache:可以缓存,但是每次都要去服务器验证是否过期。
  • must-revalidate:与no-cache相似,意思是缓存不过期就直接使用,否则就必须验证。

(二)客户端缓存

客户端同样也可以使用Cache-Control:max-age=0设置缓存时间。

使用Crtl+F5可以强制刷新,相当于发送了Cache-Control:no-cache

七、代理服务

计算机科学领域里的任何问题,都可以通过引入一个中间层来解决。

代理服务:服务器本身不产生内容,而是处于中间位置转发上下游的请求和响应,具有双重身份。
  • 面向下游用户:表现为服务器,代表源服务器响应客户端的请求;
  • 面向上游服务器:表现为客户端,代表客户端发送请求。

(一)代理的作用

  1. “负载均衡”,这是代理的最基本的功能。如图所示,客户端请求源服务器时,反向代理屏蔽了源服务器(客户端只能看到代理服务器),于是代理服务器就可以掌握“请求分发”的大权,决定由后面的哪台服务器响应请求。(负载均衡算法:轮询、一致性哈希。)

  1. 健康检测:监控后端服务器,发现故障后”踢出”集群,保证服务可用。
  2. 安全防护:限制IP地址或流量,抵御网络攻击和过载。
  3. 加密卸载:对外王使用SSL/TLS加密通信认证,在安全的内网不加密,消除加密解密的成本。
  4. 数据过滤:拦截上下行的数据,任意指定策略修改请求或者响应。
  5. 内容缓存:暂存、服用服务器响应。

(三)代理相关头字段

使用Via表明代理身份,它是一个通用字段,请求头或响应头都可以出现,每当报文经过一个代理节点,代理服务器就会把自身的信息追加到字段的末尾,就像经手人盖了一个章。

如果通信链路中有很多的代理,就会在Via里形成一个链表,这样就知道报文走了多少个环节才能到达目的地了。需要注意的是Via只包含了主机名,不涉及真实的IP地址,这样保护了企业内网的安全。

另外,X-Forwarded-For表示“为谁而转发”,形式上与Via差不多,但是Via 是追加代理主机名,而X-Forwarded-For是追加请求方的IP地址。

X-Real-IP记录客户端IP信息,不包含中间代理的信息。

八、缓存代理

缓存代理,能够减少响应时间、节约带宽、提升客户端的用户体验。

在没有缓存的时候,代理服务器每次都会直接转发客户端的报文,中间不储存数据,只有简单的中转功能;加入缓存后,代理服务器首先把报文转给客户,然后将报文存入自己的Cache中。

(一)缓存控制

  • Cache-Control:max-age(最大生存时间)、no-store(不允许缓存)、no-cache(可以缓存,但要去服务器验证是否过期)、must-revalidate(缓存不过期就直接使用,否则就必须验证)
  • 服务器缓存私有属性:
    • private:用户私有,不能与别人共享
    • public:完全开放,谁都可以
    • proxy-revalidate:代理缓存过期后必须验证,客户端不必回源。
    • s-maxage:代理上能存放多久。
    • no-transform:不允许对缓存下来的数据进行优化。

第三章:HTTPS

一、HTTPS简介

它的出现是为了解决Http不安全的问题,因为HTTP是明文传输的,因此整个传输过程完全透明,任何人都可以从链路中截获,修改或者伪造请求/响应报文,数据不具有可信性。

HTTPS是将HTTP底层的传输协议由TCP/IP改为了SSL/TLS,即由HTTP over TCP/IP变成了HTTP over SSL/TLS,让HTTP运行在安全的协议上,收发报文不再使用Socket API,而是调用专门的安全接口。实际上SSL(Secure Sockets Layer)是一个会话层协议,TLS指的是SSLv3版本,TLS1.0就是SSLv3.1。另外,HTTP端口号为80,而HTTPS的默认端口号是443。

如图所示,加密方式的基本形式为密钥交换算法+签名算法+对称加密算法+摘要算法。这里使用的加密方式为ECDHE-RSA-AES256-GCM-SHA384,意思是握手时使用ECDHE算法进行密钥交换,用RSA进行签名和身份认证,握手后使用密钥长度为256,分组模式为GCMAES对称加密算法进行通信,最后使用摘要算法SHA384对消息进行认证和产生随机数。

二、对称与非对称加密

(一)对称加密

加密与解密过程使用同一个密钥,只要保证密钥安全,整个通信过程就安全了。TLS的对称加密算法有很多,例如RC4DES3DESAESChaCha20等。现在最广泛使用的是AES加密,密钥长度可以是128、192或256。

对称算法还有一个“分组模式”的概念,它可以让算法用固定长度的密钥加密任意长度的明文,把密钥转换为密文。如今最新的分组模式为AEAD,在加密的同时增加了认证功能,常用的是GCMCCMPoly1305

(二)非对称加密

为了解决对称加密中密钥交换的问题,发明了非对称加密,因为对称加密是建立在密钥保密的基础上的,如果其他人也有了这个密钥,那么就不存在所谓的“机密性”了。

非对称加密有两个密钥,一个是“公钥”,一个是“私钥”,两个是不同的不对称的,公钥可以公开给任何人,但是私钥严格保密。公钥私钥之间有着特别的“单向”性,即公钥加密的数据只能由私钥解密,私钥加密的数据只能由公钥解密。非对称加密中,常用的算法有RSA,它是基于“整数分解”的数学难题;ECC,它是基于“椭圆曲线离散对数”的数学难题。

这解决了“密钥交换”的问题,网站报关私钥,公钥在网上任意分发,如果用户想要登录网站,使用公钥加密即可,网站可以通过私钥对其进行解密。

三、安全传输

在安全传输中,我们一般通过机密性、完整性、身份认证、不可否认这四个特性定义安全传输。下面将分别介绍这四个特性。

  • 机密性:对数据的“保密”,只能由可信的人访问,对其他人不可见,即不让不相关的人看到不该看的东西。

    问题:篡改明文数据。

    解决:使用混合加密,这是因为非对称加密速度过慢,一直使用会拖慢系统性能;对称加密无法安全的进行”密钥分发“,因此通常使用非对称加密将”对称加密的密钥“进行分发后,使用对称机密进行安全通信。

  • 完整性:数据在传输过程中没有被篡改,完完整整地保持着传输原状。

    问题:捕获加密文件后,拼接,篡改数据。

    解决:使用哈希消息认证码HMAC,它包含明文与摘要(通过摘要算法把原文映射到一个小空间,例如HASH,TLS中常用SHA-2

  • 身份认证:确认对方真实身份,证明“我是我”,保证消息只发送给可信的人。

  • 不可否认:不可抵赖,不能否认已经发生过的行为。(不能说话不算数。)

    问题:伪装用户身份。

    解决:使用数字签名(即私钥+摘要算法)。用户与网站互相交换公钥,然后通过”签名“与”验签“来确认消息的真实性,这就能保证双方的身份。

此外,因为谁都可以发布公钥,便产生了一个”公钥信任“的问题。我们通过第三方的CA证书认证机构解决了这一问题,CA通过自签名证书认证了自己的身份,然后通过一级一级的发布证书。

四、TLS1.2过程

TLS包括记录协议(规定了TLS收发数据的基本单位)、警报协议、握手协议、变更密码规范协议。

如图所示,这个图简单描述了TLS握手的过程,通过四个消息完成握手,然后可以在安全的通信环境中发送HTTP报文,实现HTTPS

  1. 前期工作,建立TCP连接。

  2. 客户端>>服务器

    • “Client Hello”消息:里面包括版本号(TLS version)、支持的密码套件(Clipher Suites)、和一个随机数Client Random。(Client RandomServer RandomPre-Master生成会话密钥)。
    1
    2
    3
    4
    5
    6
    Handshake Protocol: Client Hello
    Version: TLS 1.2 (0x0303)
    Random: 1cbf803321fd2623408dfe…
    Cipher Suites (17 suites)
    Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (0xc02f)
    Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (0xc030)
  3. 服务器>>客户端

    • “Server Hello”消息:里面包括版本号(TLS version)、从客户端列表中选择作为本次通信的密码套件(Clipher Suites)、和一个服务端随机数(Server Random)。

      ps:这里使用的加密方式为TLS_ECDHE_RSA_WITH_AES_256-GCM-SHA384,意思是握手时使用ECDHE算法进行密钥交换,用RSA进行签名和身份认证,握手后使用密钥长度为256,分组模式为GCMAES对称加密算法进行通信,最后使用摘要算法SHA384对消息进行认证和产生随机数。

    1
    2
    3
    4
    Handshake Protocol: Server Hello
    Version: TLS 1.2 (0x0303)
    Random: 0e6320f21bae50842e96…
    Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (0xc030)
    • “Server Certificate”:把证书发送给客户端,证明服务器身份。
    • “Server Key Exchange”:客户端使用ECDHE算法将公钥(Server Params)发送给客户端,并加上自己的私钥签名认证。
    1
    2
    3
    4
    5
    6
    7
    Handshake Protocol: Server Key Exchange
    EC Diffie-Hellman Server Params
    Curve Type: named_curve (0x03)
    Named Curve: x25519 (0x001d)
    Pubkey: 3b39deaf00217894e...
    Signature Algorithm: rsa_pkcs1_sha512 (0x0601)
    Signature: 37141adac38ea4...
    • “Server Hello Done”:表明消息已经发完。
  4. 客户端

    • “Client Key Exchange”:客户端生成一个公钥(Client Params
    1
    2
    3
    Handshake Protocol: Client Key Exchange
    EC Diffie-Hellman Client Params
    Pubkey: 8c674d0e08dc27b5eaa…
    这时,通信双方均可使用`Client Params 客户端公钥`和`Server Params 服务端公钥`生成`Pre-Master`,将它与`Server Random`和`Client Random`组合生成一个会话密钥,称为`Master Secret`。其中`PRF`为伪随机数函数。
    1
    master_secret = PRF(pre_master_secret, "master secret",ClientHello.random + ServerHello.random)
    • “Change Cipher Spec”
    • “Finished”:把之前发过的所有消息做一个摘要,加密后发送,给服务器做验证。
  5. 服务器:

    • “Change Cipher Spec”
    • “Finished”

五、TLS1.3

为了保证使用TLS1.2的设备可以继续使用,避免老设备不兼容1.3,TLS1.3保持现有记录格式不变,通过“伪装”兼容TLS1.2,即使用“扩展协议”(在记录的末尾添加“扩展字段supported_versions”)

1
2
3
4
5
Handshake Protocol: Client Hello
Version: TLS 1.2 (0x0303)
Extension: supported_versions (len=11)
Supported Version: TLS 1.3 (0x0304)
Supported Version: TLS 1.2 (0x0303)

TLS1.3中,升级了很多漏洞,去除了很多加密算法,简化流程,提高效率。

  • 对称加密算法:AESChaCha20
  • 非对称加密算法:ECDHEDHE
  • 分组模式:AEADGCMPoly1305
  • 摘要算法:SHA256SHA384

  1. 前期准备:建立TCP连接。

  2. “Client Hello”消息:里面包括版本号(TLS version)、支持的密码套件(Clipher Suites)、一个随机数Client RandomExtension(1.3的扩展)。

    • supported_versions:支持版本
    • supported_groups:支持的曲线
    • key_share:曲线对应的参数
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    Handshake Protocol: Client Hello
    Version: TLS 1.2 (0x0303)
    Random: cebeb6c05403654d66c2329…
    Cipher Suites (18 suites)
    Cipher Suite: TLS_AES_128_GCM_SHA256 (0x1301)
    Cipher Suite: TLS_CHACHA20_POLY1305_SHA256 (0x1303)
    Cipher Suite: TLS_AES_256_GCM_SHA384 (0x1302)
    Extension: supported_versions (len=9)
    Supported Version: TLS 1.3 (0x0304)
    Supported Version: TLS 1.2 (0x0303)
    Extension: supported_groups (len=14)
    Supported Groups (6 groups)
    Supported Group: x25519 (0x001d)
    Supported Group: secp256r1 (0x0017)
    Extension: key_share (len=107)
    Key Share extension
    Client Key Share Length: 105
    Key Share Entry: Group: x25519
    Key Share Entry: Group: secp256r1
  3. “Server Hello”消息:里面包括版本号(TLS version)、从客户端列表中选择作为本次通信的密码套件(Clipher Suites)、一个服务端随机数(Server Random)、和Extension

    • supported_versions:选择的版本。
    • key_share:选择对应的曲线和公钥。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    Handshake Protocol: Server Hello
    Version: TLS 1.2 (0x0303)
    Random: 12d2bce6568b063d3dee2…
    Cipher Suite: TLS_AES_128_GCM_SHA256 (0x1301)
    Extension: supported_versions (len=2)
    Supported Version: TLS 1.3 (0x0304)
    Extension: key_share (len=36)
    Key Share extension
    Key Share Entry: Group: x25519, Key Exchange length: 32
    这时,客户端与服务器都获得了`Client Params 客户端公钥`和`Server Params 服务端公钥``Client Random客户端随机数`、`Server Random服务端随机数`。两边各自使用`ECDHE`生成`Pre-Master`,再生成`Master Secret`

六、HTTPS优化

  • 硬件优化:计算密集型
    • 更快的CPU
    • SSL加速卡
  • 软件优化
    • 升级Linux、Nginx、OpenSSL
  • 协议优化 TLS1.2>>TLS1.3
  • 证书优化
  • 会话复用:复用Master Secret 会话密钥
    • Session ID:各自保存一个会话的ID号,储存主密钥和其他相关信息。
    • Session Ticket:将加密后的Ticket发送给服务器。