输入URL到返回页面的全过程 #
- 根据域名,进行DNS域名解析
- 检查浏览器缓存、操作系统缓存、路由器缓存、ISP 缓存
- DNS 查询、ARP 请求
- 拿到解析的IP地址,建立 TCP 连接
- 向 IP 地址发送 HTTP 请求
- 服务器处理请求
- 返回相应结果
- 关闭 TCP 连接
- 浏览器解析 HTML
- 浏览器布局渲染
OSI 七层模型 #
OSI中的层 | 功能 | TCP/IP协议族 |
---|---|---|
应用层 | 文件传输,电子邮件,文件服务,虚拟终端 | TFTP,HTTP,SNMP,FTP,SMTP,DNS,Telnet |
表示层 | 数据格式化,代码转换,数据加密 | 没有协议 |
会话层 | 解除或建立与别的接点的联系 | 没有协议 |
传输层 | 提供端对端的接口 | TCP,UDP |
网络层 | 为数据包选择路由 | IP,ICMP,RIP,OSPF,BGP,IGMP |
数据链路层 | 传输有地址的帧以及错误检测功能 | SLIP,CSLIP,PPP,ARP,RARP,MTU |
物理层 | 以二进制数据形式在物理媒体上传输数据 | ISO2110,IEEE802,IEEE802.2 |
报文长度 #
ip 报文
MTU:最大传输单元。以太网(Ethernet)数据帧的长度必须在 46-1500 字节之间,这是由以太网的物理特性决定的。
这个 1500 字节被称为链路层的 MTU(最大传输单元)。MTU 指的是链路层的数据区,并不包括链路层的首部和尾部的 18 个字节.
所以,事实上,这个 1500 字节就是网络层 IP 数据报的长度限制。
IP 数据报的首部为 20 字节,所以 IP 数据报的数据区长度最大为 1480 字节。
当 IP 数据报长度大于 MTU 时,ip 层就会进行分片,接收方对数据报进行重组
由于 UDP 特性,当一片数据丢失时,会丢弃整个数据报
因此在普通局域网环境下,应尽量避免分片
UDP 包最大数据长度:
IP 数据包长度字段限制为 16 bit,可表示最大值为 2^16^ - 1 = 64KB - 1 = 65535
UDP 数据包没有序列号确认号等字段,不能进行分片
UDP 包头占 8 字节,ip 包头占 20 字节,65535 - 28 = 65507
当需要发送的 udp 报文大于 65507 时需要在应用层分片
TCP:
MSS:最大分解大小,为每次 TCP 数据包每次传输的最大数据的分段大小
TCP #
- TCP 提供一种面向连接的、可靠的字节流服务
- 在一个 TCP 连接中,仅有两方进行彼此通信。广播和多播不能用于 TCP
- TCP 使用校验和,确认和重传机制来保证可靠传输
- TCP 给数据分节进行排序,并使用累积确认保证数据的顺序不变和非重复
- TCP 使用滑动窗口机制来实现流量控制,通过动态改变窗口的大小进行拥塞控制
- UDP 首部 8 字节,TCP 首部最小 20 字节, 最大 60 字节
重置报文段(RST) #
一个将 RST 字段置为的报文段被称为"重置“报文段。 当发现一个达到的报文段对于相关连接而言是不正确的时,TCP 会发送一个重置报文段,一般表示异常关闭连接。 在任何时刻,我们可以通过发送一个重置报文段替代 FIN 来终止一条连接,这种方式被称为终止释放。 终止释放可以为应用程序提供以下两个属性:1. 任何排队的数据都将被抛弃,一个重置报文段会被立即发送出去。2. 重置报文段的接收方会说明通信另一段采用了终止的方式,而不是一次正常关闭。
三次握手 #
- Client将标志位 SYN 置为 1(表示要发起一个连接),随机产生一个值 seq = J,并将该数据包发送给 Server,Client 进入 SYN_SENT 状态,等待 Server 确认。
- Server 收到数据包后由标志位 SYN=1 知道 Client 请求建立连接,Server 将标志位 SYN 和 ACK 都置为 1,ack=J+1,随机产生一个值 seq=K,并将该数据包发送给 Client 以确认连接请求,Server 进入 SYN_RCVD 态。
- Client 收到确认后,检查 ack 是否为 J+1,ACK 是否为 1,如果正确则将标志位 ACK 置为 1,ack=K+1,并将该数据包发送给 Server,Server 检查 ack 是否为 K+1,ACK 是否为 1,如果正确则连接建立成功,Client 和 Server 进入 ESTABLISHED 状态,完成三次握手,随后 Client 与 Server 之间可以开始传输数据了。(如果 B 未收到 A 的 ACK,会一直超时重传,直到收到 A 的 ACK)
为什么不能两次握手
如果只是两次握手, 至多只有连接发起方的起始序列号能被确认, 另一方选择的序列号则得不到确认
如果 A 发送了 SYN,超时重传,此时
网络编程函数 #
- 客户端调用 connect() 函数,此时客户端会向服务端发送 SYN
- 服务端收到 SYN 后,会从 listen() 函数返回 SYN + ACK
- 客户端收到 connect() 函数的返回,之后向服务端发送最后一个 ACK
- 服务端收到最后一个 ACK 以后,将该连接请求从未完成连接队列放入已完成连接队列中,等待 accept() 从该队列中取出
四次挥手 #

- 数据传输结束后,A和B都处于 ESTABLISHED 状态
- A发送连接释放报文段,并停止发送数据,主动关闭 TCP 连接。将 FIN 标识位置为 1,其序号为 seq = u,等于前面传送过的数据最后一个字节序号 + 1,A 进入 FIN_WAIT_1 状态,等待B的确认(FIN即使不携带数据也要占用一个序号)
- B收到释放报文段后即发出确认,ack = u + 1,序号 seq = v,等于B前面传送过数据的最后一个序号 + 1,B进入 CLOSE_WAIT 状态。此时服务器通知高层进程,从A到B方向的连接释放,此时 TCP 连接处于半关闭状态,A 没有数据发送,但 B 若发送数据,A 仍要接受,也就是说从 B 到 A 方向连接未关闭。
- A 收到 B 的确认后,进入 FIN_WAIT_2 状态,等待 B 发送连接释放报文段
- 若 B 已经没有要向 A 发送的数据,其应用进程通知 TCP 释放连接。B 将报文 FIN 置为 1,假定 B 的序号为 w(半关闭状态B可能又发送了一些数据)ack = u + 1,B 进入 LAST_ACK 状态,等待 A 的确认
- A收到B的释放报文段,将 ACK 置为1,ack = w + 1,seq = u + 1。进入 TIME_WAIT 状态,TCP 连接还未释放掉,必须经过时间等待计时器设置的时间 2MSL(MSL:最长报文段寿命)最后 A 进入 CLOSED 状态
为什么是四次
- 关闭连接时,客户端向服务端发送 FIN 时,仅仅表示客户端不再发送数据了但是还能接收数据。
- 服务器收到客户端的 FIN 报文时,先回一个 ACK 应答报文,而服务端可能还有数据需要处理和发送,等服务端不再发送数据时,才发送 FIN 报文给客户端来表示同意现在关闭连接。
从上面过程可知,服务端通常需要等待完成数据的发送和处理,所以服务端的 ACK 和 FIN 一般都会分开发送,从而比三次握手导致多了一次。
为什么 TIME_WAIT 等待时间 2MSL
网络中可能存在来自发送方的数据包,当这些发送方的数据包被接收方处理后又会向对方发送响应,所以一来一回需要等待 2 倍的时间。
为什么会 TIME_WAIT
-
防止具有相同四元组的旧数据包被收到
经过 2MSL 这个时间,足以让两个方向上的数据包都被丢弃,使得原来连接的数据包在网络中都自然消失,再出现的数据包一定都是新建立连接所产生的
-
保证连接的正确关闭
客户端四次挥手的最后一个 ACK 报文如果在网络中被丢失了,此时如果客户端 TIME-WAIT 过短或没有,则就直接进入了 CLOSE 状态了,那么服务端则会一直处在 LAST-ACK 状态。当客户端发起建立连接的 SYN 请求报文后,服务端会发送 RST 报文给客户端,连接建立的过程就会被终止。
如果 TIME-WAIT 等待足够长的情况就会遇到两种情况:
- 服务端正常收到四次挥手的最后一个 ACK 报文,则服务端正常关闭连接。
- 服务端没有收到四次挥手的最后一个 ACK 报文时,则会重发 FIN 关闭连接报文并等待新的 ACK 报文。
过多 TIME_WAIT 的危害
- 内存资源占用
- 对端口资源的占用,一个 TCP 连接占用一个本地端口
过多 CLOSE_WAIT
序列号回绕 #
传入无符号数字,相减后变为有符号数字,如果发生回绕则相减后为负数
滑动窗口 #
在三次握手阶段,双方互相将自己的最大可接收的数据量告诉对方,也就是自己的数据接收缓冲池的大小。这样对方可以根据已发送的数据量来计算是否可以接着发送。在处理过程中,当接收缓冲池的大小发生变化时,要给对方发送更新窗口大小的通知,利用滑动窗口机制有效提高通信效率。
拥塞避免 #
慢启动+拥塞窗口避免(加法增大,乘法减小,拥塞窗口缓慢增大,拥塞后迅速减小)
- 开始时使用小的拥塞窗口,因为不知道网络状况,大量数据可能造成网络瘫痪,逐渐增加拥塞窗口,每收到一个 ack 就 + 1,此时拥塞窗口指数增长,当超出慢启动门限时,进入拥塞避免算法。
- 拥塞窗口大于慢启动门限时,发送拥塞窗口大小的报文后收到确认就将拥塞窗口 + 1,此时线性规律增长
- 无论是在慢启动阶段,还是在拥塞避免阶段,只要发送方判断网络出现拥塞(依据就是没有按照收到确认,超时重传),就要把 ssthresh(慢启动门限) 设置为出现拥塞时的 cwnd(拥塞窗口) 值的一半
- 在更新了 ssthresh 后,同时将 cwnd 重新设置为 1,又开始执行慢启动算法。这样做的目的是要迅速减少主机发送到网络中的分组数,使得发生拥塞的中间设备有足够的时间把缓冲区中积压的分组处理完毕。
快重传+快回复
快重传
- 快重传算法首先要求接收方每收到一个**失序的报文(就是不是连续的报文,出现有序号缺失的报文)**段就立即发出重复确认(为的是使发送方及早知道有报文段没有到达对方),然后若是发送方接收到 3 个重复确认 ACK,则启动快重传算法。==重复确认失序报文==
- 发送方只要一连收到 3 个重复确认就应当立即重传对方尚未收到的报文段,而不必继续等到该报文段设置的重传计时器 RTO 到期==立即重传丢失报文==
快恢复
- 一旦发生超时重传,或收到三个重复的 ack 时,TCP 会把慢启动门限设置为拥塞窗口 cwnd 的一半,同时 cwnd = ssthresh
TCP 定时器 #
-
重传计时器:Retransmission Timer:为了控制丢失的报文段或丢弃的报文段,也就是对报文段确认的等待时间。当 TCP 发送报文段时,就创建这个特定报文段的重传计时器,可能发生两种情况:若在计时器超时之前收到对报文段的确认,则撤销计时器;若在收到对特定报文段的确认之前计时器超时,则重传该报文,并把计时器复位;
-
坚持计时器:Persistent Timer:专门为对付零窗口通知而设立的。当发送端收到零窗口的确认时,就启动坚持计时器,当坚持计时器截止期到时,发送端 TCP 就发送一个特殊的报文段,叫探测报文段,这个报文段只有一个字节的数据。探测报文段有序号,但序号永远不需要确认,甚至在计算对其他部分数据的确认时这个序号也被忽略。探测报文段提醒接收端 TCP,确认已丢失,必须重传。
-
保活计时器:Keeplive Timer:每当服务器收到客户的信息,就将 keep live timer 复位,超时通常设置 2 小时,若服务器超过 2 小时还没有收到来自客户的信息,就发送探测报文段,若发送了 10 个探测报文段(每 75 秒发送一个)还没收到响应,则终止连接。
-
时间等待计时器:Time_Wait Timer:在连接终止期使用,当 TCP 关闭连接时,并不认为这个连接就真正关闭了,在时间等待期间,连接还处于一种中间过度状态。这样就可以时重复的fin报文段在到达终点后被丢弃,这个计时器的值通常设置为一格报文段寿命期望值的两倍。
零窗死锁 #
零窗死锁:当接收端向发送端发送零窗口报文段后不久,接收端的接收缓存又有了一些存储空间,于是接收端向发送端发送了 Windows size = 2 的报文段,然而这个报文段在传输过程中丢失了。发送端一直等待收到接收端发送的非零窗口的通知,而接收端一直等待发送端发送数据,这样就死锁了。
解决办法:TCP 为每个连接设有一个持续计时器。只要 TCP 连接的一方收到对方的零窗口通知,就启动持续计时器,若持续计时器设置的时间到期,就发送一个零窗口探测报文段(仅携带 1 字节的数据),而对方就在确认这个探测报文段时给出了现在的窗口值。
连接队列 #
如果有多个连接请求到达,TCP 如何处理
此时连接可能有下述两种状态
- 连接尚未完成,但是已经接收到 SYN,即处于 SYN_RCVD 状态
- 已经完成三次握手,并且处于 ESTABLISHED 状态,但是还未被应用程序接受
操作系统通常使用两个不同的连接队列来处理上述两个过程
- 当一个连接请求到达时,将会检查系统范围内的参数
net.ipv4.tcp_max_syn_backlog
(默认为1000),如果 SYN_RCVD 状态的连接数目超过了这一个阈值,进入的连接将会被拒绝。 - 每个处于监听状态下的连接,但是未被应用程序接受,这称为未完成连接(backlog)。backlog 的数目必须在0 ~ net.core.smaxconn 之间,net.core.smaxconnn 默认为128.
- 如果监听节点的队列中仍有空间分配给新的连接,TCP 模块会应答 SYN 并完成连接。
- 如果队列中没有足够的空间分配给新的连接,那么 TCP 将会延迟对 SYN 做出响应。
TCP 保活机制 #
是由保活计数器来实现的,当计时器被触发,连接一端将发送一个保活探测报文,另一端接收报文的同时,也会发送一个 ACK 作为响应.
粘包问题 #
TCP粘包是指发送方发送的若干包数据到接收方时粘成一包,从接受缓冲区来看,后一包的数据的头紧接着前一包数据尾.
造成原因:
- 连接复用:一条连接可以供一台主机上的多个进程使用,边界分割出现问题
- Nagle 算法
- 数据包过大
- 流量控制、拥塞控制
- 接收方不及时接收缓冲区的包
解决:
- 尾部标记序列:通过特殊标志符表示数据包的边界
- 头部标记分布接收,在 TCP 的头部加上表示数据长度
- 应用层发送数据定长发送
如何保证可靠传输 #
- 应用数据被分割成 TCP 认为最适合发送的数据块
- TCP 给发送的每一个包进行编号,接受方对数据包进行排序,把有序数据传送给应用层
- **校验和:**TCP 将保持它首部和数据的校验和。端到端的校验和,目的是监测数据在传输过程中的任何变化。如果收到段的校验和有差错,TCP 将丢弃这个报文段和不确认收到此报文段
- 接收端会丢弃重复数据
- **流量控制:**TCP 连接的每一方都有固定大小的缓冲空间,TCP 的接收端只允许发送端发送接收端缓冲区能接纳的数据。当接收方来不及处理发送方的数据,能提示发送方降低发送的速率,防止包丢失。TCP 使用的流量控制协议是可变大小的滑动窗口协议
- **拥塞控制:**当网络拥塞时,减少数据的发送
- **停止等待协议:**每发完一个分组就停止发送,等待对方确认,在收到确认后再发下一个分组。**超时重传:**当 TCP 发出一个段后,启动一个定时器,等待目的端口确认收到这个报文段。如果不能及时收到一个确认,将重发这个报文段
DDos攻击 #
客户端向服务端发送请求链接数据包,服务端向客户端发送确认数据包,客户端不向服务端发送确认数据包,服务器一直等待来自客户端的确认
SYN 洪泛 预防:
- 限制同时打开SYN半链接的数目
- 缩短SYN半链接的Time out 时间
- 关闭不必要的服务
- 给每一个请求连接的 IP 地址分配一个 Cookie,如果短时间内连续收到某个 IP 重复的 SYN 报文则认为收到攻击,以后来自这个 IP 的包全部丢掉
- 利用防火墙阻止 DDoS 攻击
- SYN 网关:防火墙收到客户端的 SYN 包时,直接转发给服务器;防火墙收到服务器的 SYN/ACK 包后,一方面将 SYN/ACK 包转发给客户端,另一方面以客户端的名义给服务器回送一个 ACK 包,完成 TCP 的三次握手,让服务器端由半连接状态进入连接状态。当客户端真正的 ACK 包到达时,有数据则转发给服务器,否则丢弃该包。由于服务器能承受的连接状态要比半连接状态高得多,所以这种方法能有效地减轻对服务器的 SYN 洪泛攻击。
- 被动式 SYN 网关:设置防火墙的 SYN 请求超时参数,让它远小于服务器的超时期限。防火墙负责转发客户端发往服务器的 SYN 包、服务器发往客户端的 SYN/ACK 包,以及客户端发往服务器的 ACK 包。这样,如果客户端在防火墙计时器到期时还没发送 ACK 包,防火墙则往服务器发送 RST 包,以使服务器从队列中删去该半连接。由于防火墙的超时参数远小于服务器的超时期限,因此这样能有效防止 SYN 洪泛攻击。
- 防火墙在收到客户端的 SYN 包后,并不会向服务器转发,而是记录该状态信息,然后主动给客户端回送 SYN/ACK 包,如果收到客户端的 ACK 包,表明是正常访问,由防火墙向服务器发送 SYN 包并完成三次握手。这样由防火墙作为代理来实现客户端和服务器端的连接,可以完全过滤掉不可用的连接发往服务器。
UDP #
与 TCP 区别
- TCP 协议进行数据通信之前需要三次握手建立连接,UDP 协议不需要建立连接即可发送数据。
- TCP 有确认机制,丢包可以重发,保证数据的正确性;UDP 不保证正确性,只是单纯的负责发送数据包。UDP 本身不提供确认,序列号,超时重传等机制。UDP 数据报可能在网络中被复制,被重新排序。即 UDP 不保证数据报会到达其最终目的地,也不保证各个数据报的先后顺序,也不保证每个数据报只到达一次
- TCP 协议可能会对大数据包进行拆分,并且在接收方进行重组数据包操作;UDP 协议是面向报文的,不会进行分片和重组,所以需要注意传输的报文大小。
- 网络包中的 TCP 头部为20个字节;UDP 头部只有8个字节。
- UDP 是无连接的。UDP 客户和服务器之前不必存在长期的关系。UDP 发送数据报之前也不需要经过握手创建连接的过程。
- UDP 支持多播和广播。
ARP协议 #
地址解析协议,即 ARP(Address Resolution Protocol),是根据IP地址获取物理地址的一个 TCP/IP 协议。
主机发送信息时将包含目标IP地址的ARP请求广播到网络上的所有主机,并接收返回消息,以此确定目标的物理地址;收到返回消息后将该IP地址和物理地址存入本机 ARP 缓存中并保留一定时间,下次请求时直接查询 ARP 缓存以节约资源。
- 首先,每个主机都会在自己的 ARP 缓冲区中建立一个 ARP 列表,以表示 IP 地址和 MAC 地址之间的对应关系。
- 当源主机要发送数据时,首先检查 ARP 列表中是否有对应 IP 地址的目的主机的 MAC 地址,如果有,则直接发送数据,如果没有,就向本网段的所有主机发送 ARP 数据包,该数据包包括的内容有:源主机 IP 地址,源主机 MAC 地址,目的主机的 IP 地址。
- 当本网络的所有主机收到该 ARP 数据包时,首先检查数据包中的IP地址是否是自己的IP地址,如果不是,则忽略该数据包,如果是,则首先从数据包中取出源主机的 IP 和 MAC 地址写入到 ARP 列表中,如果已经存在,则覆盖,然后将自己的 MAC 地址写入 ARP 响应包中,告诉源主机自己是它想要找的 MAC 地址。
- 源主机收到 ARP 响应包后。将目的主机的 IP 和 MAC 地址写入 ARP 列表,并利用此信息发送数据。如果源主机一直没有收到 ARP 响应数据包,表示 ARP 查询失败。
广播发送 ARP 请求,单播发送 ARP 响应。
首先查询 ARP 缓存,如果命中,则直接返回结果
如果没有命中:
- 查看路由表,目标 IP 地址是否在本地路由表中的某个子网内,是则使用跟那个子网相连的接口,否则使用与默认网关相连的接口。
- 查询选择的网络接口的 MAC 地址。
- 发送一个数据链路层的 ARP 请求。
如果与 路由器直连:路由器返回 ARP 响应
连接到集线器,则将请求向所有其他端口广播如果路由器在其中,则返回 ARP 响应
连接到交换机:
- 检查本地 CAM/MAC 表,查看哪个端口有要找的 MAC 地址,如果没有则向所有其他端口广播这个请求
- 如果表中有对应的条目,向有我们想要查询的 MAC 地址的那个端口发送 ARP 请求
- 如果路由器在其中,会返回一个响应
DNS #
Domain Name System 或者 Domain Name Service 将网址(域名)翻译成可以理解的IP地址(DNS域名解析)
主机向本地 DNS 服务器查询一般采用递归查询
本地 DNS 向根 DNS 服务器查询采用迭代查询

浏览器输入地址,然后浏览器这个进程去调操作系统某个库里的 gethostbyname
函数(例如,Linux GNU glibc 标准库的 gethostbyname
函数),然后呢这个函数通过网卡给 DNS 服务器发 UDP 请求,接收结果,然后将结果给返回给浏览器。
- 在用 chrome 浏览器的时候,其实会先去浏览器的 dns 缓存里头查询,dns 缓存中没有,再去调用
gethostbyname
函数 gethostbyname
函数在试图进行 DNS 解析之前首先检查域名是否在本地 Hosts 里,如果没找到再去 DNS 服务器上查
DNS 中区域传送用到了 TCP 协议
DNS 的规范规定了 2 种类型的 DNS 服务器,一个叫主 DNS 服务器,一个叫辅助 DNS 服务器。在一个区中主 DNS 服务器从自己本机的数据文件中读取该区的 DNS 数据信息,而辅助 DNS 服务器则从区的主 DNS 服务器中读取该区的 DNS 数据信息。当一个辅助 DNS 服务器启动时,它需要与主 DNS 服务器通信,并加载数据信息,这就叫做区传送(zone transfer)。 这种情况下,使用 TCP 协议。
为什么域名解析用UDP协议
UDP 快,UDP 的 DNS 协议只要一个请求、一个应答就好了。而使用基于 TCP 的 DNS 协议要三次握手、发送数据以及应答、四次挥手。但是 UDP 协议传输内容不能超过 512 字节。不过客户端向 DNS 服务器查询域名,一般返回的内容都不超过 512 字节,用 UDP 传输即可。
为什么区域传送用TCP协议
TCP协议可靠性好,传输内容大
DNS 负载均衡
在 DNS 服务器中为同一主机名配置多个 IP 地址,在应答 DNS 查询时,DNS 服务器对每个查询将以 DNS 文件中主机记录的 IP 顺序返回不同的解析结果(根据每台机器的负载量、该机器离用户地理位置的距离等),将客户端的访问引导到不同的机器上去
DHCP #
DHCP(Dynamic Host Configuration Protocol):动态主机配置协议
IP 地址按照分配方式,可以分为:静态IP地址、动态IP地址
DHCP 协议基于UDP协议,客户端是68端口,服务器是67端口(双方端口都固定)
DHCP 服务器会从IP地址池中,挑选一个 IP 地址“出租“给客户端一段时间,时间到期就回收
平时家里上网的路由器就可以充当 DHCP 服务器
- 主机生成 DHCP 发现报文,广播形式,源地址:0.0.0.0,目的地址:255.255.255.255,源端口:67,目的端口:68,源 MAC 地址:电脑 MAC 地址,目的 MAC 地址:FF:FF:FF:FF
- DHCP 服务器收到 DHCP 发现报文后,会向 DHCP 服务器做出响应,它从尚未出租的 IP 地址中选择一个,然后向主机发送 DHCP 提供报文。是单播还是广播取决于客户端发送的 discover 报文中的字段 “Boot flags”。
- 主机选择第一个收到的 DHCP 提供报文,然后以广播的形式发送 DHCP 请求报文,也是通知其他 DHCP 服务器。
- 然后 DHCP 服务器向主机发送 DHCP 确认报文。
- 重新登录。以后 DHCP 客户机每次重新登录网络时,就不需要再发送 DHCP discover 发现信息了,而是直接发送包含前一次所分配的 IP 地址的 DHCP request 请求信息。当 DHCP 服务器收到这一信息后,它会尝试让 DHCP 客户机继续使用原来的IP地址,并回答一个 DHCP ack 确认信息。如果此 IP 地址已无法再分配给原来的 DHCP 客户机使用时(比如此 IP 地址已分配给其它 DHCP 客户机使用),则 DHCP 服务器给 DHCP 客户机回答一个 DHCP nack 否认信息。当原来的 DHCP 客户机收到此 DHCP nack 否认信息后,它就必须重新发送 DHCP discover 发现信息来请求新的IP地址。
- 更新租约。DHCP 服务器向 DHCP 客户机出租的IP地址一般都有一个租借期限,期满后 DHCP 服务器便会收回出租的 IP 地址。如果 DHCP 客户机要延长其 IP 租约,则必须更新其 IP 租约。DHCP 客户机启动时和 IP 租约期限过一半时,DHCP 客户机都会自动向 DHCP 服务器发送更新其IP租约的信息。
ICMP #
Internet 控制报文协议 (Internet Control Message Protocol)
主机和路由器使用 ICMP 来发送差错报文和查询报文,ICMP 被主机和路由器用来彼此沟通网络层信息,提供给 IP 协议层配置和 IP 数据报处置相关的诊断和控制信息。
ICMP 报文被封装在 IP 数据报中发送,在**==网络层==**。ICMP 通常被认为是 IP 的一部分,但是从体系结构上它是位于 IP 之上的,因为 ICMP 的报文是承载在 IP 分组中的。
应用 #
分组网间探测(ping)
-
用来测试主机或路由器之间的连通性
-
应用层直接使用网际层的 ICMP (没有通过运输层的 TCP 或 UDP)
-
使用 ICMP 回送请求和回答报文
跟踪路由(traceroute)
- 用来测试 IP 数据报从源主机到达目的主机要经过哪些路由器
- win 版本
- tracert 命令
- 应用层直接使用网际层 ICMP
- 使用 ICMP 回送请求和回答报文以及差错报告报文
- Unix 版本
- traceroute 命令
- 运输层使用 UDP 协议,在发送 UDP 包时,填入一个不可能的端口号作为 UDP 目标端口号(大于 3000),目的主机收到 UDP 包后会返回 ICMP 差错报文信息,类型为端口不可达
- 仅使用 ICMP 差错报告报文
- 过程
- 它发送一份 TTL 为 1 的 IP 数据报给目的主机,经过第一个路由器时,TTL 值被减为 0,则第一个路由器丢弃该数据报,并返回一份超时 ICMP 报文,于此得到了路径中第一个路由器的地址;,ICMP 报文类型为时间超时
- 然后再发送一份 TTL 值为 2 的数据报,便可得到第二个路由器的地址;
- 以此类推,一直到到达目的主机为止,这样便记录下了路径上所有的路由 IP。
HTTP #
构建于 TCP/IP 之上,是一个应用层协议,默认端口号80
-
无连接无状态
-
HTTP 请求头和响应头都是以 ASCII 文本方式传输的,但是传输内容可能是多种形式的。接收方处理数据时是根据请求头/响应头中的 content-type 属性来处理
Content-Type
表示请求和响应中的媒体类型信息。它用来告诉服务端如何处理请求的数据,以及告诉客户端(一般是浏览器)如何解析响应的数据,比如显示图片,解析并展示 html 等等。type
:主类型,任意的字符串,如 text,如果是 * 号代表所有;subtype
:子类型,任意的字符串,如 html,如果是 * 号代表所有,用 “/” 与主类型隔开;parameter
:可选参数,如 charset,boundary 等。
例如:
Content-Type: text/html;
Content-Type: application/json;charset:utf-8;
请求报文 #
-
请求行
由请求方法字段、URL 字段和 HTTP 协议版本字段 3 个字段组成,它们用空格分隔
GET /data/info.html HTTP/1.1
-
请求头部
对于 POST 请求来说 Content-Length 必须出现。表示请求消息正文的长度
HOST
:给出请求资源所在服务器的域名。Content-Length
: 表示请求消息正文的长度Content-Type
: 表示请求和响应中的媒体类型信息。Connection
:处理完这次请求后是否断开连接还是继续保持连接。如果是 “Keep- Alive”,或者看到请求使用的是 HTTP 1.1 ( HTTP 1.1 默认进行持久连接),它就可以利用持久连接的优点,当页面包含多个元素时(例如Applet,图片),显著地减少下载所需要的时间。Accept
:说明用户代理可处理的媒介类型,一般是Accept: */*
表 示浏览器可以处理所有类型。If-Modified-Since
: 把浏览器缓存页面的最后修改时间发送到服务器去,服务器会把这个时间与服务器实际文件的最后修改时间对比,如果时间一致,则返回 304,客户端直接使用本地缓存。如果不一致,则会返回 200 状态和新的文件内容,客户端收到之后会丢弃旧的文件,将新文件缓存起来,并显示在浏览器中。Cookie
: 最重要的请求头部之一,用于将 Cookie 的值发送给 HTTP 服务器. -
空行
告诉服务器请求头部到此为止。
-
请求数据
若方法字段是 GET,则此项为空,没有数据
若方法字段是 POST,则通常来说此处放置的就是要提交的数据
响应报文 #
-
响应行
一般由协议版本、状态码及其描述组成 比如
HTTP/1.1 200 OK
1xx:指示信息–表示请求已接收,继续处理,属于提示信息,是协议处理的一种中间状态,用到较少
2xx:成功–表示请求正常处理完毕
- 200 OK:客户端请求被正常处理
3xx:重定向–要完成请求必须进行更进一步的操作
-
301 永久性重定向。该状态码表示请求的资源已经分配了新的 URI,以后应该使用资源现在所指的 URI。也就是说,如果已经把资源对应的 URI 保存为书签了,这是应该按 Location 首部字段提示的 URI 重新保存。301、302 都会在响应头里使用字段
Location
像下方给出的请求 URI,当指定资源路径的最后忘记添加斜杠 /,就会产生 301 状态码。
http://example.com/sample
-
302 临时性重定向
-
304 如果客户端发送了一个带条件的 GET 请求且该请求已被允许,而文档的内容(自上次访问以来或者根据请求的条件)并没有改变,则服务器应当返回这个304状态码。简单的表达就是:服务端已经执行了GET,但文件未变化。
4xx:客户端错误–请求有语法错误,服务器无法处理请求
- 400 (错误请求) 该状态码表示请求报文中存在语法错误。当错误发生时,需要修改请求的内容后再次发送请求。另外,浏览器会像 200 OK 一样对待该状态码。
- 403 (禁止)该状态码表明对请求资源的访问被服务器拒绝了。服务器端没有必要给出拒绝的详细理由,但是如果想说明的话,可以在实体上的主体部分对原因进行描述,这样就能让用户看到了。未获得文件系统的访问权限,访问权限出现某些问题(从未授权的发送源 IP 地址试图访问)等列举的情况都可能是发生 403 的原因
- 404 (未找到)该状态码表明服务器上无法找到请求的资源。除此之外,也可以再服务器端拒绝请求且不想说明理由时使用。
5xx:服务器端错误–服务器处理请求出错。
- 500
- 501 表示客户端请求的功能还不支持
- 502 通常是服务器作为网关或代理时返回的错误码,表示服务器自身工作正常,访问后端服务器发生了错误
- 503 表示服务器当前很忙,暂时无法响应
-
响应头
响应头用于描述服务器的基本信息,以及数据的描述,服务器通过这些数据的描述信息,可以通知客户端如何处理等一会儿它回送的数据。
Content-Encoding:文档的编码 (Encode) 方法。
-
响应体
响应体就是响应的消息体,如果是纯数据就是返回纯数据,如果请求的是 HTML 页面,那么返回的就是 HTML 代码,如果是 JS 就是 JS 代码
get\post #
GET 请求的数据会附在 URL 之后(就是把数据放置在 HTTP 协议头中),会直接展现在地址栏中,以 ?
分割 URL 和传输数据,参数之间以 &
相连,如:login.action?name=hyddd&password=idontknow&verify=%E4%BD%A0%E5 %A5%BD
**POST ** 方法则会把数据放到请求数据字段中以 &
分隔各个字段,请求行不包含数据参数,地址栏也不会额外附带参数
get 方法提交数据的大小直接影响到了 URL 的长度,但 HTTP 协议规范中其实是没有对 URL 限制长度的,限制 URL 长度的是客户端或服务器的支持的不同所影响:比如 IE 对 URL 长度的限制是 2083 字节(2K+35)。对于其他浏览器,如 Netscape、FireFox 等,理论上没有长度限制,其限制取决于操作系统的支持。
**post **方式 HTTP 协议规范中也没有限定,起限制作用的是服务器的处理程序的处理能力。
POST 比 GET 方式的安全性要高
通过 GET 提交数据,用户名和密码将明文出现在 URL 上,因为一下几个原因 get 方式安全性会比 post 弱:
(1)登录页面有可能被浏览器缓存
(2)其他人查看浏览器的历史纪录,那么别人就可 以拿到你的账号和密码了
(3)当遇上跨站的攻击时,安全性的表现更差了
get 是幂等的,post 是非幂等的,不应该也不能用 get 请求做数据的增删改,因为 get 的幂等,在网络不好的隧道中会重复尝试,如果 get 请求增数据,会有重复操作的风险
condition get #
请求报文使用 GET 方法,且请求报文包括了一个 If-Modified-Since 头行
-
条件 get 使用时机
客户端之前访问过某网站,并打算再次访问
-
客户端向服务器发送一个包询问是否在上次访问网站的时间后更改了页面,如果服务器没有更新,则发送
304 Not Modified
,客户端只要使用本地缓存即可。如果已经更新,则发送更新的网页给客户
持久连接 #
Keep-Alive 功能使客户端到服务器端的连接持续有效,当出现对服务器的后继请求时,Keep-Alive 功能避免了建立或者重新建立连接。
- HTTP1.0:如果客户端浏览器支持 Keep-Alive ,那么就在HTTP请求头中添加一个字段
Connection: Keep-Alive
,服务器同理。当客户端发送另外一个请求时,就使用这条已经建立的连接。 - HTTP1.1:默认情况下所有连接都被保持,如果加入 “Connection: close” 才关闭。
- HTTP 长连接不可能一直保持,例如
Keep-Alive: timeout=5, max=100
,表示这个 TCP 通道可以保持 5 秒,max = 100,表示这个长连接最多接收 100 次请求就断开。 - 使用长连接,怎样判断本次传输结束
- 传输数据是否达到
Content-Length
指示的大小 - 动态生成的文件没有
Content-Length
,它是分块传输(chunked),这时候就要根据 chunked 编码来判断,chunked 编码的数据在最后有一个空 chunked 块,表明本次传输数据结束
- 传输数据是否达到
会话跟踪 #
HTTP协议是”无状态”的协议,它不能保存客户的信息,即一次响应完成之后连接就断开了,下一次的请求需要重新连接,这样就需要判断是否是同一个用户,所以才有会话跟踪技术来实现这种要求。
-
url
重写在 URL 结尾添加一个附加数据以标识该会话,把会话 ID 通过 URL 的信息传递过去,以便在服务器端进行识别不同的用户。
-
隐藏表单域
将会话 ID 添加到 HTML 表单元素中提交到服务器,此表单元素并不在客户端显示
-
Cookie
- 保 存在客户端内存中,称为临时 Cookie,浏览器关闭后这个 Cookie 对象将消失
- 保存在客户机的磁盘上,称为永久 Cookie。以后客户端只要访问该网站,就会将这个 Cookie 再次发送到服务器上,前提是这个 Cookie 在有效期内,这样就实现了对客户的跟踪。
-
Session
每一个用户都有一个不同的 session,各个用户之间是不能共享的,是每个用户所独享的,在 session 中可以存放信息。
在服务器端会创建一个 session 对象,产生一个 sessionID 来标识这个 session 对象,然后将这个 sessionID 放入到 Cookie 中发送到客户端,下一次访问时,sessionID 会发送到服务器,在服务器端进行识别不同的用户。
Session 的实现依赖于 Cookie,如果 Cookie 被禁用,那么 session 也将失效。
cookie #
HTTP/1.1 引入 Cookie 来保存状态信息。Cookie 是服务器发送到用户浏览器并保存到本地的一小块数据,它会在浏览器之后向同一服务器再次发起请求时被携带,用于告知服务端两个请求是否来自同一个浏览器,由于之后每次请求都会需要携带 Cookie 数据,因此会带来额外的性能开销。
Cookie 曾一度用于客户端数据的存储,因为当时并没有其它合适的存储办法而作为唯一的存储手段,但现在随着现代浏览器开始支持各种各样的存储方式,Cookie 渐渐被淘汰。新的浏览器 API 已经允许开发者直接将数据存储到本地
- 存放在内存或者磁盘中
- 服务器端生成 Cookie 在响应中通过 Set-Cookie 头部告知客户端 (允许多个 Set-Cookie 头部传递多个值)
- 客户端得到 Cookie 后,后续请求都会自动将 Cookie 头部携带至请求中。
跨站攻击 #
CSRF攻击 #
CSRF(Cross-site request forgery,跨站请求伪造)
-
关键操作只接受
post
请求 -
验证码
-
检测Referer
Referer Check 一般用于监控 CSRF 攻击的发生,而不用来抵御攻击。
-
Token
主流做法。CSRF 攻击要成功的条件在于攻击者能够预测所有的参数从而构造出合法的请求。所以根据不可预测性原则,我们可以对参数进行加密从而防止 CSRF 攻击。另一个更通用的做法是保持原有参数不变,另外添加一个参数 Token,其值是随机的。这样攻击者因为不知道 Token 而无法构造出合法的请求进行攻击。
注意:过滤用户输入的内容不能阻挡 csrf,我们需要做的是过滤请求的来源。
XSS #
XSS(Cross Site Scripting,跨站脚本攻击)
XSS 全称“跨站脚本”,是注入攻击的一种。其特点是不对服务器端造成任何伤害,而是通过一些正常的站内交互途径,例如发布评论,提交含有 JavaScript 的内容文本。这时服务器端如果没有过滤或转义掉这些脚本,作为内容发布到了页面上,其他用户访问这个页面的时候就会运行这些脚本。
常见问题 #
一个 TCP 连接可以对应几个 HTTP 请求
如果有 keep-alive,一个 TCP 连接可以发送多个 HTTP 请求,HTTP2 可以一个连接里并行,HTTP/1.1 需要等待,如果开启 pipelining 可以顺序并行
一个 TCP 连接中 HTTP 请求发送可以一起发送么
HTTP/1.1 存在一个问题,单个 TCP 连接在同一时刻只能处理一个请求,意思是说:两个请求的生命周期不能重叠,任意两个 HTTP 请求从开始到结束的时间在同一个 TCP 连接里不能重叠。
HTTP/1.1 规范中规定了 Pipelining:一个支持持久连接的客户端可以在一个连接中发送多个请求(不需要等待任意请求的响应)。收到请求的服务器必须按照请求收到的顺序发送响应。
现代浏览器默认是不开启 HTTP Pipelining ,提高页面加载效率通过
- 维持与服务器建立的TCP连接,在同一连接上顺序处理多个请求
- 和服务器建立多个TCP连接
HTTP2 提供了 Multiplexing 多路传输特性,可以在一个 TCP 连接中同时完成多个 HTTP 请求。
为什么有的时候刷新页面不需要重新建立 SSL 连接?
TCP 连接有的时候会被浏览器和服务端维持一段时间。TCP 不需要重新建立,SSL 自然也会用之前的。
浏览器对同一 Host 建立 TCP 连接到数量有没有限制?
有。Chrome 最多允许对同一个 Host 建立六个 TCP 连接。不同的浏览器有一些区别。比如传输多张图片时需要多开连接
收到的 HTML 如果包含几十个图片标签,这些图片是以什么方式、什么顺序、建立了多少连接、使用什么协议被下载下来的呢?
如果图片都是 HTTPS 连接并且在同一个域名下,那么浏览器在 SSL 握手之后会和服务器商量能不能用 HTTP2,如果能的话就使用 Multiplexing 功能在这个连接上进行多路传输。
如果发现用不了 HTTP2 呢?或者用不了 HTTPS(现实中的 HTTP2 都是在 HTTPS 上实现的,所以也就是只能使用 HTTP/1.1)。那浏览器就会在一个 HOST 上建立多个 TCP 连接,连接数量的最大限制取决于浏览器设置,这些连接会在空闲的时候被浏览器用来发送新的请求,如果所有的连接都正在发送请求呢?那其他的请求就只能等等了。
HTTP1.1 #
-
默认开启
Connection:keep-alive
,开启长连接 -
支持 Pipelining(流水线),允许一个 TCP 连接上可以传送多个 HTTP 请求和相应,但是服务器必须按顺序处理请求,一般浏览器不开启
-
块编码
可以有
Transfer-Encoding:chunked
头部域http 消息体可以包含任意长度的实体,通常它们使用Content-Length来给出消息结束标志。但是,对于很多动态产生的响应,只能通过缓冲完整的消息来判断消息的大小,但这样做会加大延迟。如果不使用长连接,还可以通过连接关闭的信号来判定一个消息的结束。
块编码:发送方将消息分割成若干个任意大小的数据块,每个数据块在发送时都会附上块的长度,最后用一个零长度的块作为消息结束的标志。这种方法允许发送方只缓冲消息的一个片段,避免缓冲整个消息带来的过载。
-
host 域
1.0 认为每台服务器都绑定一个唯一的 ip 地址,而一台物理服务器上可以存在多个虚拟主机,共享一个 IP
1.1 请求消息和响应消息都应支持 host 域,如果请求消息里没有 host 头域会报告 400 错误(Bad Request)
-
增加了 OPTIONS, PUT, DELETE, TRACE, CONNECT这些Request方法.
优化思路
- 通过缓存避免发送 HTTP 请求(304)
- 减少 HTTP 请求次数
- 将原本客户端处理的重定向请求交给代理服务器处理
- 将多个小资源合并成一个打字员,可以减少 HTTP 请求次数以及头部重复传输,减少 TCP 连接数量
- 按需访问资源每只访问当前用户看的到用得到的资源,当客户往下滑动,在访问接下来的资源达到延迟请求
- 压缩响应资源
HTTP2 #
-
完全采用二进制格式
http1.x 为明文协议,解析是基于文本,而 http2.0 的协议解析采用二进制格式
在二进制分帧层上,http2.0 会将所有的传输信息分割成更小的消息和帧,并对它们采用二进制格式的编码将其封装。其中,http1.x 中的首部信息 header 封装在 headers 帧中,而 request body 将被封装到 data 帧中
http2.0 通信都在一个 TCP 连接上完成,这个连接可以承载任意数量的双向数据流,相应的每个数据流以消息的形式发送。而消息有一个或多个帧组成,这些帧可以乱序发送,然后根据每个帧首部的流标识符重新组装
-
多路复用
根据 request 的 id 将 request 再归属到各自不同的服务端请求里面,即单个连接上可以同时进行多个业务单元数据的传输(服务器不需要按顺序处理)
-
首部压缩
HTTP2.0 在客户端和服务端之间使用首部表来跟踪和存储之前发送的键值对。请求与响应首部的定义在 HTTP2.0 中基本没有变,只是所有首部键必须全部小写,而且要求行要独为为:method:、:scheme:、:host:、:path:这些键值对
对于相同的数据,不再重新通过每次请求和响应发送。每个新的首部键值对要么追加到当前表的末尾,要么替换表中之前的值。首部表在 HTTP2.0 的链接存续期内始终存在,由客户端和服务端共同渐进的更新。
-
流量控制
HTTP2.0 为数据流和连接的流量提供了一个简单的机制:
-
请求优先级
每个流都可以带有一个 31bit 的优先值,确定这客户端和服务器处理不同的流采取不同的优先级策略。
-
服务器推送
服务器可以对一个客户端请求发送多个相应,根据客户端的请求,提前返回多个相应,推送额外的资源给客户端,加快了页面响应速度
HTTPS #
- HTTP 是超文本传输协议,信息是明文传输,存在安全风险,HTTPS 在 TCP 和 HTTP 网络层之间加入 SSL/TLS 安全协议,报文加密传输
- HTTPS 在三次握手之后还需要 SSL/TLS 握手过程,才可进入加密报文传输
- HTTP 端口为 80,HTTPS 为 443
- HTTPS 需要向 CA(证书权威机构)申请数字证书。来保证服务器身份是可信的。
所有使用 HTTPS 发送的数据都可以通过 TLS 层获得三重保护:
- 加密:窃取信息用于非法用途
- 数据完整性 : 篡改信息,中间人攻击
- 身份验证:
TLS 基本过程
- 客户端发送一个
Client Hello
消息到服务器端,消息中包含了它的 Transport Security (TLS) 版本,可用的加密算法和压缩算法 - 服务器端向客户端返回一个
ServerHello
消息,消息中包含了服务器端的 TLS 版本,服务器所选择的加密和压缩算法,以及数字证书认证机构(Certificate Authority,缩写 CA)签发的服务器公开证书,证书中包含了公钥。客户端会使用这个公钥加密接下来的握手过程,直到协商生成一个新的对称密钥。证书中还包含了该证书所应用的域名范围(Common Name,简称 CN),用于客户端验证身份。 - 客户端根据自己的信任 CA 列表,验证服务器端的证书是否可信。如果认为可信,客户端会生成一串伪随机数,使用服务器的公钥加密它。这串随机数会被用于生成新的对称密钥
- 服务器端使用自己的私钥解密上面提到的随机数,然后使用这串随机数生成自己的对称主密钥
- 客户端发送一个
Finished
消息给服务器端,使用对称密钥加密这次通讯的一个散列值 - 服务器端生成自己的 hash 值,然后解密客户端发送来的信息,检查这两个值是否对应。如果对应,就向客户端发送一个
Finished
消息,也使用协商好的对称密钥加密 - 接下来整个 TLS 会话都使用对称秘钥进行加密,传输应用层(HTTP)内容
HTTPS 是对称加密还是非对称加密
对称加密:加密的密钥和解密的密钥是一样的,加密解密处理速度比非对称加密快
非对称加密:加密的密钥和解密的密钥不一致,两种情况:(1)公钥加密,私钥解密(2)私钥加密,公钥解密
https 比 http 安全在最后一个s(ssl)
- 客户端请求服务端,获取公钥
- 服务端生成公私钥,自己保存私钥(SK),将公钥(PK)发送给客户端
- 客户端生成随机字符串 key,通过公钥(PK)加密后发送给服务端
- 服务端拿到加密后的内容后,用自己的私钥(SK)进行加密,得到 key,后续的过程都是通过密钥(key)来进行对称加密来传输
传输对称加密的密钥使用非对称加密,传输实际内容使用对称加密
https 解决的问题
解决了 http 的三分缺点(被监听、被篡改、被伪装)
-
防监听
数据是加密的,即使监听到的都是密文
-
防伪装
伪装分为客户端伪装和服务器伪装,通信双方携带证书,第三方颁布证书,很难伪造
-
防篡改
https 对数据做了摘要,篡改数据会被感知到
SSL #
安全套接字协议,位于 TCP/IP 协议与各种应用层协议之间,为将数据通信提供安全支持,主要任务是提供私密性,信息完整性和身份认证
SSL 加密知名协议:HTTPS,邮件协议 SMTP,pop3
协议结构:
- SSL 记录协议层:为高层协议提供基本的安全服务,记录封装各种各层协议,具体实施压缩解压缩,加密解密、计算和校验 MAC 等与安全相关的操作。它建立在可靠的传输(如TCP)之上,为高层协议提供数据封装、压缩、加密等基本功能。
- 握手协议层:包括 SSL 握手协议、SSL 密码参数修改协议和 SSL 告警协议,用于 SSL 管理信息的交换,允许应用协议传送数据之间相互验证,协商加密算法和生成密钥等,SSL握手协议的作用是协调客户和服务器的状态,使双方能够达到状态的同步
SSL握手协议的大概过程:
-
客户端首先发送 Client Hello 消息到服务端,服务端收到 Client Hello 消息后,再发送 Server Hello 消息回应客户端,这个 Client Hello 里包含了一个客户端生成的随机数 Random1、会话 ID,客户端支持的加密套件(Support Ciphers)和 SSL Version等信息。
会话 ID:如果客户端第一次连接到服务器,那么这个字段就会保持为空。上图中该字段为空 ,说明这是第一次连接到服务器。如果该字段不为空,说明以前是与服务器有连接的。这个阶段之后,客户端服务端知道了下列内容
- SSL版本
- 密钥交换、信息验证和加密算法
- 压缩方法
- 有关密钥生成的两个随机数。
-
服务器启动 SSL 握手第 2 阶段,是本阶段所有消息的唯一发送方,客户机是所有消息的唯一接收 方。该阶段分为 4 步:
- 证书:服务器将数字证书和到根CA整个链发给客户端,使客户端能用服务器证书中的服务器公钥认证服务器。
- 服务器密钥交换(可选):这里视密钥交换算法而定
- 证书请求:服务端可能会要求客户自身进行验证。
- 服务器握手完成:第二阶段的结束,第三阶段开始的信号
-
客户机启动SSL握手第3阶段,是本阶段所有消息的唯一发送方,服务器是所有消息的唯一接收 方。该阶段分为3步:
- 证书(可选):为了对服务器证明自身,客户要发送一个证书信息,这是可选的,在IIS中可以配置强制客户端证书认证。
- 客户机密钥交换(Pre-master-secret):这里客户端将预备主密钥发送给服务端,注意这里会使用服务端的公钥进行加密。
- 证书验证(可选),对预备秘密和随机数进行签名,证明拥有(a)证书的公钥。
-
Client Hello
客户端向服务器发起加密通信请求,也就是 ClientHello 请求
客户端向服务器发送以下信息
- 客户端支持的 SSL/TLS 版本
- 客户端产生的随机数 Client Random
- 客户端支持的密码套件列表,如 RSA 加密算法
-
ServerHello
服务器收到请求,做出相应,内容如下
- 确认 SSL/TLS 协议版本,如果浏览器不支持则关闭加密通信
- 服务器产生随机数 Server Random
- 确认的密码套件列表
- 服务器数字证书
-
客户端响应
客户端收到服务器的响应后,首先通过浏览器或者操作系统的 C/A 公钥,确认服务器的数字证书的真实性。如果没有问题,客户端会从数字证书中取出服务器的公钥,然后使用它加密报文,向服务器发送:
- 一个随机数 pre-master key
- 加密通信算法改变通知,表示随后的信息都将用 “会话密钥” 加密通信
- 客户端握手结束通知,表示客户端的握手阶段已经结束,同时把之前所有内容发生的数据做个摘要,用来供服务端校验
-
服务器响应
通过三个随机数,通过三个协商的加密算法,计算出本次通信的会话密钥,然后向客户端发送
- 加密通信算法改变通知,表示随后的信息都将用 “会话密钥” 加密通信
- 服务器握手结束通知,表示服务器的握手阶段已经结束,同时把所有内容的发生的数据做个摘要,供客户端校验
代理 #
正向代理 #
当客户端无法访问外部资源的时候(由于诸如墙这样的原因),可以通过一个正向代理去间接地访问,所以客户端需要配置代理服务器的 IP 。
正向代理是一个位于客户端和原始服务器(origin server)之间的服务器,为了从原始服务器取得内容,客户端向代理发送一个请求并指定目标(原始服务器),然后代理向原始服务器转交请求并将获得的内容返回给客户端。客户端必须要进行一些特别的设置才能使用正向代理
作用 #
-
访问本无法访问的服务器
-
加速访问服务器。
这种说法目前不像以前那么流行了,主要是带宽流量的飞速发展。早期的正向代理中,很多人使用正向代理就是提速。
假设用户A到服务器B,经过R1路由器和R2路由器,而R1到R2路由器的链路是一个低带宽链路。而用户A到代理服务器Z,从代理服务器Z到服务器B都是高带宽链路。那么很显然就可以加速访问服务器B了。
-
Cache 作用
-
客户端访问授权
-
隐藏访问者的行踪
代理服务器代替用户与服务器进行交互,如果代理服务器被用户完全或不完全控制,被称为“肉鸡”。
反向代理 #
客户端是无感知代理的存在,以代理服务器来接受 internet 上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给 internet 上请求连接的客户端。
作用 #
-
保证内网的安全,公网作为访问地址,web 服务器属于内网。
-
可在防火墙外部设置代理服务器,作为内容服务器的替身。
当外部客户机尝试访问内容服务器时,会将其送到代理服务器。
实际内容位于内容服务器上,在防火墙内部受到安全保护。
所以说反向代理服务器也起到了安全防护作用。
-
负载均衡
当反向代理服务器不止一个的时候,我们甚至可以把它们做成集群,当更多的用户访问资源服务器B的时候,让不同的代理服务器Z(x)去应答不同的用户,然后发送不同用户需要的资源。
-
缓存,将服务器的相应缓存在自己的内存中,减少服务器的压力