图解计算机网络
网络知识
-
-
数据链路层:数据链路层位于物理层和网络层中间,数据链路层定义了在单个链路上如何传输数据。
-
网络层:
-
网络层主要使用
IP
协议,IP 协议基于 IP 地址转发分包数据。IP 协议的主要作用就是将分组数据包发送到目标主机 -
TCP/IP 分层中的互联网层与传输层的功能通常由操作系统提供。
IP 还隐含着数据链路层的功能,通过 IP 协议,相互通信的主机之间不论经过怎样的底层数据链路,都能够实现相互通信。
虽然 IP 也是一种分组交换协议,但是 IP 却不具备重发机制。即使数据没有到达另一端也不会进行重发,所以 IP 属于非可靠性协议。
-
-
传输层:传输层最主要的功能就是让应用层的应用程序之间完成通信和数据交换。在计算机内部运行着很多应用程序,每个应用程序都对应一个端口号,我们一般使用端口号来区分这些应用程序。
-
-
ICMP协议:ICMP 全称是 Internet Control Message Protocol,也就是互联网控制报文协议。
- ping 是基于
ICMP
协议工作的 - 为什么需要ICMP:遇到网络问题时,需要传出消息,报告遇到了什么问题,这样才可以调整传输策略,以此来控制整个局面。
- 主要的功能包括:确认 IP 包是否成功送达目标地址、报告发送过程中 IP 包被废弃的原因和改善网络设置等。
- 在
IP
通信中如果某个IP
包因为某种原因未能达到目标地址,那么这个具体的原因将由 ICMP 负责通知。 - ICMP 包头的类型字段,大致可以分为两大类:
- 一类是用于诊断的查询消息,也就是「查询报文类型」
- 另一类是通知出错原因的错误消息,也就是「差错报文类型」
- ping 是基于
-
ICMP类型:0回送应答、3目标不可达、4原点抑制、5重定向或改变路由、8回送请求、11超时
-
数据包发送过程
-
-
应用层的处理:应用层需要对这个数据包进行处理,包括字符编码、格式化等等数据包在发送的那一刻建立 TCP 连接,这个连接相当于通道,在这之后其他数据包也会使用通道传输数据。
-
传输层的处理:TCP 会在应用数据层的前端附加一个 TCP 首部字段,TCP 首部包含了
源端口号
和目的端口号
,这两个端口号用于表明数据包是从哪里发出的,需要发送到哪个应用程序上;TCP 首部还包含序号
,用以表示该包中数据是发送端整个数据中第几个字节的序列号;TCP 首部还包含校验和
,用于判断数据是否损坏,随后将 TCP 头部附加在数据包的首部发送给 IP。 -
网络层的处理:
-
网络层主要负责处理数据包的是 IP 协议,IP 协议将 TCP 传过来的 TCP 首部和数据结合当作自己的数据,并在 TCP 首部的前端加上自己的 IP 首部。
-
因此,IP 数据包后面会紧跟着 TCP 数据包,后面才是数据本身。IP 首部包含目的和源地址,紧随在 IP 首部的还有用来判断后面是 TCP 还是 UDP 的信息。
IP 包生成后,会由路由控制表判断应该发送至哪个主机,IP 修饰后的数据包继续向下发送给路由器或者网络接口的驱动程序,从而实现真正的数据传输。如果不知道目标主机的 IP 地址,可以利用
ARP(Address Resolution Protocol)
地址解析协议获取mac地址进行查找目标主机
-
-
通信链路层的处理:
- 经由 IP 传过来的数据包,以太网会给数据附上以太网首部并进行发送处理。以太网首部包含接收端的 MAC 地址、发送端的 MAC 地址以及标志以太网类型的以太网数据协议等。
-
通信链路层的解析:
-
目标主机收到数据包后,首先会从以太网的首部找到 MAC 地址判断是否是发给自己的数据包,如果不是发给自己的数据包则会丢弃该数据包。
如果收到的数据包是发送给自己的,就会查找以太网类型判断是哪种协议,如果是 IP 协议就会扔给 IP 协议进行处理,如果是
ARP
协议就会扔给 ARP 协议进行处理。如果协议类型是一种无法识别的协议,就会将该数据包直接丢弃。
-
-
网络层的解析:
- 经过以太网处理后的数据包扔给网络层进行处理,我们假设协议类型是 IP 协议,那么,在 IP 收到数据包后就会解析 IP 首部,判断 IP 首部中的 IP 地址是否和自己的 IP 地址匹配,如果匹配则接收数据并判断上一层协议是 TCP 还是 UDP;如果不匹配则直接丢弃。
- 在路由转发的过程中,有的时候 IP 地址并不是自己的,这个时候需要借助路由表协助处理。
-
传输层的解析:
- 在传输层中,我们默认使用 TCP 协议,在 TCP 处理过程中,首先会计算一下
校验和
,判断数据是否被损坏。然后检查是否按照序号接收数据,最后检查端口号,确定具体是哪个应用程序。数据被完整的识别后,会传递给由端口号识别的应用程序进行处理。
- 在传输层中,我们默认使用 TCP 协议,在 TCP 处理过程中,首先会计算一下
-
应用层的解析:
- 接收端指定的应用程序会处理发送方传递过来的数据,通过解码等操作识别出数据的内容,然后把对应的数据存储在磁盘上,返回一个保存成功的消息给发送方,如果保存失败,则返回错误消息。
-
DNS
-
DNS原理
-
DNS 是一种分层数据库,主要三层:跟域名服务器、顶级域名服务器、权限域名服务器
-
DNS 运行在 UDP 上,使用 53 端口。
-
dns解析有两种 查询方式,分为递归查询和迭代查询。一般的 主机 向本地域名服务器的查询使用递归查询,本地域名服务器向根域名服务器查询使用迭代查询。它使用的是 UDP协议,原因是性能更好,查询时间更短,如果发生数据丢失,重传一个就好了,不需要建立连接
-
如果根域名服务器无法告知本地 DNS 服务器下一步需要访问哪个顶级域名服务器,就会使用递归查询;
如果根域名服务器能够告知 DNS 服务器下一步需要访问的顶级域名服务器,就会使用迭代查询。
-
-
-
从输入URL到返回响应的过程
- DNS域名解析—》TCP三次握手建立连接—》发起http请求—》服务端接受请求并作出响应—》浏览器收到响应并解析html代码—》TCP四次挥手断开连接—》浏览器渲染页面呈现给用户
-
1、获取输入的URL地址
- 2、浏览器会根据你输入的 URL 地址,去查找域名是否被本地 DNS 缓存,不同浏览器对 DNS 的设置不同,
- 如果浏览器缓存了你想访问的 URL 地址,那就直接返回 ip。
- 如果没有缓存你的 URL 地址,浏览器就会发起系统调用来查询本机
hosts
文件是否有配置 ip 地址,如果找到,直接返回。 - 如果找不到,就向网络中发起一个 DNS 查询。
- 如果没有缓存你的 URL 地址,浏览器就会发起系统调用来查询本机
- 3、浏览器需要和目标服务器建立 TCP 连接,需要经过三次握手的过程
- 4、在建立连接后,浏览器会向目标服务器发起
HTTP-GET
请求,HTTP 1.1 后默认使用长连接,包括其中的 URL,只需要一次握手即可多次传输数据。
-
5、如果目标服务器只是一个简单的页面,就会直接返回。但是对于某些大型网站的站点,往往不会直接返回主机名所在的页面,而会直接重定向。返回的状态码就不是 200 ,而是 301,302 以 3 开头的重定向码,浏览器在获取了重定向响应后,在响应报文中 Location 项找到重定向地址,浏览器重新第一步访问即可。
-
6、然后浏览器重新发送请求,携带新的 URL,返回状态码 200 OK,表示服务器可以响应请求,返回报文。
-
DNS域名解析:
-
浏览器搜索自己的浏览器本地DNS缓存,浏览器本地维护有一张户名和IP地址对应的表
-
未找到则搜索操作系统的DNS缓存,操作系统中也维护这么一张表
-
未找到则搜索操作系统的hosts文件,操作系统下也维护这么一张表在hosts文件里
-
未找到则到跟域名服务器、顶级域名服务器、权限域名服务器查找
-
消息请求从当前客户端上传到服务器需要用到IP协议、ARP协议、OSPF协议
-
HTTP
-
职责:
-
提高访问速度、加快对网络的浏览速度、作为防火墙、节省IP开销
-
HTTP是一种无状态协议,即服务器不保留与客户交易时的任何状态。这就大大减轻了服务器记忆负担,从而保持较快的响应速度。
HTTP是一种面向对象的协议。允许传送任意类型的数据对象。它通过数据类型和长度来标识所传送的数据内容和大小,并允许对数据进行压缩传送。
-
-
支持客户端、服务器端模式,简单快速,客户端向服务器端请求服务时,只需传送请求方法和路径,灵活,HTTP允许传输任意类型的数据对象,无连接,限制每次连接只处理一个请求,无状态,HTTP协议是无状态协议,指明协议对于事务处理没有记忆能力。
-
这是HTTP/1.0版的主要缺点,每个TCP连接只能发送一个请求,发送数据完毕后,连接就关闭了,如果还要请求就必须要新建一个请求连接。
-
HTTP1.1虽然是无状态协议,但是为了实现期望的保持状态功能,于是引入了Cookie技术,有了Cookie,和HTTP协议通信,就可以管理状态了。HTTP1.1版本是最流行的版本,可以持久连接,TCP连接默认不关闭,可以被多个请求复用,只有在一段时间内,没有请求,就可以自动关闭。
-
HTTP/1.1 采用了长连接的方式,这使得管道(pipeline)网络传输成为了可能。
即可在同一个 TCP 连接里面,客户端可以发起多个请求,只要第一个请求发出去了,不必等其回来,就可以发第二个请求出去,可以减少整体的响应时间。
-
HTTP消息结构
-
请求消息结构:一个请求消息是由请求行,请求头字段,一个空行和消息主体构成。消息主体是响应消息的承载数据。
-
服务端响应:
HTTP/1.1 200 OK Date: Tue, 10 Jul ... Content.Length: 362 Content.Type: text/html <html> ...
-
-
HTTP常见字段:
Content-Type
字段用于服务器回应时,告诉客户端,本次数据是什么格式。Connection
字段最常用于客户端要求服务器使用 TCP 持久连接,以便其他请求复用。- 服务器在返回数据时,会有
Content-Length
字段,表明本次回应的数据长度。 - Host:客户端发送请求时,用来指定服务器的域名。
Content-Encoding
字段说明数据的压缩方法。表示服务器返回的数据使用了什么压缩格式
-
HTTP工作原理:
-
HTTP1.0三种请求方法:GET、POST、HEAD(用于获取报头)。HTTP1.1新增5种方法:OPTION、PUT、DELETE、TRACE、CONNECT
- CONNECT:预留给能够将连接改为管道方式(长连接)的代理服务器。
- OPTIONS:允许客户端查看服务器性能
- TRACE:回显服务器收到的请求,用于测试和诊断
-
HTTP通信过程
-
HTTP过程中包含3个重要部分,请求消息头,响应头和状态码。
消息头中存放的信息是客户端告诉服务器能回传什么,就是客户端能接收的信息是什么类型的,如果客户端需要传值,则传值信息也会放在消息头中。
响应头中存放的信息是服务器告诉客户端返回的内容相关信息,包括回传内容的长度,内容和缓存的时间等。
状态码为服务器告诉客户端它的响应结果是什么。
-
-
状态码:
-
URL统一资源定位符:协议、IP地址、主机资源的具体地址
-
URI 统一资源标识符:访问资源的命名机制、存放资源主机名、资源自身的名称,由路径表示
-
GET和POST区别
-
get 方法一般用于请求,比如你在浏览器地址栏输入
www.cxuanblog.com
其实就是发送了一个 get 请求,它的主要特征是请求服务器返回资源,而 post 方法一般用于表单的提交,相当于是把信息提交给服务器,等待服务器作出响应,get 相当于一个是 pull/拉的操作,而 post 相当于是一个 push/推的操作。 -
get 方法是不安全的,因为你在发送请求的过程中,你的请求参数会拼在 URL 后面,从而导致容易被攻击者窃取,对你的信息造成破坏和伪造;而 post 方法是把参数放在请求体 body 中的,这对用户来说不可见。
-
get 请求的 URL 有长度限制,而 post 请求会把参数和值放在消息体中,对数据长度没有要求。
-
get 请求会被浏览器主动 cache,而 post 不会,除非手动设置。
-
get 请求在浏览器反复的
回退/前进
操作是无害的,而 post 操作会再次提交表单请求。 -
get 请求在发送过程中会产生一个 TCP 数据包;post 在发送过程中会产生两个 TCP 数据包。对于 get 方式的请求,浏览器会把 http header 和 data 一并发送出去,服务器响应 200(返回数据);而对于 post,浏览器先发送 header,服务器响应 100 continue,浏览器再发送 data,服务器响应 200 ok(返回数据)。
-
那么很明显 GET 方法就是安全且幂等的,因为它是「只读」操作,无论操作多少次,服务器上的数据都是安全的,且每次的结果都是相同的。
POST 因为是「新增或提交数据」的操作,会修改服务器上的资源,所以是不安全的,且多次提交数据就会创建多个资源,所以不是幂等的。
- 在 HTTP 协议里,所谓的「安全」是指请求方法不会「破坏」服务器上的资源。
- 所谓的「幂等」,意思是多次执行相同的操作,结果都是「相同」的。
-
-
解决HTTP无状态
无状态协议(Stateless Protocol)
就是指浏览器对于事务的处理没有记忆能力。- 1、使用cookie:
- 当你向服务端发送请求时,服务端会给你发送一个认证信息,服务器第一次接收到请求时,开辟了一块 Session 空间(创建了Session对象),同时生成一个 sessionId ,并通过响应头的 Set-Cookie:JSESSIONID=XXXXXXX 命令,向客户端发送要求设置 Cookie 的响应;客户端收到响应后,在本机客户端设置了一个 JSESSIONID=XXXXXXX 的 Cookie 信息,该 Cookie 的过期时间为浏览器会话结束;
- 接下来客户端每次向同一个网站发送请求时,请求头都会带上该 Cookie信息(包含 sessionId ), 然后,服务器通过读取请求头中的 Cookie 信息,获取名称为 JSESSIONID 的值,得到此次请求的 sessionId。这样,你的浏览器才具有了记忆能力。
- 2、JWT
- 还有一种方式是使用 JWT 机制,它也是能够让你的浏览器具有记忆能力的一种机制。与 Cookie 不同,JWT 是保存在客户端的信息,它广泛的应用于单点登录的情况。JWT 具有两个特点
- JWT 的 Cookie 信息存储在
客户端
,而不是服务端内存中。也就是说,JWT 直接本地进行验证就可以,验证完毕后,这个 Token 就会在 Session 中随请求一起发送到服务器,通过这种方式,可以节省服务器资源,并且 token 可以进行多次验证。 - JWT 支持跨域认证,Cookies 只能用在
单个节点的域
或者它的子域
中有效。如果它们尝试通过第三个节点访问,就会被禁止。使用 JWT 可以解决这个问题,使用 JWT 能够通过多个节点
进行用户认证,也就是我们常说的跨域认证
。
HTTPS
-
HTTP和HTTPS区别
- HTTPS(Hyper Text Transfer Protocol Secure),是一种基于SSL/TLS的HTTP,所有的HTTP数据都是在SSL/TLS协议封装之上进行传输的。
- HTTPS协议是在HTTP协议的基础上,添加了SSL/TLS握手以及数据加密传输,也属于应用层协议。所以,研究HTTPS协议原理,最终就是研究SSL/TLS协议。
- HTTPS 是安全的协议,它通过 密钥交换算法 - 签名算法 - 对称加密算法 - 摘要算法 能够解决上面这些问题。
- HTTP 的默认端口是 80,而 HTTPS 的默认端口是 443。
- HTTPS 协议需要向 CA(证书权威机构)申请数字证书,来保证服务器的身份是可信的。
-
加密
-
- 对称加密
对称加密指的就是加密和解密使用同一个秘钥,所以叫做对称加密。对称加密只有一个秘钥,作为私钥。
常见的对称加密算法:DES,AES,3DES等等。
-
DES
-
DES 加密算法是一种 分组密码,以 64 位为 分组对数据 加密,它的 密钥长度 是 56 位,加密解密 用 同一算法。
DES 加密算法是对 密钥 进行保密,而 公开算法,包括加密和解密算法。这样,只有掌握了和发送方 相同密钥 的人才能解读由 DES加密算法加密的密文数据。因此,破译 DES 加密算法实际上就是 搜索密钥的编码。对于 56 位长度的 密钥 来说,如果用 穷举法 来进行搜索的话,其运算次数为 2 ^ 56 次。
-
-
AES
-
AES 加密算法是密码学中的 高级加密标准,该加密算法采用 对称分组密码体制,密钥长度的最少支持为 128 位、 192 位、256 位,分组长度 128 位,算法应易于各种硬件和软件实现。这种加密算法是美国联邦政府采用的 区块加密标准。
AES 本身就是为了取代 DES 的,AES 具有更好的 安全性、效率 和 灵活性。
-
-
- 非对称加密
非对称加密指的是:加密和解密使用不同的秘钥,一把作为公开的公钥,另一把作为私钥。公钥加密的信息,只有私钥才能解密。私钥加密的信息,只有公钥才能解密。
常见的非对称加密算法:RSA,ECC
对称加密算法相比非对称加密算法来说,加解密的效率要高得多。但是缺陷在于对于秘钥的管理上,以及在非安全信道中通讯时,密钥交换的安全性不能保障。所以在实际的网络环境中,会将两者混合使用.
-
RSA
RSA
加密算法是目前最有影响力的 公钥加密算法,并且被普遍认为是目前 最优秀的公钥方案 之一。RSA
是第一个能同时用于 加密 和 数字签名 的算法,它能够 抵抗 到目前为止已知的 所有密码攻击,已被ISO
推荐为公钥数据加密标准。- 加密:
- 首先对明文进行比特串分组,使得每个分组对应的十进制数小于n,然后依次对每个分组m做一次加密,所有分组的密文构成的序列就是原始消息的加密结果,即m满足0<=m<n,则加密算法为:
c≡ m^e mod n; c为密文,且0<=c<n。
- 首先对明文进行比特串分组,使得每个分组对应的十进制数小于n,然后依次对每个分组m做一次加密,所有分组的密文构成的序列就是原始消息的加密结果,即m满足0<=m<n,则加密算法为:
- 解密:对于密文0<=c<n,解密算法为:m≡ c^d mod n;
-
-
HTTPS请求过程
-
实际上SSL/TLS协议的基本思路是非对称加密和对称加密结合来传输数据,一言以弊之,HTTPS是通过一次非对称加密算法(如RSA算法)进行了协商密钥的生成与交换,然后在后续通信过程中就使用协商密钥进行对称加密通信,之所以要使用这两种加密方式的原因在于非对称加密计算量较大,如果一直使用非对称加密来传输数据的话,会影响效率。
-
1.HTTPS请求
这个步骤是整个通信过程中的第一步,首先,客户端(通常是浏览器)先向服务器发出加密通信的请求,在这一步中,客户端主要向服务器提供以下信息:
- 支持的协议版本,比如TLS 1.0版
- 一个客户端生成的随机数RandomC,稍后用于生成“协商密钥”。
- 支持的加密方法,比如RSA公钥加密(非对称加密)。
- 支持的压缩方法。
-
2.服务器响应
服务器收到客户端请求后,向客户端发出回应,服务器的回应一般包含以下内容:
- 确认使用的加密通信协议版本,比如TLS 1.0版本。如果浏览器与服务器支持的版本不一致,服务器关闭加密通信。
- 一个服务器生成的随机数RandomS,稍后用于生成 协商密钥。
- 从客户端支持的加密方法中选择一个作为确认要使用的加密方法,比如RSA公钥加密。
- 服务器证书。
这个服务器证书就是表明服务器身份的东西,其中也包含了非对称加密中需要使用的公钥。
-
3.证书校验、生成密码、公钥加密
客户端收到服务器回应以后,首先验证服务器返回的证书。如果证书不是可信机构颁发,或者证书中的域名与实际域名不一致,或者证书已经过期,以浏览器为例客户端会向网页访问者显示一个警告,由其选择是否还要继续通信。 如果证书没有问题,客户端就会从证书中取出服务器的公钥。然后生成密码、公钥加密。
生成密码的过程会先产生一个随机数Pre-master key,该随机数是整个握手阶段出现的第三个随机数,稍后会经过公钥加密发送到服务端,有了它以后,客户端和服务器就同时有了三个随机数——RandomC,RandomS,Pre-master key,接着双方就用事先商定的加密方法,各自生成本次会话所用的同一把“协商密钥”。 -
4.加密信息C-S (发送加密数据)
加密信息是指上面一步生成的内容,主要包括
- 一个随机数Pre-master key。用于给服务端生成“协商密钥”。
- 编码改变通知,表示随后的信息都将用双方商定的加密方法和密钥发送。
- 客户端握手结束通知,表示客户端的握手阶段已经结束。这一项通常也是前面发送的所有内容的hash值,用来供服务器校验。
-
5.私钥解密、解密握手消息、验证Hash (接收加密数据并解密)
服务器收到客户端公钥加密的第三个随机数Pre-master key之后,通过自身私钥解密该数值并由之前的RandomC和RandomS计算生成本次会话所用的“会话密钥”。然后,通过约定的Hash算法验证客户端发送的数据完整性。
-
6.加密信息S-C
- 编码改变通知,表示随后的信息都将用双方商定的加密方法和密钥发送。
- 服务器握手结束通知,表示服务器的握手阶段已经结束。这一项同时也是前面发生的所有内容的hash值,用来供客户端校验。
-
7.解密握手消息、验证Hash
客户端解密并计算握手消息的HASH,如果与服务端发来的HASH一致,此时握手过程结束。
-
8.正常加密通信
握手成功之后,所有的通信数据将由之前协商密钥及约定好的算法进行加密解密。
-
-
HTTPS抓包
-
Charles本身是一个协议代理工具,如果只是普通的HTTP请求,因为数据本身没经过再次加密,因此作为代理可以知道所有客户端发送到服务端的请求内容以及服务端返回给客户端的数据内容,这也就是抓包工具能够将数据传输内容直接展现出来的原因。对于HTTPS请求,4,6,8步骤的数据都已经经过了加密,代理如果什么都不做的话是无法获取到其中的内容的。为了实现这个过程的数据获取,Charles需要做的事情是对客户端伪装服务端,对服务端伪装客户端,具体
- 截获真实客户端的HTTPS请求,伪装客户端向真实服务端发送HTTPS请求
- 接受真实服务器响应,用Charles自己的证书伪装服务端向真实客户端发送数据内容
一般情况下HTTPS中是客户端对服务端做证书校验,当然也有一些金融机构会有用户证书作为提供给服务端做用户认证的工具,保证发出请求的的确是这部分授权用户。我们仅分析客户端对服务单做证书校验的这种。Android有自己的一套HTTPS通信调用方式,以HttpsURLConnection为例
上面这段代码就是一个https请求的样例,这种方法的特点是证书校验工作交由系统处理,系统只会允许可信CA签发的数字证书能够访问,私有CA签发的数字证书(比如12306以及我们上文说的Charles证书)是无法访问的。
那么如何绕过呢,- 第一种方法是修改Https通信代码,这种只对开发者开发应用的时候好使,我们需要实现X509TrustManager接口去做自己的一套证书校验,它并不通用,尤其是对于我们抓包而言是不可行的,因为我们没法去修改别人应用中的代码。
- 第二种方法是将私有CA签发的数字证书安装到手机中并且作为受信任证书保存,这种方式是我们推荐的方式,唯一的缺点是你的手机上可能会在通知栏一直留着一个特殊标志,告诉你网络可能被监控。
-
-
HTTPS加密过程
- 混合加密的方式实现信息的机密性,解决了窃听的风险。
- HTTPS 采用的是对称加密和非对称加密结合的「混合加密」方式:
- 在通信建立前采用非对称加密的方式交换「会话秘钥」(对称加密密钥),后续就不再使用非对称加密。
- 在通信过程中全部使用对称加密的「会话秘钥」的方式加密明文数据。
- HTTPS 采用的是对称加密和非对称加密结合的「混合加密」方式:
- 摘要算法(如MD5)的方式来实现完整性,它能够为数据生成独一无二的「指纹」,指纹用于校验数据的完整性,解决了篡改的风险。
- 客户端在发送明文之前会通过摘要算法算出明文的「指纹」,发送的时候把「指纹 + 明文」一同加密成密文后,发送给服务器,服务器解密后,用相同的摘要算法算出发送过来的明文,通过比较客户端携带的「指纹」和当前算出的「指纹」做比较,若「指纹」相同,说明数据是完整的。
- 将服务器公钥放入到数字证书中,解决了冒充的风险。
- 客户端先向服务器端索要公钥,然后用公钥加密信息,服务器收到密文后,用自己的私钥解密。
- 所以这里就需要借助第三方权威机构
CA
(数字证书认证机构),将服务器公钥放在数字证书(由数字证书认证机构颁发)中,只要证书是可信的,公钥就是可信的。
- 混合加密的方式实现信息的机密性,解决了窃听的风险。
-
HTTPS安全原理
-
TLS 旨在为 Internet 提供通信安全的加密协议。TLS 握手是启动和使用 TLS 加密的通信会话的过程。在 TLS 握手期间,Internet 中的通信双方会彼此交换信息,验证密码套件,交换会话密钥。
每当用户通过 HTTPS 导航到具体的网站并发送请求时,就会进行 TLS 握手。除此之外,每当其他任何通信使用 HTTPS(包括 API 调用和在 HTTPS 上查询 DNS)时,也会发生 TLS 握手。
TLS 具体的握手过程会根据所使用的
密钥交换算法的类型
和双方支持的密码套件
的不同而不同。我们以RSA 非对称加密
来讨论这个过程。整个 TLS 通信流程图如下 -
-
在进行通信前,首先会进行 HTTP 的三次握手,握手完成后,再进行 TLS 的握手过程
-
ClientHello:客户端通过向服务器发送
hello
消息来发起握手过程。这个消息中会夹带着客户端支持的TLS 版本号(TLS1.0 、TLS1.2、TLS1.3)
、客户端支持的密码套件(如RSA非对称加密算法)、以及一串客户端随机数
(用于给服务端生成“协商密钥”)。 -
ServerHello:在客户端发送 hello 消息后,服务器会发送一条消息,这条消息包含了服务器的 SSL 证书、服务器选择的密码套件和服务器生成的随机数。(用于生成“协商密钥”)
-
认证(Authentication):客户端的证书颁发机构CA会认证 SSL 证书,然后服务端发送
Certificate
报文,报文中包含公开密钥证书。最后服务器发送ServerHelloDone
作为hello
请求的响应。第一部分握手阶段结束。 -
加密阶段
:在第一个阶段握手完成后,客户端会发送ClientKeyExchange
作为响应,这个响应中包含了一种称为The premaster secret
的密钥字符串,这个字符串就是使用上面公开密钥证书进行加密的字符串。随后客户端会发送ChangeCipherSpec
,告诉服务端使用私钥解密这个premaster secret
的字符串,然后客户端发送Finished
告诉服务端自己发送完成了。
Session key 其实就是用公钥证书加密的公钥。
实现了安全的非对称加密
:然后,服务器再发送ChangeCipherSpec
和Finished
告诉客户端解密完成,至此实现了 RSA 的非对称加密。- TLS握手成功之后,所有的通信数据将由之前协商密钥及约定好的算法(对称加密)进行加密解密。
-
TCP
-
传输控制协议。它能够帮助你确定计算机连接到 Internet 以及它们之间的数据传输。通过三次握手来建立 TCP 连接,三次握手就是用来启动和确认 TCP 连接的过程。一旦连接建立后,就可以发送数据了,当数据传输完成后,会通过关闭虚拟电路来断开连接。
-
TCP头部格式:
-
TCP 的主要特点有
- TCP 能够确保连接的建立和数据包的发送
- TCP 支持错误重传机制
- TCP 支持拥塞控制,流量控制、能够在网络拥堵的情况下延迟发送
- TCP 能够提供错误校验和,去除有害的数据包。
-
TCP/IP模型
-
网络带宽网速计算,10m带宽的实际下载速度
答:实际下载速度=带宽/8,这是理论上的值。所以10M的带宽的下载速度是 10M/8=1.25M/S,也就是最大下载速度1.25MB
-
tcp和udp区别:
- TCP 是一种可靠的协议,它能够保证数据包的可靠性交付,TCP 能够正确处理传输过程中的丢包、传输顺序错乱等异常情况。此外,TCP 还提供拥塞控制用于缓解网络拥堵。
- UDP 是一种不可靠的协议,它无法保证数据的可靠交付,相比 TCP ,UDP 不会检查数据包是否到达、网络是否阻塞等情况,但是 UDP 的效率比较高。UDP 常用于分组数据较少或者广播、多播等视频通信和多媒体领域。
-
TCP半连接队列和全连接队列
- 在 TCP 三次握手的时候,Linux 内核会维护两个队列,分别是:
- 半连接队列,也称 SYN 队列;
- 全连接队列,也称 accepet 队列;
- 服务端收到客户端发起的 SYN 请求后,内核会把该连接存储到半连接队列,并向客户端响应 SYN+ACK,接着客户端会返回 ACK,服务端收到第三次握手的 ACK 后,内核会把连接从半连接队列移除,然后创建新的完全的连接,并将其添加到 accept 队列 (全连接队列),等待进程调用 accept 函数时把连接取出来。
- 不管是半连接队列还是全连接队列,都有最大长度限制,超过限制时,内核会直接丢弃,或返回 RST 包。
- 在服务端可以使用
ss
命令,来查看 TCP 全连接队列的情况 - TCP全连接队列溢出:当服务端并发处理大量请求时,如果 TCP 全连接队列过小,就容易溢出。发生 TCP 全连接队溢出的时候,后续的请求就会被丢弃,这样就会出现服务端请求数量上不去的现象。
- 在 TCP 三次握手的时候,Linux 内核会维护两个队列,分别是:
-
tcp三次握手
- SYN:它的全称是
Synchronize Sequence Numbers
,同步序列编号。是 TCP/IP 建立连接时使用的握手信号。在客户机和服务器之间建立 TCP 连接时,首先会发送的一个信号。客户端发送 SYN 消息时,就会在自己的段内生成一个随机值 X。此时客户端为半打开状态syn_sent - SYN-ACK:服务器收到 SYN 后,打开客户端连接,发送一个 SYN-ACK 作为答复。确认号ACK设置为比接收到的序列号多一个,即 X + 1,服务器为数据包选择的序列号是另一个随机数 Y。此时客户端进入了 established状态,服务端进入半打开状态syn_rcvd
- ACK:
Acknowledge character
, 确认字符,表示发来的数据已确认接收无误。最后,客户端将 ACK 发送给服务器。序列号被设置为所接收的确认值即 Y + 1。此时客户端也进入了 established 状态
- SYN:它的全称是
-
优化TCP三次握手策略:
-
TCP四次挥手
- 首先,客户端应用程序决定要终止连接(这里服务端也可以选择断开连接)。这会使客户端将 FIN 发送到服务器,并进入
FIN_WAIT_1
状态。当客户端处于 FIN_WAIT_1 状态时,它会等待来自服务器的 ACK 响应。 - 然后第二步,当服务器收到 FIN 消息时,服务器会立刻向客户端发送 ACK 确认消息。
- 当客户端收到服务器发送的 ACK 响应后,客户端就进入
FIN_WAIT_2
状态,然后等待来自服务器的FIN
消息 - 服务器发送 ACK 确认消息后,一段时间(可以进行关闭后)会发送 FIN 消息给客户端,告知客户端可以进行关闭。
- 当客户端收到从服务端发送的 FIN 消息时,客户端就会由 FIN_WAIT_2 状态变为
TIME_WAIT
状态。处于 TIME_WAIT 状态的客户端允许重新发送 ACK 到服务器为了防止信息丢失。客户端在 TIME_WAIT 状态下花费的时间取决于它的实现,在等待一段时间后,连接关闭,客户端上所有的资源(包括端口号和缓冲区数据)都被释放。
-
Linux查看TCP/UDP
-
netstat -nt --->>>查看tcp连接
-
netstat -nua --->>>查看udp连接
-
测试tcp监听端口连通性:
telnet <host> <port>
-
测试目标udp端口连通性:
nc -vuz <host> <port>
-
1、查看TCP和UDP端口的监听状态
cat /proc/net/tcp
cat /proc/net/udp
2、查看进程id对应的进程名称,如10002id
busybox ps | grep 10002
-
-
TCP数据传输
- 「重传」和「去重」工作操作系统的网络内核模块都已经帮我们处理好了,用户层是不用关心的。
- 数据传输优化策略:
-
TCP通过序列号与确认应答实现可靠传输
-
重传机制:超时重传、快速重传、SACK、D-SACK
-
超时重传
- 就是在发送数据时,设定一个定时器,当超过指定的时间后,没有收到对方的
ACK
确认应答报文,就会重发该数据,也就是我们常说的超时重传。 - 两种情况发生:数据包丢失、确认应答丢失
- 超时重传时间 RTO 的值应该略大于报文往返时间 RTT 的值。
- 就是在发送数据时,设定一个定时器,当超过指定的时间后,没有收到对方的
-
快速重传
- 它不以时间为驱动,而是以数据驱动重传。
- 快速重传的工作方式是当收到三个相同的 ACK 报文时,会在定时器过期之前,重传丢失的报文段
- 快速重传机制只解决了一个问题,就是超时时间的问题,但是它依然面临着另外一个问题。就是重传的时候,是重传之前的一个,还是重传所有的问题。为了解决不知道该重传哪些 TCP 报文,于是就有
SACK
方法。
-
SACK 选择性确认
- 这种方式需要在 TCP 头部「选项」字段里加一个
SACK
的东西,它可以将缓存的map发送给发送方,这样发送方就可以知道哪些数据收到了,哪些数据没收到,知道了这些信息,就可以只重传丢失的数据。 - 如果要支持
SACK
,必须双方都要支持。在 Linux 下,可以通过net.ipv4.tcp_sack
参数打开这个功能(Linux 2.4 后默认打开)。
- 这种方式需要在 TCP 头部「选项」字段里加一个
-
D-SACK
- 主要使用了 SACK 来告诉「发送方」有哪些数据被重复接收了。
- 可以让「发送方」知道,是发出去的包丢了,还是接收方回应的 ACK 包丢了;
- 可以知道是不是「发送方」的数据包被网络延迟了;
- 可以知道网络中是不是把「发送方」的数据包给复制了;
- 在 Linux 下可以通过
net.ipv4.tcp_dsack
参数开启/关闭这个功能(Linux 2.4 后默认打开)。
-
-
滑动窗口
-
解决的问题:数据包的往返时间越长,通信的效率就越低。
-
那么有了窗口,就可以指定窗口大小,窗口大小就是指无需等待确认应答,而可以继续发送数据的最大值。
-
窗口的实现实际上是操作系统开辟的一个缓存空间,发送方主机在等到确认应答返回之前,必须在缓冲区中保留已发送的数据。如果按期收到确认应答,此时数据就可以从缓存区清除。
-
ACK 600 确认应答报文丢失,也没关系,因为可以通话下一个确认应答进行确认,只要发送方收到了 ACK 700 确认应答,就意味着 700 之前的所有数据「接收方」都收到了。这个模式就叫累计确认或者累计应答。
-
TCP 头里有一个字段叫
Window
,也就是窗口大小。这个字段是接收端告诉发送端自己还有多少缓冲区可以接收数据。于是发送端就可以根据这个接收端的处理能力来发送数据,而不会导致接收端处理不过来。所以,通常窗口的大小是由接收方的决定的。
-
发送方发送的数据大小不能超过接收方的窗口大小,否则接收方就无法正常接收到数据。
-
发送方的滑动窗口,大小计算:可用窗口大小 = SND.WND -(SND.NXT - SND.UNA)
-
接收方滑动窗口:接收窗口的大小是约等于发送窗口的大小的。
-
因为滑动窗口并不是一成不变的。比如,当接收方的应用进程读取数据的速度非常快的话,这样的话接收窗口可以很快的就空缺出来。那么新的接收窗口大小,是通过 TCP 报文中的 Windows 字段来告诉发送方。那么这个传输过程是存在时延的,所以接收窗口和发送窗口是约等于的关系。
-
-
流量控制:
- TCP 提供一种机制可以让「发送方」根据「接收方」的实际接收能力控制发送的数据量,这就是所谓的流量控制。通过滑动窗口实现
-
操作系统缓冲区与滑动窗口关系
- 前面的流量控制例子,我们假定了发送窗口和接收窗口是不变的,但是实际上,发送窗口和接收窗口中所存放的字节数,都是放在操作系统内存缓冲区中的,而操作系统的缓冲区,会被操作系统调整。
- 如果发生了先减少缓存,再收缩窗口,就会出现丢包的现象。
- 为了防止这种情况发生,TCP 规定是不允许同时减少缓存又收缩窗口的,而是采用先收缩窗口,过段时间再减少缓存,这样就可以避免了丢包情况。
-
窗口关闭
- TCP 通过让接收方指明希望从发送方接收的数据大小(窗口大小)来进行流量控制。
- 如果窗口大小为 0 时,就会阻止发送方给接收方传递数据,直到窗口变为非 0 为止,这就是窗口关闭。
- 问题:接收方向发送方通告窗口大小时,是通过
ACK
报文来通告的。当发生窗口关闭时,接收方处理完数据后,会向发送方通告一个窗口非 0 的 ACK 报文,如果这个通告窗口的 ACK 报文在网络中丢失了,出现死锁 - 解决窗口关闭出现的死锁问题:TCP 为每个连接设有一个持续定时器,只要 TCP 连接一方收到对方的零窗口通知,就启动持续计时器。如果持续计时器超时,就会发送窗口探测 ( Window probe ) 报文,而对方在确认这个探测报文时,给出自己现在的接收窗口大小。
-
拥塞控制
-
前面的流量控制是避免「发送方」的数据填满「接收方」的缓存,但是并不知道网络的中发生了什么。
-
在网络出现拥堵时,如果继续发送大量数据包,可能会导致数据包时延、丢失等,这时 TCP 就会重传数据,但是一重传就会导致网络的负担更重,于是会导致更大的延迟以及更多的丢包,这个情况就会进入恶性循环被不断地放大….
-
所以,TCP 不能忽略网络上发生的事,它被设计成一个无私的协议,当网络发送拥塞时,TCP 会自我牺牲,降低发送的数据量。
-
有了拥塞控制,控制的目的就是避免「发送方」的数据填满整个网络。为了在「发送方」调节所要发送数据的量,定义了一个叫做「拥塞窗口」的概念。
-
拥塞窗口 cwnd是发送方维护的一个 的状态变量,它会根据网络的拥塞程度动态变化的。
-
发送窗口的值是swnd = min(cwnd, rwnd),也就是拥塞窗口和接收窗口中的最小值。
-
拥塞窗口cwnd规则:
- 只要网络中没有出现拥塞,
cwnd
就会增大; - 但网络中出现了拥塞,
cwnd
就减少;
- 只要网络中没有出现拥塞,
-
其实只要「发送方」没有在规定时间内接收到 ACK 应答报文,也就是发生了超时重传,就会认为网络出现了拥塞。
-
拥塞控制算法:慢启动、拥塞避免、拥塞发生、快速恢复
-
慢启动:
- 当发送方每收到一个 ACK,拥塞窗口 cwnd 的大小就会加 1。发包的个数是指数性的增长。
- 有一个叫慢启动门限
ssthresh
(slow start threshold)状态变量。一般来说ssthresh
的大小是65535
字节。- 当
cwnd < ssthresh
时,使用慢启动算法。 - 当
cwnd >= ssthresh
时,就会使用「拥塞避免算法」。
- 当
-
拥塞避免算法
-
规则:每当收到一个 ACK 时,cwnd 增加 1/cwnd。即线性增长
-
就这么一直增长着后,网络就会慢慢进入了拥塞的状况了,于是就会出现丢包现象,这时就需要对丢失的数据包进行重传。
当触发了重传机制,也就进入了「拥塞发生算法」。
-
-
拥塞发生:
- 当网络出现拥塞,也就是会发生数据包重传
- 发生超时重传的拥塞发生算法,sshresh 和 cwnd 的值会发生变化:
ssthresh
设为cwnd/2
,cwnd重置为
1 - 快速恢复:发生快速重传的拥塞发生算法,
cwnd = cwnd/2
,也就是设置为原来的一半;ssthresh = cwnd
;- 发生快速恢复后,
cwnd = ssthresh + 3
- 发生快速恢复后,
-
-
TCP粘包
- 原因:
- Tcp是个“流协议”,所谓流,就是没有界限的一连串数据,没有界限。TCP底层不了解业务数据的含义,它会根据TCP缓冲区的实际情况进行包的划分,所以业务上认为,一个完整的包可能被TCP拆分为多个包进行发送,也可能把多个小包封装成一个大的数据包进行发送,这就是所谓的TCP粘包和拆包问题。
- 应用程序write写入的字节大小大于套接口缓冲区的大小
- 进行MSS(最大报文段长度)大小的TCP分段
- 以太网帧的payload大于MTU进行IP分片
- 解决:
- 由于底层无法理解上层的业务数据,所以底层是无法保证数据不被拆分和重组的。只能通过设计上层的协议栈来解决,业界的方案可归纳如下:
- 消息定长,例如每个报文固定200字节,如果不够,空位补空格
- 在包尾增加回车换行符进行分割,如FTP协议
- 将消息分为消息头和消息体,消息头中包含消息的长度,字段等信息
- 更复杂的应用层协议,如Netty通过 ByteToMessageDecoder 和 MessageToMessageDecoder 接口解决
- 原因:
UDP
- 用户数据报协议。它不需要所谓的
握手
操作,从而加快了通信速度,允许网络上的其他主机在接收方同意通信之前进行数据传输。数据报是与分组交换网络关联的传输单元。 - UDP 的特点主要有
- UDP 能够支持容忍数据包丢失的带宽密集型应用程序,如音频、视频、大文件数据等
- UDP 具有低延迟的特点
- UDP 能够发送大量的数据包
- UDP 能够允许 DNS 查找,DNS 是建立在 UDP 之上的应用层协议。