万字HTTP学习笔记

*个人学习笔记,如有侵权,请立刻联系删除

计划做得多不如极客上路

老师背景:

罗剑锋(Chrono) 前奇虎360技术专家,Nginx/OpenResty开源项目贡献者

“To Be a HTTP Hero!”

一、破冰篇

01:HTTP前世今生

HTTP关键技术(蒂姆-伯纳斯-李):

  1. URI:统一资源标识符
  2. HTML:超文本标记语言
  3. HTTP:超文本传输协议

HTTP发展历程:

  1. HTTP/0.9
  2. HTTP/1.0(1996)
  3. HTTP/1.1(1999)
  4. HTTP/2(2015)
  5. HTTP/3(基于Google QUIC未来的发展方向)

02: HTTP是什么,不是什么

HTTP (HYPERText Transfer Protocol超文本传输协议) =  超文本 + 传输 + 协议

超文本:文本属于线性,超文本包括图片视频音频超链接等等,是非线性的网状结构关系

传输:搬运工,从A - > B 或者从A - > B - > C,HTTP是双向的

协议:一个或者多个的双方约定

HTTP是什么:

“HTTP 是一个在计算机世界里专门在两点之间传输文字、图片、音频、视频等超文本数据的约定和规范”。

HTTP不是什么:

HTTP不是互联网、不是编程语言、不是应用、HTTP更加不是一个孤立的协议。

在互联网世界里,HTTP 通常跑在 TCP/IP 协议栈之上,依靠 IP 协议实现寻址和路由、TCP 协议实现可靠数据传输、DNS 协议实现域名查找、SSL/TLS 协议实现安全通信。此外,还有一些协议依赖于 HTTP,例如 WebSocket、HTTPDNS 等。这些协议相互交织,构成了一个协议网,而 HTTP 则处于中心地位。

小结:

HTTP 是一个用在计算机世界里的协议,它确立了一种计算机之间交流通信的规范,以及相关的各种控制和错误处理方式。HTTP 专门用来在两点之间传输数据,不能用于广播、寻址或路由。HTTP 传输的是文字、图片、音频、视频等超文本数据。HTTP 是构建互联网的重要基础技术,它没有实体,依赖许多其他的技术来实现,但同时许多技术也都依赖于它。

03:与HTTP相关的各种概念

1:上集

万字HTTP学习笔记_第1张图片

浏览器(B): chrome

服务器(Web Server):Apache、...

CDN(Content Diliver xxx):内容分发网络

 2:下集

万字HTTP学习笔记_第2张图片

  • TCP/IP : IP(Internet Protocol)协议负责寻址,TCP(Transmission Control Protocol)协议负责通讯
  • DNS:域名系统(Domain Name System)用来做域名映射(“nginx.org” ===> 95.211.80.227),用点号分割,级别从左到右升高,最右为顶级域名。
  • URI(Uniform Resource Identify):统一资源标识符,URL(Uniform Resource Locator)统一资源定位符,是URI的子集,但是差异不大。
    • http://nginx.org/en/download.html
      
      协议名:即访问该资源应当使用的协议,在这里是“http”;
      主机名:即互联网上主机的标记,可以是域名或 IP 地址,在这里是“nginx.org”;
      路径:即资源在主机上的位置,使用“/”分隔多级目录,在这里是“/en/download.html”。
  • HTTPS(HTTP over SSL/TLS):SSL(Secure Socket Layer) =改名=> TLS(Transport Layer Security)
  • 代理(Proxy):常见的代理种类有
    • 匿名代理 - 外界只看到代理
    • 透明代理 - 顾名思义
    • 正向代理 - 靠近客户端,代表客户端向服务器发请求
    • 反向代理 - 靠近服务端,代表服务器响应客户端
  • 课后思考
    • Q:DNS 与 URI 有什么关系?
    • A:DNS 做域名映射找到对应的地址,URI由 协议名+ 主机名+ 路径,DNS通过主机名找到地址,URI访问到具体的路径
    • Q:在讲代理时我特意没有举例说明,你能够用引入一个“小强”的角色,通过打电话来比喻一下吗?
    • A: 正向代理:我用小明的电话打电话给小强。反向代理:我打给小明找到小强

04:“四层”、“七层”是什么

TCP/IP网络分层

万字HTTP学习笔记_第3张图片

  • 第一层:链接层(Link Layer),负责在以太网、WIFI这样得底层网络上发送原始数据包,MAC工作的地方
  • 第二层:网际层(Internet Layer),IP就在这里工作
  • 第三层:传输层(Transport Layer),保证数据“可靠”地传输。TCP、UDP就在这一层工作的,他们的区别是,TCP可靠、连续字节流、有先后顺序,UDP则是分散的数据包,顺序阀,乱序收,不保证一定到达
  • 第四层:应用层(Application Layer),Telnet、SSH、FTP、SMTP、HTTP就在这一层,MAC层传输单位是帧,IP层传输的是包,TCP传输单位是段,HTTP传输单位是消息或者报文

OSI网络分层模型

万字HTTP学习笔记_第4张图片

  • 第一层:物理层,网络的物理形式,例如电缆、光纤、网卡、集线器等等;
  • 第二层:数据链路层,它基本相当于 TCP/IP 的链接层;
  • 第三层:网络层,相当于 TCP/IP 里的网际层;
  • 第四层:传输层,相当于 TCP/IP 里的传输层;
  • 第五层:会话层,维护网络中的连接状态,即保持会话和同步;
  • 第六层:表示层,把数据转换为合适、可理解的语法和语义;
  • 第七层:应用层,面向具体的应用传输数据。

两个模型的映射关系

万字HTTP学习笔记_第5张图片

  • 第一层:物理层,TCP/IP 里无对应;

  • 第二层:数据链路层,对应 TCP/IP 的链接层;

  • 第三层:网络层,对应 TCP/IP 的网际层;

  • 第四层:传输层,对应 TCP/IP 的传输层;

  • 第五、六、七层:统一对应到 TCP/IP 的应用层。

小结:

  1. 七层大学的时候一般是这个样背..“物数网传会表应”。老师将整个网络层具象化到A寄快递给B。A发送的玩具(数据),A来看就是 (装玩具袋)应用层 ->(贴标签)传输层 -> (装上快递小哥的车)网际层 ->(装上通往B城市的大卡车) 连接层 -> B则反之,倒过来直到最后拆出玩具(数据)。 这样的举例加深了我对整个网络模型的印象与理解。
  2. 关于传输层TCP、UDP看了网友的例子,也是很好理解 。TCP属于顺丰,快递必须送到你的手里才行,UDP就想别家快递员,不在家就扔你门口(快递员看到别打我)

课下思考

  • 你能用自己的话解释一下“二层转发”“三层路由”吗?
    • 四层模型中,二层表示网际层路由,三层表示传输层做不了路由,肯定是不符合题意
    • 七层模型中,二层表示数据链路层,三层是网络层。数据链路层表示通过MAC地址来转发,网络层则是通过IP进行路由
  • 你认为上一讲中的 DNS 协议位于哪一层呢?
    • DNS属于代理,只是做域名映射,所以是应用层。
  • 你认为 CDN 工作在那一层呢?
    • CDN也是代理,做内容分发,也在应用层

05:域名里面的门道

域名的形式

“time.geekbang.org”

time:主机名,www(万维网服务)、mail(邮件服务)
geekbang:二级域名
org:顶级域名

域名的和解析

万字HTTP学习笔记_第6张图片

  1. 根域名服务器:返回“com”、“org”、"cn"等顶级域名服务器的IP地址
  2. 顶级域名服务器:返回apple.com各自域名下的权威域名服务器
  3. 权威域名服务器:返回www.apple.com的ip地址

例如要访问“www.apple.com”:

  1. 访问跟根域名服务器告诉你com对应的顶级域名服务器地址
  2. 访问顶级域名服务器的地址返回apple.com对应的权威域名服务器地址
  3. 访问权威域名服务器地址返回www.apple.com的地址

注意:

当全世界的网民都在上网的时候,如果不采取别的手段,也会瘫痪:

  1. 一个是大公司、网络运营商用的代理DNS,简称非权威域名服务器,可以缓存之前查询的结果。
  2. 操作系统对访问过的DNS解析结果做缓存
  3. 主机映射 Linux在“/etc/hosts ”而Windows在“C:\WINDOWS\system32\drivers\etc\hosts”中配置,操作系统找不到DNS记录,会在这里找

域名的“新玩法”

  • 重定向,用新IP地址的机器顶替旧服务,域名不变,对外访问也不变,无感替换
  • 内部DNS,用域名来标记内部服务,无需写死IP
  • 负载均衡,一个是返回多个IP地址,用于前端在判断(之前公司用过ping)那个连接好用哪个访问。二是通过内部策略,直接给客户端分配最近的主机。

课后思考

Q1:在浏览器地址栏里随便输入一个不存在的域名,比如就叫“www. 不存在.com”,试着解释一下它的 DNS 解析过程。

A: 前面提过,域名解析的过程是“自顶向下”,并且本地计算机、附近的DNS也会做缓存。所以解析过程是(发起访问"www.不存在.com" --> 操作系统找缓存 --> hosts文件映射 --> 内部DNS缓存(如果有) --> 网络运营商DNS缓存(非核心?) --> 根域名服务器 --> 顶级域名服务器(有继续,没有就返回) --> 权威域名服务器(同理) )

Q2:如果因为某些原因,DNS 失效或者出错了,会出现什么后果?

A:由A1得知,这个问题需要分析,本地是否由缓存,如果有,则无需转发至DNS,如果没有,返回错误

评论区补充发现:

  1. 查找是基于UDP协议查找的
  2. ISP(Internet Service Provider)网络服务提供商、DHCP(Dynamic Host Configuration Protocol)动态主机配置协议
  3. 返回多个DNS,我发现有“8.8.8.8”和“114.114.114” windows 使用“ipconfig /all”
  4. A1上面少了一层浏览器缓存

06: 自己动手,搭建HTTP实验环境

“最小化”环境用到的应用软件:

Wireshark

Chrome/Firefox

Telnet

OpenResty

以下是部署的问题:
1、http_study已解压,openresty也在http_study目录下,http_study也在openresty下,但在http_study\www\start运行后提示windows找不到文件..\openresty\nginx
A: 问题本质,就是在运行自己写的Windows批脚本不要用管理员身份运行,运行路径会变为C:\System32,此时../openXXX就找不到了,如果非要,notepad改start改绝对路径。
2、Nginx 错误10013: An attempt was made to access a socket in a way forbidden by its access permissions
A: 1:netstat -aon | findstr :80 or 443(https)//找到端口占用情况 tasklist|findstr "进程号" //占用端口服务 ,任务管理器关掉服务

二、基础篇

01| 一次浏览器的访问流程

访问IP www.127.0.0.1/

万字HTTP学习笔记_第7张图片

访问域名 http://www.chrono.com

万字HTTP学习笔记_第8张图片

先讲两个访问方法的相同点:

1、浏览器通过URI、端口号,和Web服务器建立TCP连接,当然要三次握手,HTTP就可以干活了

2、然后Browser发送一条HTTP/1.1协议

3、然后回WebServer会返回一个HTTP/1.1 200 OK

4、浏览器ACK WebServer走的是UDP协议(这里没抓)

5、Browser解析HTML文件

区别:

1、通过域名访问的,需要访问一遍自己的缓存 + hots文件,最后才去DNS取

02| HTTP报文拆解

| 组成HTTP报文的结构分为三大类:

  • 起始行(start line):描述报文的基本信息
  • 头部字段集合(header):key-value形式 ,里面有许多报文的信息
  • 消息正文(body):实际传输的东西,不一定是文本,可能是图片音频等二进制
  • HTTP协议中,必须要有header,可以没有body,并且header之后必须有“空行”,就是“CRLF”,十六进制为“0D0A”

来看看实际报文结构:

万字HTTP学习笔记_第9张图片

抽象后的报文:

 万字HTTP学习笔记_第10张图片

| 报文又分为以下两种:

        HTTP报文又分为两种,一中是请求报文,一种是响应报文。他们有相同的地方,也有不同的地方。

相同点:

1、都有起始行、头部字段,都是CRLF表示结束。

抽象图如下:

万字HTTP学习笔记_第11张图片

以上值得注意的是:

  1. 字段不分大小写,但是最好用首字母大写;
  2. 字段不允许出现空格,但是可以出现“-”,不能用下划线;
  3. 字段名后面必须紧跟着”:”不能有空格,“:”后面可以用多个空格;
  4. 没有顺序可言
  5. 字段原则上不允许有重复,除非特殊,例如Set-Cookie

不同之处:

1、请求报文的起始行叫请求行,响应报文的起始行叫状态行,两者抽象结构如下:

万字HTTP学习笔记_第12张图片

实际报文结构:

 万字HTTP学习笔记_第13张图片

 2、虽然说都有头部字段,但是有些字段是只能在请求报文,有些字段只能在响应报文里面,如下:

  1. 通用字段:在请求头和响应头里都可以出现
  2. 请求字段:顾名思义
  3. 响应字段:顾名思义,补充响应信息
  4. 实体字段:属于通用,但是描述的事body

基本头字段表格

Host 只会出现在请求字段,用于区分多个域名指向同一个IP的情况 User-Agent 只能出现在请求头里面,用于限时当前浏览器的信息 Date 只会出现在响应头中,表示HTTP报文创建时间 Server 只能出现在响应头,表示当前服务的Web服务信息 Content-Length 表示body的长度

 | 课后思考:

Q1、如果拼 HTTP 报文的时候,在头字段后多加了一个 CRLF,导致出现了一个空行,会发生什么?

A1: 刚开始以为是会忽略,但是评论区中说是只会吧CRLF当做body,老师也认同了。

Q2、讲头字段时说“:”后的空格可以有多个,那为什么绝大多数情况下都只使用一个空格呢?

A2:省流量,多一个占位符,多一个字节

03| 请求方法的种类剖析

 | 关于HTTP请求的介绍

  1. GET:获取资源,读取下载数据
  2. HEAD:获取资源元信息
  3. POST:向资源提交数据,相当于写入上传数据
  4. PUT:类似POST
  5. DELETE:删除
  6. CONNECT:建立特殊的连接隧道
  7. OPTIONS:列出可对资源实行的方法
  8. TRACE:追踪请求

 万字HTTP学习笔记_第14张图片

| HTTP关于安全与幂等

安全:指请求的方法是否会破坏服务器的资源,例如GET、HEAD是安全的,DELETE、POST、PUT是不安全的。

幂等:意思值多次执行相同的操作,结果都是相同的。

| 课后思考

Q1:你能把 GET/POST 等请求方法对应到数据库的“增删改查”操作吗?请求头应该如何设计呢?

A1:GET = SELECT,POST = INSERT OR UPDATE,这些行为都是谓语,其他是宾语 + 状语,数据库查询是查找什么东西,在哪里,有什么条件,比如HTTP GET方法就是访问谁,获取什么东西、有什么条件,一一对上即可。

Q2:你觉得 TRACE/OPTIONS/CONNECT 方法能够用 GET 或 POST 间接实现吗?

A2:

TRACE:用GET、POST实现,约定好URL或者data_field标记就好

OPTIONS:用GET、POST实现,约定好URL比约定key省事

CONNECT:用GET、POST实现,约定好URI,每次收到这个key或者URI的请求就转发(猜想)

评论区得知:

1、前端跨域请求常常用到OPTION 所有人都应该知道的跨域及CORS - 知乎

04|  搞懂URI

|>  URI的基本格式

万字HTTP学习笔记_第15张图片

 scheme:使用什么协议请求,如http、https、ftp、file、ldap、news

:// : 特定字符,必填但是就是做分隔,没别的用途

authority(hosts + port + path):host = 主机名(可以是ip地址)、port = 端口(不填默认端口80,https默认端口443)、path = 标记资源所在位置,用"/"开始,"/"分隔,

query: 参数

do some example:

http://nginx.org
http://www.chrono.com:8080/111
https://tools.ietf.org/html/rfc7230
file:///D:/http_study/www/

1、使用http协议访问,主机名是ngsinx.org,使用http默认端口80

2、使用http协议访问,主机名是www.chrono.com,端口号用8080,path是"/111"

3、使用https协议访问,主机名是tools.ietf.org,端口号443,path是“/html/rfc7230”

4、使用file协议访问,没有host,默认localhost,path是“/D:/http_study/www/”

|>  在浏览器中观察一次URI

万字HTTP学习笔记_第16张图片

GET方法后紧跟着path,因为Host字段就有有主机名了,就没必要再拼一次,由此得知客户端与服务端看的的URI是不一样的,客服端因为要查找,所以需要URI的完整信息,服务端看到的是报文,被删除协议名和主机名的URI

|> URI的查询参数

        URI的查询参数,用“?”开始,但是不包括问号,用“key = value”的格式,用“&”来连接,一下是使用“http://www.chrono.com:8080/11-1?uid=1234&name=mario&referer=xxx”访问,看看Chrome中解析的URL:

万字HTTP学习笔记_第17张图片

|> URI的完整格式

万字HTTP学习笔记_第18张图片

与基本格式相比,多了以下两个部分:

1、`user:passwd@`,表示登录主机时的用户名和密码,由于把账密暴露出来,现在不用这种格式

2、`#fragment`,片段标识符,浏览器可以在获取资源后跳转到她指示的位置,服务器看不到。

|> URI的编码

        在URI使用英语以外的语言,URI引用了编码机制,可以将ASCII码以外的字符和特殊字符做一个特殊的操作,既把它们转换与URI语义不冲突的形式,俗称“转义”,转义规则是直接转换为十六进制,在前面加个“%”。

看看浏览器是怎么做的:

copy浏览器的地址或者F12看看他的原型:

 万字HTTP学习笔记_第19张图片

|> 课后思考

Q1:HTTP 协议允许在在请求行里使用完整的 URI,但为什么浏览器没有这么做呢?

A1:意义是一样的,整个请求都可以拿到完整的URI。

Q2:URI 的查询参数和头字段很相似,都是 key-value 形式,都可以任意自定义,那么它们在使用时该如何区别呢?

A2:先讲相同的,都是KV结构。再将不同的,第一、最明显的区别,查询参数,是跟整个URL一起出现的,而header如果不打开开发者模式,或者不抓包都看不到带了什么参数。第二、规则不同,头部字段不允许下划线、空格,查询字段key可以。补充:评论区老师答复“query参数针对的是资源(uri),而字段针对的是本次请求,也就是报文。一个是长期、稳定的,一个是短期、临时的。”

05| 响应状态码

        RFC标准把状态码分成了五类,用数字的第一位来表示,0~99不适用。

|>  状态码的种类

  • 1XX:提示信息
  • 2XX:成功,被正确处理
  • 3XX:重定向,资源位置发生变动,需要客户端重新发送请求
  • 4XX:客户端错误,请求报文错误
  • 5XX:服务端错误, 服务器内部错误

万字HTTP学习笔记_第20张图片

|>  开发中比较有价值的状态码详解:

  • 1XX,偶尔能见到的是"101 Switching Protocols"。表示客户端使用Update头字段,要求在HTTP协议的基础上改成其他协议继续通信,比如WebSocket。如果Server同意,就会发101状态码。
  • 2XX,表示成功
    • “200 OK”:”表示一切正常,服务器如客户端期望返回结果。
    • “204 No Content”:与“200 OK”一致,但是没有body数据。
    • “206 Partial Content”: 是HTTP分块下载或者断点续传基础,与200一样,但是Body不是全部数据,还会带Content-Range。
  • 3XX,表示重定向
    • “301 Moved Permanently”:表示永久性重定向。
    • “302 Found” :表示临时重定向。
      • 301和302都会在头部字段Location指明需要跳转的URI,比如网站升级到HTTPS,一以前的HTTP不实用了,就是永久的更换。如果是临时的维护需要跳转到静态页面,那就是302。
    • “304 Not Modified”:表示缓存重定向
  • 4XX,表示客户端发送的报文有错误
    • “400 Bad Request”:通用的错误,这是一个笼统的错误,并不知道是什么错误。
    • “403 Forbidden”:实际上不是客户端的错误,表示服务器禁止访问资源。
    • “404 Not Found”:表示资源在服务器找不到,无法返回结果。
    • “405 Method Not Allowed”:不允许使用某些方法操作资源,例如不允许POST只能GET。
    • “406 Not Acceptable”:资源无法满足客户端请求,请求中文只有英文。
    • “408 Request Timeout”:请求超时,服务器等待了过长时间。
    • “409 ConFlict”:多个请求冲突,多线程竞态。
    • “413 Request Entity Too Large”:请求报文里面的Body太大。
    • “414 Request-URI Too Long”:请求行的URI太大。
    • “429 Too Many Requests”:客户端请求太多。
    • “431 Request Header Fidelis Too Large”:请求头某个字段或者数量太大。
  • 5XX,表示客户端请求报文正确,但是服务器处理时出错。
    • “500 Internal Sever Error”:通用错误码,只告诉前端服务器出错了。
    • “501 Not Implemented”:表示客户端请求的功能 没有支持。
    • “502 Bad GateWay”:网关或者代理返回的错误。
    • “503 Service Unavailable”:表示服务器很忙, 暂时无法响应服务,同时带有一个“Retry-After”字段,表示可以后面再尝试。

|>  课后思考:

Q1:你在开发 HTTP 客户端,收到了一个非标准的状态码,比如 4××、5××,应当如何应对呢?

A1: 首先我会按照4、5先定义一个default的错误提示信息,4开头前端错了,就未知错误,5开头服务器错的,就服务器错误后面再试。

Q2:你在开发 HTTP 服务器,处理请求时发现报文里缺了一个必需的 query 参数,应该如何告知客户端错误原因呢?

A2:首先,报文错误,肯定是客户端的错误,所以是4开头的,具体错误信息,在body里面带上就好了吧,前端处理。

评论区收获:

1、约定body带json返回例如 {"code":-1,"message:"userid参数必须填写"}。

2、错误也可以是返回200,在body返回

06| HTTP协议的特点

|>  灵活拓展

        Body不限制与文本格式得TXT或者HTML, 可以是图片、音频、视频等等....

|>  可靠传输

        前面几章都讲到,浏览器访问一个网址是先经过TCP握手连接得,TCP本身就是以一个"可靠"的连接,但是不是100%数据一定能够发送到另一端,在网络繁忙的环境下,也有可能会收发失败。

|>  应用层协议

        应用层协议有很多种,FTP、SMTP、SSH等等,他们的功能都是单一的,而HTTP几乎可以传递一切东西,满足各种需求。

|>  请求应答

        通俗来讲就是"一收一发",契合传统的C\S系统架构,用轻量级的浏览器代替笨重的客户端,实现0维护瘦客户端。此外这种模式也很好的再RPC的工作模式下运作。

|>  无状态

        TCP连接时会在双端各自维护一个状态类似,CLOSED、ESTABLISHED,形象的来讲,无状态就是没有记忆力,只要请求合法,都会返回一样的东西。对比UDP的无连接无状态,HTTP是有连接无状态,顺序发包顺序收包,按照收发顺序管理报文。

|>  其他

        可压缩、分段获取数据、支持身份验证、支持国际化语言。

|>  课后思考

Q1:就如同开头我讲的那样,你能说一下今天列出的这些 HTTP 的特点中哪些是优点,哪些是缺点吗?
A1:刚开始以为拓展性高、可靠传输、无状态是优点。但是凡事都有正反面,因为你机制加多了,有可能就不灵活、效率不高,有时候机制少了,在某些场景下又可能不安全不可靠不稳定,所以没有绝得的优缺点,所以我个人认位灵活拓展那是它最大的优点了,只要大家都按照RPC来规范约束,可以愉快的写出轻便简洁的代码。

Q2:不同的应用场合有不同的侧重方面,你觉得哪个特点对你来说是最重要的呢?

A2:能够在上层实现的那些机制,都不算比较重要的,而是要找那种为什么是使我加上这种机制就能满足的基础,那才是最重要的,所以我绝得是灵活性

07| HTTP协议的优缺点(只针对HTTP/1)

|>  优点

  • 简单、灵活、便于扩展
    • 基本报文格式就是header + body
    • URI、状态码、原因短音,头字段每一个核心要素都没有写死的
    • 不限制下层协议,不仅可以对TCP、UNIX Domain Socket、还能用SSH\TLS,或者基于UDP的QUIC
  • 应用广泛、环境成熟
    • 市场上使用HTTP的地方很多
    • 开发领域对于HTTP的支持

|>  优缺点

  • 无状态
    • 容易做集群,负载均衡把请求转发到任意一台服务器
    • 无法支持需要多个步骤的事务,比如电商平台购物,需要一系列操作(Cookie解决)
  • 明文
    • 可以用肉眼观察,利于开发调试
    • 不使用二进制文件,暴露信息
    • 不安全,身份认证做不到,报文可以被篡改(HTTPS解决)
  • 性能,不算差不算好
    • TCP/IP ,现在互联网的特点是移动和高并发
    • 应答模式,“对头阻塞”问题(解决方案HTTP2、HTTP3)

|>  课后思考

Q1:你最喜欢的 HTTP 优点是哪个?最不喜欢的缺点又是哪个?为什么?

Q2:你能够再进一步扩展或补充论述今天提到这些优点或缺点吗?

Q3:你能试着针对这些缺点提出一些自己的解决方案吗?

三、进阶篇

01| HTTP的实体数据

|> MIME(Multipupose Internet Main Extensions)

1、text:即文本,超文本 text/html,纯文本text/plain,样式表text/css

2、image:即图像文件,有image/gif 、 image\jpeg 、 image\png等

3、audio/video:音频和视频数据,例如audio/mpeg 、 video/mp4

4、application:数据格式不固定,可能是文本也可能是二进制,由上层来解析。常见的application/json、application/javascript、application/pdf、application/octet-stream

此外,有了数据类型,还不够,HTTP在传输的时候为了节约带宽,会进行压缩。所以还要告诉对方用什么类型的编码格式。用的"Encoding type"约定,常见的有:

1、gzip:GNU zip 压缩格式,也就是互联网上最流行的压缩格式

2、deflate:zlib(deflate)压缩格式,流行度仅次于gzip

3、br:一种专门为HTTP优化的新压缩算法

|> 数据类型使用的头字段

        为了更好的客户端与服务端的“内容协商”,HTTP还定义了Accept请求头字段和Content实头字段。客户端用Accept告诉服务器想接受什么数据,而服务器用Content头告诉客户端实际发了什么数据。比如我们请求CSDN的官网

请求头:

万字HTTP学习笔记_第21张图片

响应头: 

 由图可知,每个类型可以用“,”来分割,此外,还有一个Accept-Encoding字段标记客户端支持的压缩格式。响应头则放在Content-Encoding里面。

|> 语言类型与编码

        不同国家不同地区的人使用了很多不同的语言,HTTP为了解决这个问题,会在请求头带上“Accept-language”用于表示浏览器期望接收到什么国家地区的语言,并且除了语言种类,还可以支持到地区性的方言,以“type-subtype”的格式来表示。例如还是CSDN的官网,期望接收到汉语。当然了,我们也可以用UTF8、GBK等编码格式

|> 内容协商的质量值

        在用那个Accept、Accept-Encoding、Accept-language的时候,还有用到一个特殊的参数“q”来表示权重。权重值UI大是1,最小是0.01,默认是1, 如果是0则表示拒绝,具体的形式如上图,“;” + "q= value"

|> 内容协商的结果

        由于每个Web服务器使用的算法都不一样,所以要用一个字段来标记服务器在内容协商时参考的请求头字段,这个字段叫做“Vary”。

        如图访问CDSN的网站返回的vary是 Accept-Encoding,意思就是依据这个字段来决定返回的响应报文。同一个URI可能又多个“版本”,主要用于传输链路中代理服务器实现缓存。 

|> 动手实验

json文件的请求响应头

万字HTTP学习笔记_第22张图片

 mp4文件的请求响应头

万字HTTP学习笔记_第23张图片

  txt文件的请求响应头

万字HTTP学习笔记_第24张图片

   webp文件的请求响应头

万字HTTP学习笔记_第25张图片

 xml文件请求响应头

万字HTTP学习笔记_第26张图片

万字HTTP学习笔记_第27张图片

|> 课后思考

Q1、试着解释一下这个请求头“Accept-Encoding: gzip, deflate;q=1.0, *;q=0.5, br;q=0”,再模拟一下服务器的响应头。

A1:请求头哦表示的意思是,gzip = 权重1 ,deflate 权重也是1,其他所有的权重0.5, br这种压缩方式不合适。服务器响应头是,Content-Type + Content-Encoding = gzip\deflate\other , Content-Language,Vary:Accept-Encoding

Q2、假设你要使用 POST 方法向服务器提交一些 JSON 格式的数据,里面包含有中文,请求头应该是什么样子的呢?

A2:这题没想出来,看了评论区发现是在请求头带上一个Content-Type:application/json

发现原阿里Content-Type是实体字段,所以在请求也能带

Q3、试着用快递发货收货比喻一下   MIME、Encoding 等概念。

A3:

02| HTTP传输大文件

        传输大文件的解决方案,把大文件变小,把大文件拆开变小。

|> 数据压缩

        前面实体数据讲到,客户端发起请求头会带上一个Accept-Encoding字段,用于表示浏览器支持的报文压缩算法,服务器回复的Content-Encoding表示用了什么压缩方法,例如gzip,deflate,bar等来压缩。

        如果压缩率有50%,相当于带宽不变的前提下,提升了一倍熟度。但是gzip压缩方法有压缩缺陷,之恶能对文本文件有较好的压缩率,图片、视频、音频本身就是高度压缩,有可能经过gzip后负负得正,报文还大了。

|> 分块传输

        前面说了还可以把大文件拆散,在”Transfer-Encoding:chunked“来表示,意思是报文里的body部分,不是一次性发来的,而是被分成了许多快逐个发送。“Transfer-Encoding:chunked”与“Content-Length”这两个字段是互斥的,两个字段不能同时出现,长度要么已知,要么未知。

下面来剖析一下协议:

万字HTTP学习笔记_第28张图片

万字HTTP学习笔记_第29张图片

(PS:由于电脑的Telnet Server问题没法用Telnet看到报文)

|> 范围请求

        HTTP中的范围请求可以让我们平时在日常看电影刷剧的过程中,一下跳到片头,一下跳到片尾。服务端必须在响应头使用字段“Accept-Ranges:bytes”,请求头中使用“Range”字段来表示,

客户端发起范围查询:

格式是,“bytes=x-y”, 范围从0开始计数,类似数组下标,比如文件100个字节,要获取前10个字节 "bytes = 0-9", 这里的格式跟Go语言中的切片有点像”bytes 10- “ 表示从第10个字节拿到最后一个,”bytes =  -1“ 则表示获取最后一个字节。

服务端收到范围查询:

1、检查范围,错误返回416

2、获取偏移量数据,返回216

3、添加一个响应头 “Content - Range”,格式是“bytes x-y/length” ,这里会返回总长度

|> 分段传输

        除了范围请求,HTTP还支持一次性获取多个片段数据。需要使用MIME类型:“multipart/bytesranges”表示报文是由多节字段序列组成的,还用加上一个“boundary = xxx”给出的段分割标记。

万字HTTP学习笔记_第30张图片


|>  课后思考

Q1、分块传输数据的时候,如果数据里含有回车换行(\r\n)是否会影响分块的处理呢?

A1:不会,因为每个分段里面都有指定长度

Q2、如果对一个被 gzip 的文件执行范围请求,比如“Range: bytes=10-19”,那么这个范围是应用于原文件还是压缩后的文件呢?

A2:看源文件是什么形式, 如果源文件是gzip则没问题,如果是一个普通的tx,那就是txt的数据。

03| HTTP连接管理

|>  短、长连接

        短连接:发完HTTP协议就关闭TCP连接

        长连接:保持TCP连接,要关的时候才关

|>  连接相关的字段

        请求头里可以明确的指出要求使用长连接机制,使用字段是“Connection”,值为“keep-alive”。当然长连接也有他的弊端,由于需要一直保持长连接,所以有些连接会是浪费的,比如一直占用连接但是不发数据,数量多了会耗尽服务器的资源,一般会采取超时关闭,或者限量关闭的手段来解决。

|>  队头阻塞

     

万字HTTP学习笔记_第31张图片

|>  性能优化

并发连接:

        一个客户端申请多个连接

域名分片:

        做域名拆分,增大连接数

|>  课后思考

Q1、在开发基于 HTTP 协议的客户端时应该如何选择使用的连接模式呢?短连接还是长连接?

A1:里面的业务用长连接,大大减少连接开销。登录可以用短连接。

Q2、应当如何降低长连接对服务器的负面影响呢?

A2:1、限时

        2、限流量

        3、Linux配置半握手连接数

04| HTTP的重定向和跳转

  • 主动跳转:浏览器主动发起的
  • 重定向(被动跳转):服务器发起

|>重定向的过程

  • 状态码,301、302、3xx
  • 一次重定向 = 两次请求
  • 请求响应多了一个Location字段
    • Location字段属于响应字段,必须出现在响应报文里面,而且是要配合301、302、3xx状态码才有意义,他标记了服务器要求重定向的URI
    • 允许使用绝对URI、相对URI,如果是站内跳转可以放心使用相对URI,但是站外跳转必须使用绝对URI

|>重定向的状态码

  • 301:永久性重定向,意思是原本的URI失效了
  • 302:临时重定向,意思是URI处于临时维护的状态
  • 303:类似302,但是要求重定向后改为GET请求访问,避免POST、PUT重复操作
  • 307:类似302,但是要求重定向后的方法和实体都不允许改变
  • 308:类似307,但是是301永久重定向的含义
  • 注意:303-308接收成都较低,要看看浏览器版本支持与否

|>重定向的应用场景

  • 重定向
    • 资源不可用,必须域名变更、服务器变更、系统维护等等
    • 避免重复,多个URI都跳入同一入口,会增加访问入口的同时,还不会增加额外的工作量
  • 永久/临时
    • 服务器换了新机房、网站目录层次重构等等,属于永久性的
    • 某个时间段内服务维护,还有就是服务降级,关闭某些入口

|>重定向的相关问题

  1. 问题一:性能损耗
    1. 大量的跳转对服务器的影响也是不可忽视的,站内重定向还好,可以用长连接,如果是站外跳转的话,网络情况差的情况下,用户体验会受影响
  2. 问题二:循环跳转
    1. 避免出现 “A => B =>C => A”这种链路,不停地在里面转圈圈,当然,浏览器必须有检测循环跳转这种能力,会报一个错误提示

05| HTTP的Cookie

|>Cookie的工作过程

响应头字段:Set-Cookie,可以设置多个,用“;”隔开(例子:Set-Cookie:a=xxx  \n Set-Cookie:b=xxx)

请求头字段:Cookie(例子:Cookie:a=xxx;b=yyy)

|>Cookie的属性

  • 生命周期 - 用Expires和Max-Age两个属性来设置
    • Expires:过期时间,绝对的时间点
    • Max-Age:相对时间,单位是秒
    • Expire和Max-Age是可以同时出现的,优先使用Max-Age来计算失效
    • eg.
      Set-Cookie:a = xxx;Max-age = 30;Expires = Fri,07...

  • Cookie的作用域 - 让浏览器仅发送给特定的服务器和URI
    • Domain、Path:浏览器会在发送Cookie前从URI中提取出host和Path部分,对比Cookie的属性。如果不满足就不会发
  • Cookie的安全性 - 用document.cookie可以读写Cookie数据,有安全隐患
    • HttpOnly:告诉浏览器,这个Cookie只能在Http里面传输,禁止一切API
    • SameSite:可以防范“跨站请求伪造”设置成“SameSite = Strict”/“SameSite = Lax
    • Secure:表示这个Cookie用Https加密传输,明文的Http协议会禁止发送,Cookie还是以明文的形式
  • 开发者工具看Cookie

万字HTTP学习笔记_第32张图片

|> Cookie的应用

  • 身份识别:用账号和密码登录某电商,电商会给你打一个身份标签
  • 广告跟踪:如果点开某些广告图片,也会给浏览器打标签,平台做数据分析,这种Cookie不是由访问的主站储存的,又叫第三方Cookie

|> 小结

  1. Cookie是服务端发到浏览器的一种临时存储手段
  2. 响应报文用Set-Cookie字段发送
  3. 请求用Cookie字段发送
  4. 为了保护Cookie,要给他设置过期时间,作用域
  5. Cookie最基本的使用用途是身份识别

|> 课后思考

1、如果 Cookie 的 Max-Age 属性设置为 0,会有什么效果呢?

答:Cookie失效

2、Cookie 的好处已经很清楚了,你觉得它有什么缺点呢?

答:由于是明文的存在,如果服务端没有做好一些加密、混淆等操作,而是直接用某些字符串给用户打标签,极其容易泄露用户的行为模型。

补充:

1、数量和大小限制,Cookie太大也不好,传输数据会大

2、客户端可能不保存Cookie,比如telnet收发数据,用户禁用浏览器保存Cookie的情况

06| HTTP的缓存控制

|> 服务器的缓存控制

  • 服务器标记资源有效期的字段是:Cache-Control,里面用max-age,跟cookie过期时间一样
  • max-age是生存时间,类似TTL,时间的计算起点是,响应报文的创建时间,不是浏览器收到报文的时间
  • 此外还有别的属性来控制浏览器使用缓存
    • no-store:不允许缓存,用于变化非常频繁的数据,类似秒杀
    • no-cache:可以缓存,使用之前要先去服务器比较
    • must-revalidate: 缓存不过期,就可以继续使用,过期了要去找服务器比较
  • 图解服务端的缓存控制

万字HTTP学习笔记_第33张图片

|> 客户端的缓存控制

  • 浏览器也可以在请求报文中加Cache-Control:max-age = 0,意思为获取最新的资源
  • Ctrl + F5 强制刷新发的事 Cache-Control:no-cache,意思和上面一样
  • 浏览器按后退,用本地的cache,即“from disk cache”

|> 条件请求

HTTP定义了以If开头的条件请求字段,第一次服务器返回的报文中需要带上Last-Modified、Etag,然后浏览器请求的时候就可以带上缓存的值去比较。

  • if-Modified-Since:是否是某时间之前的资源
  • if-None-Match:如果比较不成功
  • Last-Modified:资源最后修改时间
  • Etag:唯一标识,强Etag要求字节级别完全相同,弱Etag则是语义上无变化
  • 如果资源没有变化,服务器会返回一个“304 Not Modified”,表示缓存有效,浏览器更新一下有效期,继续用缓存

|> 小结

  1. HTTP每个环节都可以有缓存
  2. 服务器用“Cache-Control”设置缓存策略
  3. 浏览器收到数据就会缓存,只要不过期就可以用
  4. 验证资源用条件请求,收到304就可以复用
  5. 服务器在响应时先预先发送“Last-modified”和“,“ETag”
  6. 浏览器也可以发“Cache-Control”,使用“max-age=0”或“no_cache”刷新数据

课下思考:

1、Cache 和 Cookie 都是服务器发给客户端并存储的数据,你能比较一下两者的异同吗?

答:Cache意思为资源保存,Cookie为标记主要是保存简要信息

2、即使有“Last-modified”和“ETag”,强制刷新(Ctrl+F5)也能够从服务器获取最新数据(返回 200 而不是 304),请你在实验环境里试一下,观察请求头和响应头,解释原因。

补充:强制刷新是因为请求头里面没有了条件请求的字段,所以服务器无法判断是否过期之类的,只能返回资源

07| HTTP的代理服务

|> 代理服务

在原本HTTP与服务器连接的过程中,中间多加一个节点,称之为代理服务器,代理服务器不产生内容,做转发用,转发上下游的请求和请求

|>代理的作用

  • 对上屏蔽真是客户端,对下屏蔽了真是服务器,灵活使用HTTP协议
  • 负载均衡,客户端不知道有多少台服务器,IP地址也不知道,代理服务器来决定由哪台服务器来响应请求,同事也可以执行更多的功能
    • 健康检查:使用心跳机制监控后端服务器
    • 安全防护:保护被代理后的后端服务器,限制IP、流量
    • 加密卸载:对往外使用SSL、TLS加密验证,在内网不验证
    • 数据过滤:拦截上下行数据,指定策略
    • 内容缓存::暂存、复用服务器响应

|> 代理相关头字段

  • 代理服务器需要用字段“Via”标明代理的身份
    • eg. 请求via:proxy1,proxy2,响应via:proxy2,proxy1
  • “X-Forwarded-For”:追求请求方的IP
  • “X-Real-IP”:记录客户端的IP地址,不记录中间节点
  • “X-Forwarded-Host”:记录客户端原始域名
  • “X-Forwarded-Proto”:记录客户端原始协议

|> 代理协议

“X-Forwarded-For”由于在Http报文内,服务端每次获取源IP时还需要拆解协议,降低了性能,所以就出现了一个叫代理协议的标准。直接在HTTP报文前面多加一行ASCII码文本头,格式是 

PROXY TCP4 1.1.1.1 2.2.2.2 55555 80\r\n

GET / HTTP/1.1\r\n

Host: www.xxx.com\r\n

\r\n

|> 小结:

  1. 代理服务器,意为在客户端和服务端中间,多加N个节点,用于转发
  2. 代理服务器使得HTTP协议更加灵活,包括实现负载均衡、安全防护、数据过滤等等
  3. 代理服务器用Via标注请求经过的链路,并且返回的时候也是原路返回
  4. 要知道真实的客户端ip,用X-fastforward-For和X-Real-IP
  5. 代理协议可以在不修改原始HTTP的情况下传递客户端的真实IP

|> 课后思考:

1、你觉得代理有什么缺点?实际应用时如何避免?

补充:

1、优点是匿名,多级代理还有做缓存的用途

2、 作为中转站,需要为上游和下游开启两个连接,大量并发请求,会出现性能瓶颈,应减少资源开销,加快响应速度,比如代理缓存,动静分离

2、你知道多少反向代理中使用的负载均衡算法?它们有什么优缺点?

答:轮询,哈希,一致性哈希

补充:

1、随机——简单,是否均匀看随机情况
2、轮询(一般轮询、加权轮询)——相对简单,也会考虑机器资源和性能的均衡性
3、哈希(一般哈希、一致性哈希、带虚拟节点的一致性哈希)——相对复杂,要求越公平就会越复杂,而且适当考虑了请求

4、最少连接数、最快连接数

08| HTTP的缓存代理

|>缓存代理服务

  • 代理服务收到源服务器发来的响应数据后需要做两件事。第一个当然是把报文转发给客户端,而第二个就是把报文存入自己的 Cache 里。
  • “既是客户端,又是服务器”,同时也“既不是客户端,又不是服务器”,可以是用Cache-Control属性

|>源服务器的缓存控制

  • 新属性,用于区分在客户端上的缓存和代理上的缓存,可以使用两个新属性private和public。private表示是用户私有的,不用做缓存共享,public则反义。
  • must-revalidate 和proxy-revalidate的区别,是一个需要回服务器验证,而另外一个只要求缓存过期后必须验证
  • s-maxage用于代理缓存的生存时间
  • no-transform用于禁止代理服务器对数据做一些操作修改之类的
  • 下面的流程图是完整的服务器端缓存控制策略,可以同时控制客户端和代理

万字HTTP学习笔记_第34张图片

|>客户端的缓存控制

万字HTTP学习笔记_第35张图片

  • 多了两个新属性“max-stale”和“min-fresh”
    • “max-stale”的意思是如果代理上的缓存过期了也可以接受,但不能过期太多,超过 x 秒也会不要。
    • “min-fresh”的意思是缓存必须有效,而且必须在 x 秒后依然有效。
  • 有的时候客户端还会发出一个特别的“only-if-cached”属性,表示只接受代理缓存的数据,不接受源服务器的响应。如果代理上没有缓存或者缓存过期,就应该给客户端返回一个 504(Gateway Timeout)。

|>其他问题

  • Vary:内容协商的结果,代理服务器根据这些不同的东西,返回不同的缓存版本
  • Purge:缓存清理
    • 过期的数据要淘汰,避免浪费空间
    • 资源有更新,需要删除旧版本
    • 储存了不应该存的东西

|> 小结

评论总结:

浏览器拿到一个网址的时候,先判断是否允许缓存,允许会先查看本地缓存:1.有缓存并在缓存可用期那直接拿来用。2.缓存不存在或者不可用 那需要请求。
浏览器拿到host,判断:1.ip+port 那直接请求对应的服务器 2.域名 那开展一系列的dns递归查询:先拿dns缓存,没有缓存->本地dns服务器->根dns服务器->顶级dns服务器->权威dns服务器->GSLB,查到ip返回最优ip组实现负载均衡,浏览器随机或者轮询取一个ip开始它的http请求之旅。
浏览器判断该网页是否允许缓存,然后添加Cache-Control的各种字段no-store是否允许缓存/no-cache缓存必须进行验证/noly-if-cached只接受代理的缓存等,max-age最大生存时间 max-stale 短时间过期可用 min-fresh 最短有效时间等。If-Modified-Since/if-None-Match/Last-modified/ETag等字段用于判断服务端是否有更新。然后将请求发给代理服务器。请求代理服务器,如果是第一次,要经历浏览器和代理服务器的3次tcp握手进行连接,连接成功,发送http请求。
代理服务器拿到请求,首先查看是否允许缓存,允许那就查看自己本地缓存有没有,通过查看max-age/max-stale/min-fresh等信息判断是否过期,没有过期直接拿来用,将数据返回给客户端。如果过期了,代理服务器将用客户端的请求,再次像真实服务器进行请求。如果也是第一次连接,需要经历代理服务器和真实服务器的3次tcp握手,连接成功,发送请求。
真实服务器收到请求之后,通过if-Modified-Since/Last-Modified/if-None-Match/ETag等字段判断是否有更新,没有更新,直接返回304。如果有更新,则将数据打包http response 返回。返回头字段会添加Cache-Control字段,用来判断缓存的控制策略以及生存周期,no-store不允许缓存/no-cache使用缓存必须先验证/must-revalidate缓存不过期可用过期必须重新请求验证/proxy-revalidate缓存过期只要求代理进行请求验证 private不能在代理层保存只能在客户端保存/public缓存完全开放 s-maxage缓存在代理上可以缓存的时间 no-transform不允许代理对缓存做任何的改动。然后根据业务需求判断该地址是不是需要重定向,如果需要是短期的重定向还是永久的重定向,按需将状态码修改为301或者302。最后真实服务器将数据打包成http相应 回给代理服务器。
代理服务器收到真实服务器的回应数据,首先会查看Cache-Control里的字段,是否允许它进行缓存,如果是private,代理服务器不进行缓存,直接返回给客户端。public则根据s-maxage/no-transform进行缓存,如果可以优化并且代理服务器需要优化,那可能会先优化数据,否则同时将数据回发给客户端。
客户端收到数据,如果是304,则直接拿缓存数据进行渲染,并修改相关缓存变量,比如时间,以及缓存使用策略。如果收到了301或者302,那么客户端会再次发起新的url请求,进行跳转到最终的页面。
最后,底层tcp 经过4次挥手,完成关闭连接。

|> 课后思考

​​1、加入了代理后 HTTP 的缓存复杂了很多,试着用自己的语言把这些知识再整理一下,画出有缓存代理时浏览器的工作流程图,加深理解。

答:如笔记内

2、缓存的时间策略很重要,太大太小都不好,你觉得应该如何设置呢?

答:根据缓存变化频率来设置,有规律根据规律走,没有规律不做缓存

四、安全篇

01| HTTPS、SSL、TLS

|>为什么要有HTTPS

  1. 天生明文,任何人都可以在各个节点做假
  2. 代理服务也可以发送虚假请求、响应

|>什么是安全?

  • 机密性:数据是保密的,就是不能让不相关的人看到不该看的东西。
  • 完整性:在传输的过程中不会被篡改,不多不少。
  • 身份认证:保证消息只发给可信的人。
  • 不可否认:不能否认已经发生过的行为。

|>什么是HTTPS

  • 使用新默认端口443
  • HTTPS 协议在语法、语义上和 HTTP 完全一样
  • HTTPS把HTTP层下的TCP、IP协议转为SSL、TLS(当然也能用别的,比如FTP)

来一幅图讲解一下HTTP与HTTPS的区别:

万字HTTP学习笔记_第36张图片

|>SSL、TLS

SSL即安全套接层(Secure Sockets Layer),SSL在V3版本被IETF改名为TLS(传输层安全,Transport Layer Security),版本号从1.0重新算,所以TLS1.0实际上就是SSLV3.1。

  • TLS由记录协议、握手协议、警告协议、变更密码规范协议、扩展协议等几个子协议组成,综合使用了对称加密、非对称加密、身份认证等密码学技术。
  • 浏览器和服务器在使用TLS建立连接需要用一组加密算法来通信, 这些算法组合叫密码套件
  • 如“ECDHE-RSA-AES256-GCM-SHA384”,TLS对密码套件的命名规范为,握手用“ECDHE”,用RSA签名认证,握手后用AES算法,长度为256,分组模式是GCM,摘要算法用SHA385用于消息认证和产生随机数。

|>OpenSSL

摘抄:

说到 TLS,就不能不谈到 OpenSSL,它是一个著名的开源密码学程序库和工具包,几乎支持所有公开的加密算法和协议,已经成为了事实上的标准,许多应用软件都会使用它作为底层库来实现 TLS 功能,包括常用的 Web 服务器 Apache、Nginx 等。OpenSSL 是从另一个开源库 SSLeay 发展出来的,曾经考虑命名为“OpenTLS”,但当时(1998 年)TLS 还未正式确立,而 SSL 早已广为人知,所以最终使用了“OpenSSL”的名字。OpenSSL 目前有三个主要的分支,1.0.2 和 1.1.0 都将在今年(2019)年底不再维护,最新的长期支持版本是 1.1.1,我们的实验环境使用的 OpenSSL 是“1.1.0j”。由于 OpenSSL 是开源的,所以它还有一些代码分支,比如 Google 的 BoringSSL、OpenBSD 的 LibreSSL,这些分支在 OpenSSL 的基础上删除了一些老旧代码,也增加了一些新特性,虽然背后有“大金主”,但离取代 OpenSSL 还差得很远。

|>小结

  1. 因为HTTP是明文,所以不安全,容易被篡改和监听
  2. 通信安全必须满足,机密性、完整性、身份验证、不可否认
  3. HTTPS语义还是HTTP,只是把下层的TCP/IP改了SSL/TLS
  4. OpenSSL是著名的开源密码学工具,是SSL/TLS的具体实现

|>课后思考

1、你能说出 HTTPS 与 HTTP 有哪些区别吗?

答:传输层的不同

2、你知道有哪些方法能够实现机密性、完整性等安全特性呢?

补充:实现机密性可以采用加密手段,接口签名实现完整性,数字签名用于身份认证

02| 对称加密和非堆成加密

  • 加密:把消息转换成谁也看不懂的格式,只有只有掌握钥匙的人才能转换出原来的消息
  • 密钥:密钥就是这里的钥匙,是一串长的数字,约定俗成用位(bit)。如果密钥长度是128bit,那么就是16字节的二进制串。
  • 明文:加密前的信息
  • 密文:加密后的信息
  • 解密:使用密钥还原密文

|>对称加密

对称加密很好理解,就是加、解密都是用一个密钥

万字HTTP学习笔记_第37张图片

 TLS有非常多的对称加密算法可以提供,比如 RC4、DES、3DES、AES、ChaCha20 等,但前三种算法都被认为是不安全的,通常都禁止使用,目前常用的只有 AES 和 ChaCha20。

|>加密分组模式

  • 让算法用固定长度的密钥加密任意长度的明文
  • 常用的分组模式为:GCM、CCM 和 Poly1305
  • 加上使用AES128加密,那么分组就是每16个字节分一组来加密

|>非对称加密

对称加密无法解决被窃取密钥从而解密密文的方法,所以出现了非对称加密(公钥加密算法)

  • 有两个密钥,一个叫公钥,一个叫私钥,两个密码是不同不对对称的,公钥可以给任何人,私钥必须严格保密
  • 公钥加密后,只能私钥解开,私钥加密,只能是公钥解开
  • 常用算法:RSA1024/2048(整数分解)、ECC(椭圆曲线离散对数),ECC密钥更短,性能相较于RSA高。

万字HTTP学习笔记_第38张图片

|>混合加密

由于非对称的加解密设计到数学公式,那么会比较消耗双方计算性能,跟对称加密是相差几百倍,所以出现了混合加密。

混合加密采用了,首次交换对称加密密钥的时候,把对称加密密钥当作报文用非对称加密的方法加密,等建立了连接以后,就用这个随机生成的对称加密密钥来加密报文,因为这个过程中的对称加密密钥是加密过的,就算截取了也无法解出,所以更加解不出后面对称加密加密过的报文,从而保密了数据。

万字HTTP学习笔记_第39张图片

|>小结

  1. 加密算法的思想是:一个小加密串,转化为一个大的密文消息
  2. 对称加密只使用一个密钥,速度较快,密钥必须保密,但是无法保证安全的密钥交换,并且它所占的位数野较小
  3. 非对称加密有两个密钥,公钥可以随便分发,私钥自己自己有,但是加解密较蛮慢

|>课后思考

1、在混合加密中用到了公钥加密,因为只能由私钥解密。那么反过来,私钥加密后任何人都可以用公钥解密,这有什么用呢?

答:私钥加密过后的数据,公钥才能打开,证明这个协议确实是下发公钥过来的那个人,而不是其他人

03| 数字签名与证书

只有对报文加密是不够的,一方面是黑客可以搜集尽量多的报文,去试探服务器的响应,再获取进一步的线索,最后破解明文。或者是下发的公钥根本就不是源服务器或代理服务器的,而是黑客建立的钓鱼网站,你以为你在跟某人聊天,其实不是,那个只是戴上头套的黑客(碟中谍)。

万字HTTP学习笔记_第40张图片

 |>摘要算法

  • 摘要算法近似的理解为压缩算法,它能够把任意长度的数据压缩成固定长度,是独一无二的字符串
  • 单向加密算法,只有算法,没有密钥,加密无法解密
  • 好的摘要算法能够抵抗碰撞
  • 摘要算法对输入具有“单向性”和“雪崩效应”,输入的微小不同会导致输出的剧烈变化
  • 常用SHA224、SHA256、SHA384,分别生成28字节,32字节,48字节的摘要,MD5很少用了。

|>完整性

有了摘要,如果消息在传输过程中被修改,那么数据的摘要一定是不一样的,如果把摘要不具有机密性的话,那么很可能会把摘要也改了,所以摘要也要做机密性。如图所示

万字HTTP学习笔记_第41张图片

|>数字签名

有了以上的这些手段,还是很可能有漏洞,除了能伪造网站,还能伪造用户,向服务端发请求,所以客户端必须证明自己是自己,所以这里要用数字签名。

万字HTTP学习笔记_第42张图片

和网站互换公钥,然后我用自己的私钥签名消息,网站收到后用我的公钥来验签,以此来证明我是我。

|>数字证书与CA

任何的人都可以生成公钥,所以怎么证明这个公钥就是某权威网站的呢,这里就用到了CA

  • CA对公钥的签名认证是有格式的,要包含序列号,用途,颁发者,有效时间
  • 知名CA有DigiCert、VeriSign、Entrust、Let’s Encrypt 等,们签发的证书分 DV、OV、EV 三种,区别在于可信程度
    • DV 是最低的,只是域名级别的可信,背后是谁不知道。EV 是最高的,经过了法律和审计的严格核查,可以证明网站拥有者的身份(在浏览器地址栏会显示出公司的名字,例如 Apple、GitHub 的网站)。
  • CA如何证明自己是合法的CA,总不能收到是什么就什么什么吧,所以这里是信任链的问题,小一点的CA让大CA签名认证,到最后一定是RootCA,这个RootCA只能自己认证自己

|>证书体系的弱点

  1. 由于CA的失误或者被欺骗,签发了错误的证书,用CRL吊销列表,还有OCSP在线证书状态协议,及时废止有问题的CA
  2. CA被黑客攻击、CA有恶意,撤销CA的信任,列入黑名单,他所颁布的证书都被认为是不安全的

|>小节

  1. 摘要算法用来实现完整性,生成独一无二的指纹
  2. 数字签名是用私钥对摘要加密,服务器有用户的公钥,可以判断这个是否是用户自己
  3. 公钥的分发需要试用数字证书,这是一个网站的身份证,公钥类似我的身份证号,以证明我是我
  4. 作为信任链的源头有时候不可信,有CRL、OCSP等手段终止信任

|>课后思考

1、为什么公钥能够建立信任链,用对称加密算法里的对称密钥行不行呢?

答:不可以,因为在一开始交换对称密钥的时候有可能泄露密钥。私钥加密,公钥解密能证明我是我

2、假设有一个三级的证书体系(Root CA=> 一级 CA=> 二级 CA),你能详细解释一下证书信任链的验证过程吗?

补充:

一、具体流程大概是:
1、服务器去CA机构申请证书,证书中包含了要发给客户端的公钥、签发者、到期时间等等信息。如果这样简单地把证书发给浏览器,中间人可以轻松地修改成自己的公钥,之后的通信就是不安全的了。于是需要一定的加密手段,这里的做法就是使用数字签名:将证书的信息利用摘要算法计算出摘要之后,用CA的秘钥进行加密,生成数字签名。
2、服务器将数字证书和数字签名一起发给浏览器,因为有数字签名,所以数字证书无法被中间人做修改(修改之后生成的数字签名无法被CA公钥解密),浏览器拿到数字证书之后,去本地的信任机构中查询到对应的机构,利用其公钥解密数字签名,验证证书是否有被修改过。这一步就保证了浏览器获取到的公钥一定是正确的。
3、公钥正确地传给浏览器之后,接着就是协商对称加密的密钥,然后通信等等..

二、服务器返回的是证书链(不包括根证书,根证书预置在浏览器中),然后浏览器就可以使用信任的根证书(根公钥)解析证书链的根证书得到一级证书的公钥+摘要验签,然后拿一级证书的公钥解密一级证书拿到二级证书的公钥和摘要验签,再然后拿二级证书的公钥解密二级证书得到服务器的公钥和摘要验签,验证过程就结束了。

04| TLS1.2\1.3

|>TLS协议组成

  • TLS 包含几个子协议,相当于几个不同职责的模块。
    • 记录协议:用于规定TLS收发数据的基本单位,所有子协议都要通过记录协议发出,多个记录数据可以在一个TCP包发出,不需要像TCP那样ACK
    • 警报协议:向对方发出警报信息,类似状态码
    • 握手协议:用于浏览器和服务器握手过程中协商TLS版本号、随机数、密码套件等,然后交换证书和密钥,在协商得到会话密钥,用于混合加密
    • 变更密码规范协议:通知对方,后续数据用加密保护,在此之前是明文

万字HTTP学习笔记_第43张图片

|>抓包准备工作

目前是直接wireshark过滤tls的协议

|>ECDHE握手过程

万字HTTP学习笔记_第44张图片

  •  TCP建立了连接以后,浏览器回发“Client Hello”。里面包括了客户端的协议版本号、支持的密码套件、还有一个随机数。还带有一些拓展项
  • 随后Sever端收到以后,也会返回一个“Server Hello”

万字HTTP学习笔记_第45张图片

  • 版本号对上了以后,可以加密, 这里服务端的Hello选择了本次通信的密码套件,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384”,用椭圆曲线 + RSA、AES、SHA384。同时Server也给了一个随机数

万字HTTP学习笔记_第46张图片

  •  随后是服务器的证书,用于证明自己是自己

万字HTTP学习笔记_第47张图片

  •  这里服务器把自己的公钥传了下来,这里的密钥是服务端通过生成一个随机数作为私钥,并且根据ECDHE算法生成了公钥,并且还附带上自己的签名,证明自己是自己

万字HTTP学习笔记_第48张图片

  • 重点来了,客户端也生成一个随机数作为本次会话的私钥,然后用这个Key去生成一个公钥,发给服务器
  • 两端现在同时握有、server pub key,client pub key,双端还有自己的private key,由于ECDHE算法得出,用对方的公钥 + 自己的私钥,可以或的一个椭圆曲线上面的X,Y点,并且X还是相等的,所以这里就出现了一个叫pre-master的Key
  • 根据前面交换的Server-Random、Client- Random、pre-master,这三个值来算出最终的会话密钥(master-secret),PRF还会拓展出更多的密钥,比如客户端发送的密钥,服务端发送的密等等,避免一个密钥带来的隐患
  • 为什么能这样算得看这个博客ECDHE

万字HTTP学习笔记_第49张图片

  •  有了主密钥和派生的会话密钥,握手就快结束了。客户端发一个“Change Cipher Spec”,然后再发一个“Finished”消息,把之前所有发送的数据做个摘要,再加密一下,让服务器做个验证。万字HTTP学习笔记_第50张图片
  •  服务器也是同样的操作,发“Change Cipher Spec”和“Finished”消息,双方都验证加密解密 OK,握手正式结束,后面就收发被加密的 HTTP 请求和响应了。

|>RSA握手过程

  • RSA握手过程,不会发送“Server Key Exchange”
  • 客户端不用等服务器返回“Finished”再发HTTP报文
  • 无需生成“Pre-Master”,客户端直接生成随机数,用服务器的公钥加密,只有服务器能看。

|>双向认证

  • 上面说的都是单向验证,只验证了服务端得身份,没有认证客户端的身份,是因为客户端在进行操作的时候,用账密就可以确认用户的真实身份
  • 同时可以用U盾这样的给客户端颁发证书来实现双向认证,只需在“server hello done”后,“client key exchange”之前给服务端发送客户端的cert即可

|>TLS1.3

        |>最大化兼容性

        由于1.1、1.2版本已经推出了很多年,所以改造很困难,所以TLS1.3不得不向下兼容,用拓展协议在末尾添加一系列的拓展字段来增加新的功能,握手的hello消息后面必须有supported_versions,标记TLS版本号区分新旧协议。

        |>强化安全

        废除了许多加密算法,禁用了加密,使得TLS1.3更轻量,为什么不用RSA算法加密,都用ECDHE,是为了防止今日截获,明日破解的状况,一但RSA加密被破戒了,获取了pre master,那么以往的所有信息都将泄露。

        |>提升性能

        TLS1.3比TLS1.2减少了一个RTT,删除了“key-exchange”,在hello把需要的椭圆曲线、签名算法、公钥带上

 |>小节

  1. HTTPS协议会先与服务器执行TCP连接,再执行TLS握手
  2. 握手的慕白哦是安全的交换对称密钥,需要三个随机数,第三个随机数,premaster必须加密,不能破解,ECDME是通过双方计算得出的。
  3. Hello交换随机数,key exchange 交换pre master
  4. “Change Cipher Spec”之前传输的都是明文,之后都是对称密钥加密的密文。
  5. 由于要向下兼容所以TLS1.3伪装成TLS1.2
  6. TLS1.3删除了大量有安全隐患的算法
  7. 简化了握手流程,只需要一个消息往返

 |>课后思考

1、密码套件里的那些算法分别在握手过程中起了什么作用?

2、你能完整地描述一下 RSA 的握手过程吗?

3、你能画出双向认证的流程图吗?

4、TLS1.3 里的密码套件没有指定密钥交换算法和签名算法,那么在握手的时候会不会有问题呢?

答:TLS1.3精简了加密算法,通过support_groups、key_share、signature_algorithms这些参数就能判断出密钥交换算法和签名算法,不用在cipher suite中协商了

5、结合上一讲的 RSA 握手过程,解释一下为什么 RSA 密钥交换不具有“前向安全”。

答:一次破解终生免费

6、TLS1.3 的握手过程与 TLS1.2 的“False Start”有什么异同?

答:相同点:都在未收到Finished确认消息时就已经向对方发送加密信息了,不同点:TLS1.3将change cipher spec合并到了hello中

05| HTTPS优化

  • HTTPS比HTTP慢的原因是因为:
    • HTTPS需要TLS握手
    • 用于密钥交换产生的公私钥对
    • 验证证书访问CA
    • 非对称加密处理Pre-Master
  • 硬件优化:
  • 软件优化:
  • 协议优化:
  • 证书优化:
  • 会话复用:
  • 会话票证:
  • 预共享密钥:

*待完成的篇幅:

06| HTTPS使用场景

五、飞翔篇

六、探索篇

01| Nginx

02| OpenResty

03| WAF

04| CDN

05| WebSocket

七、总结篇

01| HTTP性能优化

八、小测题剖析

你可能感兴趣的:(学习日记,http,网络协议,网络)