1.写在前面
前面我们了解了网络协议的HTTP协议,TLS协议,WebSocket协议,今天我们来介绍对应的TCP协议,差不多画上一篇博客的篇幅,大概的介绍下。
2.TCP 历史及其设计哲学
TCP/IP 的前身 ARPA:NCP 协议
TCP/IP 协议发展
TCPv4 协议分层后的互联网世界
TCP/IP 的七个设计理念
David D Clark:《The Design Philosophy of The DARPA Internet Protocols》
- Internet communication must continue despite loss of networks or gateways.
- The Internet must support multiple types of communications service.
- The Internet architecture must accommodate a variety of networks.
- The Internet architecture must permit distributed management of its resources.
- The Internet architecture must be cost effective.
- The Internet architecture must permit host attachment with a low level of effort.
- The resources used in the internet architecture must be accountable.
3.TCP 解决了哪些问题?
TCP 的作用
TCP协议的分层
- TCP:面向连接的、可靠的、基于字节流的传输层通信协议
- IP:根据IP地址穿越网络传送数据
层层嵌套的"信封":报文头部
报文头部的层层组装与卸载
不可靠的网络传输
- 网络设备
- 主机
- 物理链路
TCP 协议特点
在 IP 协议之上,解决网络通讯可依赖问题
- 点对点(不能广播、多播),面向连接
- 双向传递(全双工)
- 字节流:打包成报文段、保证有序接收、重复报文自动丢弃
- 缺点:不维护应用报文的边界(对比 HTTP、GRPC)
- 优点:不强制要求应用必须离散的创建数据块,不限制数据块大小
- 流量缓冲:解决速度不匹配问题
- 可靠的传输服务(保证可达,丢包时通过重发进而增加时延实现可靠性)
- 拥塞控制
4.TCP 报文格式
消息传输的核心要素
-
寄件人与收件人信息
- IP 地址
- TCP(UDP)端口
- HTTP Host/URI 等
-
物流订单号
- IP 序列号
- TCP 序列号
-
物流系统需求
IP头部
UDP 头部
TCP 协议的任务
- 主机内的进程寻址
- 创建、管理、终止连接
- 处理并将字节(8bit)流打包成报文段(如 IP 报文)
- 传输数据
- 保持可靠性与传输质量
- 流控制与拥塞控制
如何标识一个连接?
-
TCP 四元组(源地址,源端口,目的地址,目的端口)
- 对于 IPv4 地址,单主机最大 TCP 连接数为 2(32+16+32+16)
-
没有连接 ID:QUIC 协议
TCP Segment 报文段
控制信息
- 寻址
- 滑动窗口
- Flags
- 校验和
数据
常用选项
5.如何使用 tcpdump 分析网络报文?
捕获及停止条件
- -D 列举所有网卡设备
- -i 选择网卡设备
- -c 抓取多少条报文
- –time-stamp-precision 指定捕获时的时间精度,默认毫秒 micro,可选纳秒 nano
- -s 指定每条报文的最大字节数,默认 262144 字节
BPF:Expression 表达式
- primitives 原语:由名称或数字,以及描述它的多个限定词组成
- qualifiers 限定词
- Type:设置数字或者名称所指示类型,例如 host www.baidu.com
- Dir:设置网络出入方向,例如 dst port 80
- Proto:指定协议类型,例如 udp
- 其他
- 原语运算符
- 与:&& 或者 and
- 或:|| 或者 or
- 非:! 或者 not
- 例如:src or dst portrange 6000-8000 && tcp or ip6
- qualifiers 限定词
限定词
- Type:设置数字或者名称所指示类型
- host、port
- net ,设定子网,net 192.168.0.0 mask 255.255.255.0 等价于 net 192.168.0.0/24
- portrange,设置端口范围,例如 portrange 6000-8000
- Dir:设置网络出入方向
- src、dst、src or dst、src and dst
- ra、ta、addr1、addr2、addr3、addr4(仅对 IEEE 802.11 Wireless LAN 有效)
- Proto:指定协议类型
- ether、fddi、tr、 wlan、 ip、 ip6、 arp、 rarp、 decnet、 tcp、udp、icmp、igmp、icmp、igrp、pim、ah、esp、vrrp
- 其他
- gateway:指明网关 IP 地址,等价于 ether host ehost and not host host
- broadcast:广播报文,例如 ether broadcast 或者 ip broadcast
- multicast:多播报文,例如 ip multicast 或者 ip6 multicast
- less, greater:小于或者大于
基于协议域过滤
- 捕获所有 TCP 中的 RST 报文
- tcp[13]&4==4
- 抓取 HTTP GET 报文
- port 80 and tcp[((tcp[12:1] & 0xf0) >> 2):4] = 0x47455420
- 注意:47455420 是 ASCII 码的 16 进制,表示"GET" TCP 报头可能不只 20 字节,data offset 提示了承载数据的偏移,但它以 4 字节为单位
文件操作
- -w 输出结果至文件(可被Wireshark读取分析)
- -C 限制输入文件的大小,超出后以后缀加 1 等数字的形式递增。注意单位是 1,000,000 字节
- -W 指定输出文件的最大数量,到达后会重新覆写第 1 个文件
- -G 指定每隔N秒就重新输出至新文件,注意-w 参数应基于 strftime 参数指定文件名
- -r 读取一个抓包文件
- -V 将待读取的多个文件名写入一个文件中,通过读取该文件同时读取多个文件
输出时间戳格式
- -t 不显示时间戳
- -tt 自 1970年 1 月 1 日 0 点至今的秒数
- -ttt 显示邻近两行报文间经过的秒数
- -tttt 带日期的完整时间
- -ttttt 自第一个抓取的报文起经历的秒数
分析信息详情
- -e 显示数据链路层头部
- -q 不显示传输层信息
- -v 显示网络层头部更多的信息,如 TTL、id 等
- -n 显示 IP 地址、数字端口代替 hostname 等
- -S TCP 信息以绝对序列号替代相对序列号
- -A 以 ASCII 方式显示报文内容,适用 HTTP 分析
- -x 以 16 进制方式显示报文内容,不显示数据链路层
- -xx 以 16 进制方式显示报文内容,显示数据链路层
- -X 同时以 16 进制及 ACII 方式显示报文内容,不显示数据链路层
- -XX 同时以 16 进制及 ACII 方式显示报文内容,显示数据链路层
6.三次握手建立连接
握手的目标
- 同步 Sequence 序列号
- 初始序列号 ISN(Initial Sequence Number)
- 交换 TCP 通讯参数
- 如 MSS、窗口比例因子、选择性确认、指定校验和算法
三次握手
- SYN:同步
- ACK:确认
三次握手:SYN 报文
三次握手:SYN/ACK 报文
三次握手:ACK 报文
7.三次握手状态变迁
三次握手流程
- CLOSED
- LISTEN
- SYN-SENT
- SYN-RECEIVED
- ESTABLISHED
netstat 命令查看 TCP 状态
interval: 重新显示选定的统计信息,各个显示间暂停的间隔秒数。
- -a: 显示所有连接和侦听端口。
- -n: 以数字形式(如 IP 地址)显示地址和端口号。
- -r: 显示路由表。
- -s: 显示每个协议的统计信息。
- -o(Windows): 显示拥有的与每个连接关联的进程 ID。
- -b(Windows)/-p(Linux) : 显示对应的可执行程序名字。
两端同时发送SYN:双方使用固定源端口且同时建连接
TCB:Transmission Control Block,保存连接使用的源端口、目的端口、目的 ip、序号、应答序号、对方窗口大小、己方窗口大小、tcp 状态、tcp 输入/输出队列、应用层输出队列、tcp 的重传有关变量等
8.三次握手中的性能优化与安全问题
服务器三次握手流程示例
超时时间与缓冲队列
- 应用层 connect 超时时间调整
- 操作系统内核限制调整
- 服务器端 SYN_RCV 状态
- net.ipv4.tcp_max_syn_backlog:SYN_RCVD 状态连接的最大个数
- net.ipv4.tcp_synack_retries:被动建立连接时,发SYN/ACK的重试次数
- 客户端 SYN_SENT 状态
- net.ipv4.tcp_syn_retries = 6 主动建立连接时,发 SYN 的重试次数
- net.ipv4.ip_local_port_range = 32768 60999 建立连接时的本地端口可用范围
- ACCEPT队列设置
- 服务器端 SYN_RCV 状态
Fast Open 降低时延
Linux上打开TCP Fast Open
net.ipv4.tcp_fastopen:系统开启 TFO 功能
- 0:关闭
- 1:作为客户端时可以使用 TFO
- 2:作为服务器时可以使用 TFO
- 3:无论作为客户端还是服务器,都可以使用 TFO
如何应对 SYN 攻击?
攻击者短时间伪造不同 IP 地址的 SYN 报文,快速占满 backlog 队列,使服务器不能为正常用户服务
- net.core.netdev_max_backlog
- 接收自网卡、但未被内核协议栈处理的报文队列长度
- net.ipv4.tcp_max_syn_backlog
- SYN_RCVD 状态连接的最大个数
- net.ipv4.tcp_abort_on_overflow
- 超出处理能力时,对新来的 SYN 直接回包 RST,丢弃连接
tcp_syncookies
TCP_DEFER_ACCEPT
9.数据传输与 MSS 分段
TCP 应用层编程示例
TCP 流的操作
TCP 流与报文段
流分段的依据
- MSS:防止 IP 层分段
- 流控:接收端的能力
MSS:Max Segment Size
- 定义:仅指 TCP 承载数据,不包含 TCP 头部的大小,参见 RFC879
- MSS 选择目的
- 尽量每个 Segment 报文段携带更多的数据,以减少头部空间占用比率
- 防止 Segment 被某个设备的 IP 层基于 MTU 拆分
- 默认 MSS:536 字节(默认 MTU576 字节,20 字节 IP 头部,20 字节 TCP 头部)
- 握手阶段协商 MSS
- MSS 分类
- 发送方最大报文段 SMSS:SENDER MAXIMUM SEGMENT SIZE
- 接收方最大报文段 RMSS:RECEIVER MAXIMUM SEGMENT SIZE
TCP 握手常用选项
10.重传与确认
报文有可能丢失
PAR:Positive Acknowledgment with Retransmission
问题:效率低
提升并发能力的 PAR 改进版
接收缓冲区的管理
- Limit 限制发送方
Sequence 序列号/Ack 序列号
- 设计目的:解决应用层字节流的可靠发送
- 跟踪应用层的发送端数据是否送达
- 确定接收端有序的接收到字节流
- 序列号的值针对的是字节而不是报文
确认序号
TCP 序列号
PAWS (Protect Against Wrapped Sequence numbers)
- 防止序列号回绕
BDP 网络中的问题
TCP timestamp
- 更精准的计算 RTO
- PAWS
11.RTO 重传定时器的计算
如何测量 RTT?
如何在重传下有效测量 RTT?
RTT 测量的第 2 种方法
- 发送时间
- 数据包中 Timestamp 选项的回显时间
RTO( Retransmission TimeOut )应当设多大?
- RTO 应当略大于 RTT
RTO 应当更平滑
平滑 RTO:RFC793,降低瞬时变化
- SRTT (smoothed round-trip time) = ( α * SRTT ) + ((1 - α) * RTT)
- α 从 0到 1(RFC 推荐 0.9),越大越平滑
- RTO = min[ UBOUND, max[ LBOUND, (β * SRTT) ] ]
- 如 UBOUND为1分钟,LBOUND为 1 秒钟, β从 1.3 到 2 之间
- 不适用于 RTT 波动大(方差大)的场景
追踪 RTT 方差
RFC6298(RFC2988),其中α = 1/8, β = 1/4,K = 4,G 为最小时间颗粒:
- 首次计算 RTO,R为第 1 次测量出的 RTT
- SRTT(smoothed round-trip time) = R
- RTTVAR(round-trip time variation) = R/2
- RTO = SRTT + max (G, K*RTTVAR)
- 后续计算 RTO,R’为最新测量出的 RTT
- SRTT = (1 - α) * SRTT + α * R’
- RTTVAR = (1 - β) * RTTVAR + β * |SRTT - R’|
- RTO = SRTT + max (G, K*RTTVAR)
12.滑动窗口:发送窗口与接收窗口
滑动窗口:发送窗口快照
-
已发送并收到 Ack 确认的数据:1-31 字节
-
已发送未收到 Ack 确认的数据:32-45 字节
-
未发送但总大小在接收方处理范围内:46-51 字节
-
未发送但总大小超出接收方处理范围:52-字节
可用窗口/发送窗口
可用窗口:46-51 字节 / 发送窗口:32-51 字节
46-51 字节已发送
可用窗口耗尽
32 到 36 字节已确认
发送窗口移动
发送窗口
约等于对端发送窗口的接收窗口
13.窗口的滑动与流量控制
窗口滑动示例: MSS 不产生影响, 窗口不变
客户端消息的发送
服务器消息的发送
14.写在最后
今天简单的介绍了TCP协议的一部分的内容,剩下的内容下次博客继续介绍。