1. 协议分层模型
OSI参考模型 | TCP/IP参考模型 | 常见协议 |
---|---|---|
应用层 |
应用层 |
HTTP FTP SMTP SSH |
表示层 |
||
会话层 |
||
传输层 |
传输层 |
TCP UDP RTP SCTP |
网络层 |
互联网层 |
IP ICMP |
数据链路层 |
网络接口层 |
IEEE802.3 IEEE802.11 |
物理层 |
以太网首部 | IP首部 | TCP首部 | HTTP请求/响应头 | 数据 |
---|---|---|---|---|
L2 |
L3 |
L4 |
L7 |
应用程序 |
<20字节> |
<20~60字节> |
<MSS> |
||
<MTU: 1500/9000> |
2. TCP协议简介
TCP
是一种面向连接的、可靠的、有序的、基于字节流的传输层通信协议. [RFC9293]
-
面向连接: 确认通信设备间连接的开始和结束, 同时通过拥塞控制机制保障端到端的高可靠通信.
-
可靠的: 通过ACK确认机制确保数据传输完成.
-
有序的: 通过SEQ机制对收到的分段顺序进行管理.
-
基于字节流: 无边界.
3. TCP连接
3.1. 握手流程
3.1.1. 标准三次握手流程
|
3.2. 挥手流程
3.2.4. so_linger
struct linger so_linger;
so_linger.l_onoff = 1;
so_linger.l_linger = 0;
setsockopt(s, SOL_SOCKET, SO_LINGER, &so_linger,sizeof(so_linger));
4. 拥塞控制
4.1. 窗口
-
\$"rwnd"\$ : 发送方从收到的ACK中被告知的接收方缓冲区大小.
-
\$"cwnd"\$ : 发送方经过拥塞控制算法计算出的拥塞窗口大小.
-
\$"swnd"\$ : 发送方最终计算到的发送窗口大小. \$"swnd"=min("rwnd","cwnd")\$
4.2. 基本阶段
4.2.1. 慢启动
-
第一次
cwnd = 1
, 后续窗口加上收到的ACK个数. -
当发生丢包 (超时重传或收到重复ACK) 时,
cwnd
重置为1, 重新进行慢启动.
4.2.2. 拥塞避免
-
设置
ssthresh
阈值为cwnd
的一半. -
cwnd < ssthresh
时, 仍然指数增长cwnd
. -
cwnd >= ssthresh
时, 每收到cwnd
个ACK时,cwnd
才会加1, 实现慢速线性增长.
4.2.3. 快速恢复
-
收到重复ACK时, 设置
ssthresh
阈值为cwnd
的一半, 重置cwnd = cwnd / 2 + 重复ACK个数
. (快速重传) -
收到重传报文对应的ACK后, 重置
cwnd = ssthresh
, 进行拥塞避免阶段.
4.2.4. 拥塞控制算法
-
Reno
-
NewReno
-
CUBIC
-
BBR
5. 工具
5.1. tcpdump
# 监听指定网卡
tcpdump -i eth0
# 监听指定端口
tcpdump port 8080
tcpdump portrange 8000-8100
# 监听指定ip(段)
tcpdump host 192.168.0.2
tcpdump net 192.168.0.0/24
# 监听指定来源/目标ip/端口的报文
tcpdump dst 1.0.0.1
tcpdump -nnvvS src 10.5.2.3 and dst port 3389
tcpdump 'src 10.0.2.4 and (dst port 3389 or 22)'
# 监听RST包
tcpdump 'tcp[13] & 4!=0'tcpdump 'tcp[tcpflags] == tcp-rst'
# 监听SYN和RST包
tcpdump 'tcp[13] = 6'
# 监听GET请求
tcpdump -vvAls0 | grep 'GET'
# 输出结果到指定文件
tcpdump host 192.168.0.2 -w 02.cap
5.2. netstat
# 查看端口占用的进程
sudo netstat -lnp | grep 22| awk '{print $NF}'
# 查看进程使用的端口号:
sudo netstat -atpn | grep <PID>
# 查看tcp使用情况分析
sudo netstat -st
# 查看所有监听的unix socket
sudo netstat -lx
5.3. ss
# 查看指定目标地址/端口的连接
ss dst 192.168.0.2
# 查看指定状态的socket
ss state ESTABLISHED
# 查看port小于1024的socket
ss -n sport \< 1024
# 查看tcp使用情况分析
ss -s