Wireshark解密HTTPS
◼ 设置环境变量SSLKEYLOGFILE(浏览器会将key信息导出到这个文件)
先在电脑上创建ssl.log文件
点击计算机>属性>高级系统设置>环境变量>用户变量>新建
◼ 设置完成后,最好重启一下操作系统
◼ 在Wireshark中选择这个文件
编辑 → 首选项 → Protocols → TLS
先点击以太网>输入tcp port 443>enter
在浏览器访问baidu.com
只有搞了这些东西,我们才可以解析出来用了什么协议
HTTP2是基于二进制帧的概念
◼ 如果环境变量不管用,可以直接设置浏览器的启动参数(下图是使用了Rolan进行启动)
配置服务器HTTP—生成证书
使用什么协议,是由后端工程师决定的
浏览器自带CA机构的公钥,可以自动验证证书
TCP三次握手,TSL十次连接,浏览器那边自动就做了,不用我们来
做为客户端,我们只要去访问URL就可以了,在前端把协议一改,用HTTPS去访问
做为服务器,我们要把证书放上去,顺便告诉客户端去哪里找这个证书
到时候,做为公司,我们去买商用的证书就可以了,比如阿里云
◼ 环境:Tomcat9.0.34、JDK1.8.0_251
◼ 首先,使用JDK自带的keytool生成证书(一个生成免费证书的网站: https://freessl.org/)
由于JDK的bin目录,我们已经配送到了环境变量里面去了,意味着,我们可以在cmd界面直接敲
keytool -genkeypair -alias mj -keyalg RSA -keystore F:/mj.jks
代码解释
jks,java keystore
配置服务器HTTPS—配置Tomcat
◼ 将证书*.jks文件放到TOMCAT_HOME/conf目录下
配置服务器HTTPS—配置Tomcat
打开TOMCAT_HOME/conf/server.xml
把8080端口的Connector给注释掉
把HTTPS的模板给复制上来
◼ 修改TOMCAT_HOME/conf/server.xml中的Connector
就改一个地方(certificateKeystoreFile),添一个地方(certificateKeystorePassword)
服务器添加证书成功
因为浏览器不认识我们的自签证书,所以显示不安全
但是我们真的是用TLS加密通道的,可以通过Wireshark抓包来查看
开发人员做的是请求这个地址,至于HTTP请求库自带的功能怎么搞,跟我们没有关系
利用HTTP请求库去请求右边HTTPS服务器,至于验证证书跟我们没有关系
左边要有验证证书的能力,右边放一个证书,给左边下载
注释:实验做完,记得改过来,不要去污染我们的环境
HTTP协议的不足(HTTP/1.1)
看底层,只要你用的是HTTP/1.1,你就存在下面的问题
◼ 同一时间,一个连接只能对应一个请求
连接可以复用,但是你要排队,前面的结束了,你后面的才可以过去
为了能够实现请求并发,可以同时建立多个连接
针对同一个域名,大多数浏览器允许同时最多6个并发连接
◼ 只允许客户端主动发起请求
首先我们的第一个请求是获取网站的html,但浏览器在解析的过程当中,发现要去加载CSS、图片、JS
所以我们在加载一个网站的时候要发起很多次请求,因为HTTP/1.1的特性,服务器做不到一次请求给我们发很多东西,只能是请求和应答的模式,所以我们要发起很多次请求
一个请求只能对应一个响应
◼ 同一个会话的多次请求中,头信息会被重复传输
在这个会话过程中,为了证明自己的身份,每一次请求都要发送cookie过去
通常会给每个传输增加500~800字节的开销
如果使用 Cookie,增加的开销有时会达到上千字节
每一次请求都要重复发上千字节
SPDY
◼ SPDY(speedy的缩写),是基于TCP的应用层协议,它强制要求使用SSL/TLS
2009年11月,Google宣布将SPDY作为提高网络速度的内部项目
作为改进HTTP/1.1的项目,因为它觉得HTTP/1.1太慢了,每次都要重复传一些东西,消耗流量;服务器无法发送数据过来;同一时间,一个连接只能对应一个请求,很麻烦,假设一个网站要100次请求,那要搞到什么时候
HTTP是一个全球标准,它要有标准组织认可才可以改,所以Google先自己用,等自己用了没问题,在推广
◼ SPDY与HTTP的关系
SPDY并不用于取代HTTP,它只是修改了HTTP请求与响应的传输方式
HTTP报文先传给SPDY,SPDY进一步压缩进行一系列处理等等,然后交给TLS
之前HTTP报文段就是文本,字符串
SPDY对HTTP报文进行加工,处理,让它传输的更快,最终在加密交给TCP
只需增加一个SPDY层,现有的所有服务端应用均不用做任何修改
以前我们编写的代码通通不用动,包括前端和后端,因为我们编写的代码是面向HTTP开发的
SPDY属于服务器的配置,代码不用动
SPDY是HTTP/2的前身
✓ 2015年9月,Google宣布移除对SPDY的支持,拥抱HTTP/2
推动变成国际标准,但是之前大家用的是HTTP,为了方便推动就改成了HTTP/2
HTTP/2
右键点击Status,选择Protocol,就可以查看请求用了什么协议
◼ HTTP/2,于2015年5月以RFC 7540正式发表
根据W3Techs的数据,截至2019年6月,全球有36.5%的网站支持了HTTP/2
◼ HTTP/1.1和HTTP/2速度对比
http://www.http2demo.io/
https://http2.akamai.com/demo
快了四倍
HTTP/1.1,一条横线就是一个连接,每一个连接是可以复用的,六个连接包揽了100多个请求
HTTP/2用一个连接,搞定了所有的请求
◼ HTTP/2在底层传输做了很多的改进和优化,但在语意上完全与HTTP/1.1兼容
速度特别快
比如请求方法(如GET、POST)、Status Code、各种Headers等都没有改变
API层面没有变,对我们开发者没有任何影响
因此,要想升级到HTTP/2
✓ 开发者不需要修改任何代码(JAVA、安卓、IOS等代码)
✓ 只需要升级服务器配置、升级浏览器
就像配置HTTPS一样
浏览器要升级一下,才会有SPDY的功能
操作系统内核里面包含了处理传输层以下的东西的API,为了应用TCP的新特性,我们要去升级一下操作系统内核,内核里面要去改代码,这是很麻烦的,但是SPDY就不一样了
应用层可以由开发者决定,比如加上一层SPDY,我们只要升级一下应用层的软件就可以了
HTTP/2的RFC文档里面不强求使用TSL/SSL,但是现在只要使用HTTP/2的公司基本上都有用TSL/SSL
HTTP/2的速度非常快,采用TSL/SSL浪费的时间基本上可以忽略不记,完全可以上安全层
HTTP/2的特性—二进制格式
◼ HTTP/2采用二进制格式传输数据,而非HTTP/1.1的文本格式(字符串)
打散,把HTTP报文编码成二进制格式,不是我们一眼可以看懂的
把信息转化成二进制帧
◼ 二进制格式在协议的解析和优化扩展上带来更多的优势和可能
先把报文打散,在传输
HTTP/2—一些基本概念
◼ 数据流:已建立的连接内的双向字节流,可以承载一条或多条消息
在一次请求当中,就好比一个数据流,双向的,类似一个管道
所有通信都在一个TCP连接上完成,此连接可以承载任意数量的双向数据流
同一个时间,一个TCP连接,可以处理N个请求
◼ 消息:与逻辑HTTP请求或响应消息对应,由一系列帧组成
我们发的和接收的内容
◼ 帧:HTTP/2通信的最小单位,每个帧都包含帧头(会标识出当前帧所属的数据流)
来自不同数据流的帧可以交错发送,然后再根据每个帧头的数据流标识符重新组装
客户端给服务器的是5号流,给客户端的是1,3号流,交错发送,所以非常快
数据流一排排的过去,他是逻辑上的概念,真实情况数据流的帧是交错发送的,并发的,随便发,在拼接的时候,才需要管顺序
HTTP/2—一些基本概念
在逻辑上有N号流,每一条流都是双向的,在上面有非常多的帧
HTTP/2的特性—多路复用(Multiplexing)
◼ 客户端和服务器可以将 HTTP消息分解为互不依赖的帧,然后交错发送,最后再在另一端把它们重新组装起来
◼ 并行交错地发送多个请求,请求之间互不影响
◼ 并行交错地发送多个响应,响应之间互不干扰
◼ 使用一个连接并行发送多个请求和响应
◼ 不必再为绕过HTTP/1.1限制而做很多工作
因为HTTP/1.1的限制,开发人员想尽各种办法,去提高我们的网速
尽量减少请求数量
比如image sprites、合并CSS\JS、内嵌CSS\JS\Base64图片、域名分片等
image sprites:精灵图片,雪碧图
合并CSS\JS:把很多个文件合并成一个文件,比如你搞四个CSS文件,就要搞四个请求,我们可以把四个文件合并成一个文件,那只需要一个请求
内嵌CSS\JS:
把CSS\JS代码内嵌进HTML里面去,响应给浏览器,就不用下次在请求
内嵌Base64图片:
先去访问工具网站,https://c.runoob.com/front-end/59/
上传图片,即可得到图片的BASE64编码,
在HTML代码中,引入BASE64编码,即可
不过,因为我的像素过大,所以我最终的结果,图片是损坏的
BASE64图片的原则是,把图片的像素信息进行编码,转成字符串进行描述
这样做,就可以减少图片的请求,因为图片数据已经包含在HTML里面了
只适合小图片,图片越大,像素越多,字符串就越长,就会导致HTML超长,不太好维护
浏览器根本就没有发请求,直接去解析字符串,图片数据已经在BASE64图片里面了,这个是给我们看的
你的N多个请求都在一个连接上发,而且这个连接上可以有很多流,交错发送
底层用的是TCP,TCP是有序的,最终拿数据是按照顺序来的
image sprites
◼ image sprites(也叫做CSS Sprites),将多张小图合并成一张大图
最后通过CSS结合小图的位置、尺寸进行精准定位
开发者只要知道,我想要的图片相对这张大图来说,你左边距离多少,上边距离多少,图片宽度多少,高度多少,这样我就可以实现精准定位,然后把它抠出来,显示出来
代码不经常敲就会忘
精灵图这个技术实在是恶心,需要多方配合,美工需要把这张图片合在一起,开发者需要知道每张图片的具体位置,所以会有一个列表信息,把图片的位置给列出来,还有一个参照表
但是我们现在有HTTP2就不用这么搞了,我们永远只有一个连接,所有的数据都在里面传输,而且这些数据还是打散的,速度非常快
精灵图片的排布顺序是乱的,它是根据算法生成,是为了尽量让空间小一点,只要加一张图片,整张精灵图片都会变,排布顺序全部打乱
域名分片:
一个域名最多只能有六个连接,搞一些子域名,把图片放到那个域名的图片里面去,直接访问那个域名
穿插一些iframe,在这个iframe里面放一些请求,这样就可以去请求其它的页面
HTTP/2的特性—多路复用(Multiplexing)
以前,同时请求3个文件,就要3个连接,一个连接,同时只能处理一个请求
现在,一个连接可以处理N个请求,数据可以打散,交错传送,非常棒
我只打开一个连接,持续打开,你后面还有请求,继续用这个连接,可以同时并发传送数据,棒极了!
HTTP/2的特性—优先级
◼ HTTP/2 标准允许每个数据流都有一个关联的权重和依赖关系
可以向每个数据流分配一个介于1至256之间的整数
每个数据流与其他数据流之间可以存在显式依赖关系
A可能依赖于B,B可能依赖于C
◼ 客户端可以构建和传递“优先级树”,表明它倾向于如何接收响应
设定一个优先级,告诉服务器,我先接收那个,后收那个
◼ 服务器可以使用此信息通过控制CPU、内存和其他资源的分配设定数据流处理的优先级
在资源数据可用之后,确保将高优先级响应以最优方式传输至客户端
HTTP/2的特性—优先级
权重越大,代表优先级越高。
隐式根流:看不见的数据流
◼ 应尽可能先给父数据流分配资源
◼ 同级数据流(共享相同父项)应按其权重比例分配资源
① A、B依赖于隐式“根数据流”,A获得的资源比例是12/16,B获得的资源比例是4/16
谁获得的资源比例高,谁就优先发,所以A先发
② D依赖于根数据流,C依赖于D,D应先于C获得完整资源分配
③ D应先于C获得完整资源分配,C应先于A和B获得完整资源分配,B获得的资源是A所获资源的1/3
④ D应先于E和C获得完整资源分配,E和C应先于A和B获得相同的资源分配,B获得的资源是A所获资源的1/3
HTTP/2的特性—头部压缩
会跟踪你以前发过的请求,第二次请求会根据压缩算法,只会发之前没有发过的,发重要的东西
浏览器会存储之前的请求,进行比对,把之前发过的请求头给删掉
无状态,请求和请求之间是独立的,它不会去管你上次有没有带Cookie,请求的是什么。它就是去对比,把你重复的部分给删掉,它才不管你发的是什么内容
只是保留了你上次发的请求而已 ,相当于是一个记录的行为
HTTP2作为底层,记录了HTTP发过的请求
◼ HTTP/2使用HPACK压缩请求头和响应头
可以极大减少头部开销,进而提高性能
◼ 早期版本的HTTP/2和SPDY使用 zlib压缩
可以将所传输头数据的大小减小85%~88%
但在2012年夏天,被攻击导致会话劫持
后被更安全的HPACK取代
HTTP/2的特性—头部压缩
静态表,本来索引里面就会有的东西,常用的、可能会用到的,建立一张表出来,把动态表放到后面去
动态表,随着不断的发请求,就会有一些新的请求头
在客户端和服务器各保留一份,双方都会保存请求过的东西
索引表里面有的,只发索引号,服务器会根据索引号找到对应的头信息
HTTP/2的特性—服务器推送(Server Push)
◼ 服务器可以对一个客户端请求发送多个响应
前提还是要客户端发送请求
只要是HTTP,肯定是请求—应答模式,先有请求才有应答
除了对最初请求的响应外,服务器还可以向客户端推送额外资源,而无需客户端额外明确地请求
例如我们请求京东的HTML,发现里面还需要CSS、IMG、JS,那服务器就会把这些资源推过来,相当于节省了请求
流是双向的,有过去就有回来
你只有一个请求,但是我却给你多个响应
HTTP/2的问题—队头阻塞(head of line blocking)
由于TCP的按序特性,当TCP接收的时候少了一个包时,后面东西就不会收了,这个时候只能重发
这个问题是由TCP决定的,而不是HTTP的问题
QUIC协议,传输的数据互不影响,当接收的时候少收了一个包时,可以把后面的优先提出来,丢的那个包后面补发就可以了,因为它底层使用的是UDP协议
HTTP/2的问题—握手延迟
QUIC直接跟你说我要给你发送数据,随后就开始仍数据给你,不用跟你握手,0秒建立连接
◼ RTT(Round Trip Time):往返时延,可以简单理解为通信一来一回的时间
HTTP/2的问题—握手延迟
QUIC跟你讲我要跟你建立连接,然后直接就给你仍数据,不用跟你握手
HTTP/3
◼ Google觉得HTTP/2仍然不够快,于是就有了HTTP/3
存在握手延迟、队头阻塞的问题
HTTP/3由Google开发,弃用TCP协议,改为使用基于UDP协议的QUIC协议实现
QUIC(Quick UDP Internet Connections),译为:快速UDP网络连接,由Google开发,在2013年实现
于2018年从HTTP-over-QUIC改为HTTP/3
传输层使用UDP协议,应用层加了一个QUIC协议,TLS升级为1.3版本,压缩算法改成了QPack,但仍然保留了流的概念
可以理解为在HTTP2的基础上加了层QUIC
HTTP/3—疑问
◼ HTTP/3基于UDP,如何保证可靠传输?
由QUIC来保证
之前是TCP层跟TCP层对接,你那边拿到了多少包,有没有漏收,漏收了我发给你,来保证可靠传输,丢包和请求失败都是TCP层报给HTTP层
丢了就丢了,对方的UDP层能收多少是多少,导致 HTTP层拿到的是不完整的,比如我们要图片,可能图片只拿到了一半,甚至连一半都没有
QUIC层会告诉对方自己发了多少个,漏了会补发,它们之间存在沟通的渠道,少了的那一方,会让对方QUIC层补发,所以我用了UDP层我也无所谓,因为QUIC层可以保证可靠传输
TCP之所以可以保证可靠传输,是因为它复杂的头部信息,TCP里面有代码可以保证可靠传输,那QUIC层也是一样的,也是有代码来保证可靠传输
就相当于是把TCP层用来保证可靠传输的那部分给取了出来,重新命了个名
◼ 为何Google不开发一个新的不同于TCP、UDP的传输层协议?
Google有能力去开发一个新的传输协议,例如GDP,兼具TCP和UDP的功能(可靠传输),解决HTTP/2存在的问题(队头阻塞)
这样子,就不会有多出来的一层,还要去写QUIC
目前采用的是,队头阻塞用UDP解决,可靠传输,我自己写一个
目前世界上的网络设备基本只认TCP、UDP
路由器、电脑、手机这些设备,固化在里面的,只认这两个
那就代表我们要研发新的设备,现在互联网上的设备都不能用了,谁出钱,我凭什么换
如果要修改传输层,意味着操作系统的内核也要修改
SocketAPI发送请求的,它是系统内核里面的东西,传输层一改,它也要跟着改
修改传输层,这是一个不现实的东西
另外,由IETF标准化的许多TCP新特性都因缺乏广泛支持而没有得到广泛的部署或使用
因此,要想开发并应用一个新的传输层协议,是极其困难的一件事情
这是一个兼容问题
HTTP/3不是最终标准,它还在改进当中
HTTP/3的特性—连接迁移
◼ TCP基于4要素(源IP、源端口、目标IP、目标端口)
也可以叫四元组
只有知道这四要素才可以建立连接,端口往端口发
切换网络时至少会有一个要素发生变化,导致连接发生变化
双方IP确定,端口确定,即可建立连接
手机自带蜂窝网络(移动网络),切换到WIFI,IP可能会变,以前的网络就不能用了
TCP的头部有源IP,目标IP,这个是改变不了的,以前的网络会超时断开,因为它找不到源IP了,这个时候只能等待一段时间,在重新建立连接
这就是当我们手机切换网络时,会卡顿的原因,甚至玩游戏会掉线
当连接发生变化时,如果还使用原来的TCP连接,则会导致连接失败,就得等原来的连接超时后重新建立连接
所以我们有时候发现切换到一个新网络时,即使新网络状况良好,但内容还是需要加载很久
如果实现得好,当检测到网络变化时立刻建立新的TCP连接,即使这样,建立新的连接还是需要几百毫秒的时间
◼ QUIC的连接不受4要素的影响,当4要素发生变化时,原连接依然维持
IP、端口可能会变
QUIC连接不以4要素作为标识,而是使用一组Connection ID(连接ID)来标识一个连接
我们发过去的包里面有Connection ID,但还是需要4要素,因为底层需要,UDP、IP,它们需要IP来找到对方,需要端口找到对应的应用,建立连接
尽管底层的四要素发生了变化,只要你Connection ID不变,我就可以尽全力保证你连接不断开
我指的是QUIC
即使IP或者端口发生变化,只要Connection ID没有变化,那么连接依然可以维持
比如
✓ 当设备连接到Wi-Fi时,将进行中的下载从蜂窝网络连接转移到更快速的Wi-Fi连接
✓ 当Wi-Fi连接不再可用时,将连接转移到蜂窝网络连接
HTTP/3的特性—向前纠错(暂时了解)
还没有成为标准,仍然有改进的空间
TCP丢包,它会超时重传
向前纠错,每个包都有冗余数据,多多少少包含有其它数据包的数据,这样子可以借助其它数据包的冗余数据,组装回丢掉的包
只适合丢掉少量的数据包,比如四个丢一个,要是丢两个就不行了
HTTP/3的问题—操作系统内核、CPU负载
◼ 据Google和Facebook称,与基于TLS的HTTP/2相比,它们大规模部署的QUIC需要近2倍的CPU使用量
Linux内核的UDP部分没有得到像TCP那样的优化,因为传统上没有使用UDP进行如此高速的信息传输
因为我们以前使用的请求大部分是用TCP,例如HTTP请求、邮件都是基于TCP的
TCP和TLS有硬件加速,而这对于UDP很罕见,对于QUIC则基本不存在
还是有很长的路要走
◼ 随着时间的推移,相信这个问题会逐步得到改善