TCP和TLS/SSL会话细节
- TCP数据段格式说明
- TCP建立连接和断开连接细节
- Https如何保证通信安全
- 一次Https网络请求通信细节
- 网络数据包分析工具wireshark的使用
问题:
SYN、ACK、FIN具体含义是什么?
TCP建立连接超时的表现?
为什么需要证书来下发服务端公钥?
客户端是如何验证证书合法性的?
对称秘钥是如何协商出来的?
为什么不直接让客户端自己生成一个秘钥发送给服务端使用?
TLS如何避免重放攻击?
TCP数据包格式说明
TCP数据段分为首部+数据两部分。
首部又分为固定首部和可选项首部。
通过对TCP数据包格式的分析,就是了解TCP协议定义的过程。

- 来源连接端口(16比特位)-辨识发送连接端口
- 目的连接端口(16比特位)-辨识接收连接端口
- 序列号(seq,32比特位)-TCP数据包标识。
- 无惧传输时的乱序或丢包
- 建立连接时发送和接收方第一次数据段的seq均为随机生成(TCP序号预测攻击),之后是上次序列号加1
- 发送数据时seq为上一次发送的数据长度加1,如果数据长度为0则seq不变
- 确认号(ack,32比特位)-表示接收方期望下次收到的数据包的序列号的值,也是当前收到的数据的字节长度加1
- 数据偏移(4比特位)-以4字节为单位计算出的数据段开始地址的偏移值,例1111 -> 15 -> 60字节
- 保留位(3比特位)-需置为0
- 标志符(9比特位)
- NS:Nonce Sum 随机和,
- CWR:Congestion Window Reduced 拥塞窗口减少标志被发送主机设置,用来表明它接收到了设置ECE标志的TCP包。拥塞窗口是被TCP维护的一个内部变量,用来管理发送窗口大小
- ECE:ECN-Echo(显式拥塞通知回显) ECN响应标志被用来在TCP3次握手时表明一个TCP端是具备ECN功能的,并且表明接收到的TCP包的IP头部的ECN被设置为11 NS/CWR/ECE三个标志组合实现估计网络拥塞情况的功能
- URG:为1表示高优先级数据包,紧急指针字段有效
- ACK:为1表示确认号字段有效
- PSH:为1表示是带有PUSH标志的数据,指示接收方应该尽快将这个报文段交给应用层而不用等待缓冲区装满
- RST:为1表示出现严重差错,可能需要重新创建TCP连接,还可以用于拒绝分发的报文段和拒绝连接请求
- SYN:为1表示这是连接请求或是连接接受请求,用于创建连接和使顺序号同步
- FIN:为1表示发送方没有数据要传输了,要求释放连接
- 窗口(WIN 16比特位)-表示从确认号开始,本报文的接收方可以接收的字节数,即接收窗口大小,用于流量控制
- 校验和(Checksum 16比特位) -对整个TCP报文段,包括TCP首部和TCP数据,计算出来的16位值,这是一个强制字段。校验方式为:将TCP报文段的头部和数据部分的和计算出来,再对其求反码
- 紧急指针(16比特位)-本报文段中的紧急数据的最后一个字节的序号
- 选项字段 -最多40字节,每个选项的开始是1字节的kind字段,说明选项的类型。下面具体说明支持的选项字段类型
- 0:(1字节)选项表结束
- 1:无操作(1字节)用于选项字段之间的字节边界对齐和分割不同的选项数据
- 2:最大报文长度(4字节,Maximum segment size,MSS) -在握手阶段告知接收方,发送方支持的最大报文数据段的长度,以太网一般为1460。只能出现在同步报文段中,否则将被忽略。通常将MSS设置为MTU-40字节(Maximum Transmission Unit 最大传输单元),这样携带TCP报文段的IP数据报的长度就不会超过MTU,从而避免本机发生IP分片。
- 3:窗口扩大因子(3字节,wscale)-取值0-14,用来把TCP的窗口的值左移的位数。只能出现在同步报文中,否则将被忽略。这是因为现在的TCP接收数据缓冲区(接收窗口)的长度通常大于65535字节
- 4:sackOK -发送端支持并同意使用SACK(Selective Acknowledgements,选择确认)选项
- 5:SACK实际工作的选项,存放丢包的边界信息,最多存放4个包的边界信息。例如123,丢了2,那么SACK存放的就是2号包的开始和结束的字节序列号
- 8:时间戳(10字节,TCP Timestamps Option,TSopt)
- 发送端的时间戳(Timestamp Value field, TSval,4字节)
- 时间戳回显应答(Timestamp Echo Reply field,TSecr,4字节)
时间戳的功能有两个:
- 用来计算往返时间RTT(Round-Trip Time),发送方在收到确认报文后,可以准确计算出RTT。
- 防止回绕的序列号,通过时间戳可以判断出相同序列号的数据报,哪个是最近发送的,哪个是以前发送的。
滑动窗口
简单一句话就是接收方可以动态控制发送方下次发送的TCP包数据段的大小。
当接收方处理数据较慢时,就可以通过WIN字段,在ACK包中告知发送方:“以后的数据段少发一些,我处理不过来了。”
在极端情况下,接收方连1字节的数据也不能处理了,那么WIN字段就设置为0,发送方就会停止发送后续的TCP包。
那么,当接收方缓过气来,可以处理更多数据时,发送方是怎么知道的呢?答案是Zero Window Probe(零窗口探针)技术。
发送方会在一定时间间隔内重复发送ZWP包,这时接收方就有机会告知发送方最新的窗口大小。
又有极端情况,接收方一直返回WIN为0,那么发送方在发送一定次数的ZWP后,就会发送RST包来断开连接(不同的系统有不同的实现)。
另外一种极端情况,接收方返回的WIN值特别小,相对于TCP的首部来说,发送较少的数据时一种浪费。这个时候接收方就会使用David D Clark’s 方案。接收方直接返回WIN为0,知道接收方有足够的能力处理新数据时再把WIN打开。
如果是由于发送方发送的数据特别少引起的,那么发送方就会使用Nagle’s algorithm。将多个小的数据包缓存起来,直到满足发送条件。
ECE和CWR
当两个支持ECN的TCP端进行TCP连接时,对于支持ECN的TCP端来说,SYN包的ECE和CWR标志都被设置了。SYN-ACK只设置ECE标志。
一个支持ECN的TCP主机在支持ECN的TCP连接上发送设置了IP头部为10或者01的TCP包。支持ECN的路由器在经历拥塞时设置IP头部的ECN域为11。当一个TCP接收端发送针对收到的一个设置ECN位为11的TCP包的响应时,它设置TCP包头中的ECE,并且在接下来的ACK中也做同样设置。
当发送主机接收到设置了ECE标志的ACK时,它就像感知到包丢失一样,开始减少发送窗口,运行慢启动过程和拥塞避免算法。在下一个数据包中,发送者设置CWR标志。在接收到新的设置CWR标志的包时,接受者停止在接下来的ACK中设置ECE标志。
超时重传
建立连接时:
如果发送方在发送一个SYN包后,在超时时间内没有收到确认包,则发送方会重新发送,称为超时重发。
默认Linux重试次数为5次,重试时间间隔由1s开始每次翻倍,即1s,2s,4s,8s,16s。如果经过1+2+4+8+16+32=63s后,仍没有收到确认包,则发送方认为接收方已掉线,会主动断开当前连接。
数据传输时:
为了网络整体的稳定,需要动态的根据往返时间设置数据包的超时时间。这里就不展开说具体算法过程了。
RTO(Retransmission Timeout)重传超时时间
RTT(Round-Trip Time)往返时间
拥塞控制
慢启动
拥塞避免
快速重传
快速恢复
三次握手 和 四次挥手
三次握手
这是简单的三次握手流程示意图,三次握手意思是需要在发送方和接收方之间传递三个数据包。通过设置不同的标识位,来告知对方当前数据包的意图。
第一次:C发送一个数据包P1给S,并将标识位的SYN置为1,表明“我要和你建立连接”。
第二次:S如果可以接受C的请求,会给C回发一个数据包P2,并将标识位SYN置为1,表明“我同意和你建立连接”。同时将ACK位置为1,表明“确认号ack”字段有效,其值为P1数据包序列号+1。
第三次:C接到P2后,会再次向S发送数据包P3,将ACK为置为1,其值为P2数据包的序列号+1,表明“我知道了你同意了”。
至此,连接就被建立完成了,双方就可以任意发送数据了。
但是,在三次握手过程中,除了要协商