1. 基本概念
a) TCP/IP 网络协议。
TCP/IP 是由 OSI 7层解析简化而来,我们不需要知道OSI,只需要记牢TCP/IP 4 层即可。
b) 组包流程
如下图所示: 原始数据由应用层传递给传输层,传输层给其添加TCP或则UDP报头(端口号), 添加TCP/UDP报头的数据传递给网络层,添加IP报头(IP),然后由网络层传递给数据链路层添加以太网头和尾(MAC)
c) IP 报文头结构
Version: 表示这个IP数据包的版本,例如IPV4 或者IPV6
IHL: Internet Head Length 告知这个IP报文头的长度
Type of Service: 这个内容为 PPPDTRUU,代表这个数据包的服务类型:
PPP: 代表包的优先级
D: 0 代表一般延迟, 1代表低延迟
T: 0 代表一般传输量, 1代表高传输量
R: 0 代表一般可靠度, 1代表高可靠度
UU: revered
TotalLength: 指出该数据包的总大小, 包括报头以及数据. 最大为 65535 bytes
Identitfication: 识别码, 当IP数据包足够大被分成了若干个小的IP数据包, 该字段区分是否不同的小的IP数据包是否来自同一个大的数据包。
Flags: 内容为0DM:
D: 0 代表可以分段, 1代表不能分段
M: 0 代表此IP为最后分段, 1代表非最后分段。
Fragment Offset: 分段偏移
代表当前IP分段在原始的IP数据包中所占的位置, 类似于序号, 通过以上4字段 TotalLength, entitfication, Flags, Fragment Offset 就能将小的IP分段组合起来。
Time To Live: TTL 生存时间, 范围为 0 – 255.
Protocol Number: 协议代码, 通过协议代码,确定协议名称:
IP TCP UDP 是常见的。
Header Checksum: 校验值
Source Address: 源地址的IP
Destionation Address: 目标地址的IP
Options: 其他参数
Padding: 32bits对齐
d) TCP 报文头:
Source Port: 源端口
Destionation: 目标端口
Sequence Number: 数据包序号
Acknowledge Number: 回应序号
Data Offset: 数据补偿, 长度不固定
Reserved: 未使用
Code: Control Flag 控制标志码,代表连接状态,非常重要。共有6个bits. 分别说明如下:
URG(Urgent): 1 代表此数据包为紧急数据包
CK(Acknowledge): 1 代表这个数据包为响应数据包
PSH(push fucntion): 1 代表要求对方立刻往上抛数据, 而不是等缓冲区满了再抛数据。
RST(Reset): 1 代表连接马上结束, 并且无需等待对方确认。意思就是强制断线。
SYN(Synchronous): 1 代表发送端希望双方能建立连接, SYN 通常带有”主动”的含义。
FIN(finish): 1 代表传送结束, 与RST 的区别在于,RST 是很粗暴的”我断了,你随意”, 但是FIN 就代表“请问我可以断开了吗?”
Window: 滑动窗口,用于通知对方本机的缓冲区的大小, 当window=0,代表缓冲区满了。
Checksum:校验码
Urgent Pointer:紧急字段, 只用code中的URG=1才有效。告知紧急数据所在的位置。
Options: 表示可以接受最大数据段的容量,较少使用。
Padding: 32bits对齐字段。
e) 三次握手基本概念
1) 为什么TCP协议有三次握手,而UDP协议没有?
因为三次握手的目的是在client端和server端建立可靠的连接。保证双方发送的数据对方都能接受到,这也是TCP协议的被称为可靠的数据传输协议的原因。而UDP就不一样,UDP不提供可靠的传输模式,发送端并不需要得到接收端的状态,因此UDP协议就用不着使用三次握手。
2) 3次握手的原理?
3) 实际抓包分析:
我在笔记本上搭建了HTTP服务器, 在本地使用Chrome 通过IP加端口的形式访问, 我们知道HTTP是基于TCP协议。如果访问成功,则一定经过了三次握手的过程。我们在命令行使用tcpdump进行抓包, 来进行我们的分析, 如下图所示(请注意, 我是在server端进行监听):
我将关键部分抓出来:
Tcpdump 指令: sudo tcpdump tcp port 8008 -X
第一个包:
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
21:48:22.317841 IP DESKTOP-8TIBRLB.local.63492 > yangxiaoyu-HP-EliteBook-8460p.local.8008: Flags [S], seq 524159038, win 8192, options [mss 1460,nop,wscale 8,nop,nop,sackOK], length 0
0x0000: 4500 0034 2c2e 4000 4006 68c3 c0a8 120f E..4,.@[email protected].....
0x0010: c0a8 1273 f804 1f48 1f3e 083e 0000 0000 ...s...H.>.>....
0x0020: 8002 2000 6a74 0000 0204 05b4 0103 0308 ....jt..........
0x0030: 0101 0402
第二个包:
21:48:22.317916 IP yangxiaoyu-HP-EliteBook-8460p.local.8008 > DESKTOP-8TIBRLB.local.63492: Flags [S.], seq 2434712356, ack 524159039, win 29200, options [mss 1460,nop,nop,sackOK,nop,wscale 7], length 0
0x0000: 4500 0034 0000 4000 4006 94f1 c0a8 1273 E..4..@[email protected]
0x0010: c0a8 120f 1f48 f804 911e c324 1f3e 083f .....H.....$.>.?
0x0020: 8012 7210 a5f9 0000 0204 05b4 0101 0402 ..r.............
0x0030: 0103 0307 ....
第三个包:
21:48:22.319051 IP DESKTOP-8TIBRLB.local.63492 > yangxiaoyu-HP-EliteBook-8460p.local.8008: Flags [.], ack 1, win 256, length 0
0x0000: 4500 0028 2c2f 4000 4006 68ce c0a8 120f E..(,/@[email protected].....
0x0010: c0a8 1273 f804 1f48 1f3e 083f 911e c325 ...s...H.>.?...%
0x0020: 5010 0100 75f3 0000 0000 0000 0000 P...u.........
这三个包是IP结构, 因此我们先使用IP包来分析它,然后使用TCP包结构分析。
首先是第一个包, 由于我们是接收端, 监听的是自己计算机的8008端口, 因此第一个包是由我本地计算机由chrome浏览器发送过去的。
可以看到第一个包的方向: DESKTOP-8TIBRLB.local.63492 > yangxiaoyu-HP-EliteBook-8460p.local.8008 (本机是台式机,叫DESKTOP-8TIBRLB 端口为 63492, 服务器是二手的惠普笔记本叫 HP-EliteBook-8460p,端口为8008)
将包按照IP报头字段分解如下(默认16进制,0B开头为2进制):
Version(4bits): 4
IHL(4bits): 5
Type of Service(8bits): 00
Total Length(16bits): 0034
Identification(16bits): 2c2e
Flags(3bits):0B010
Fragment Offset:00
Time To Live(8bits): 40
Protocol(8bits): 06
Header Checksum(16bits): 68c3
Source Address: c0a8 120f
Destination Address: c0a8 1273
Options(19bits): 无(一般 IHL>5才有Options,参阅ftp://ftp.rfc-editor.org/in-notes/std/std5.txt)
Padding:无
Data: f804 1f48 1f3e 083e 0000 0000 8002 2000 6a74 0000 0204 05b4 0103 0308 0101 0402
至此IP包分析完, Data属于TCP报头,按照TCP报头分析第一个包:
Source Port: f804 (十进制为: 63492)
Destation: 1f48(十进制为: 8008)
Sequence Number: 1f3e 083e
Acknowledge Number: 0000 0000
Data Offset: 8
Reserved: 0
Code: 0B000010 (URG|ACK|PSH|RST|SYN|FIN)
Window:2000
CheckSum:6a74
Urgent Pointer: 0000
Opations: 0204 参阅ftp://ftp.rfc-editor.org/in-notes/rfc793.txt [Page 18]
Padding: 05b4
Data: 0103 0308 0101 0402
==================================================================
接下来是第二个包:
Version(4bits): 4
IHL(4bits): 5
Type of Service(8bits): 00
Total Length(16bits): 0034
Identification(16bits): 0000
Flags(3bits):0B010
Fragment Offset:00
Time To Live(8bits): 40
Protocol(8bits): 06
Header Checksum(16bits): 94f1
Source Address: c0a8 1273
Destination Address: c0a8 120f
Options(19bits): 无(一般 IHL>5才有Options,参阅ftp://ftp.rfc-editor.org/in-notes/std/std5.txt)
Padding:无
Data: 1f48 f804 911e c324 1f3e 083f 8012 7210 a5f9 0000 0204 05b4 0101 0402 0103 0307
Data属于TCP报头,按照TCP报头分析第二个包:
Source Port: 1f48(十进制为: 8008)
Destation: f804 (十进制为: 63492)
Sequence Number: 911e c324
Acknowledge Number: 1f3e 083f
Data Offset: 8
Reserved: 0
Code: 0B010010 (URG|ACK|PSH|RST|SYN|FIN)
Window: 7210
CheckSum: a5f9
Urgent Pointer: 0000
Opations: 0204 参阅ftp://ftp.rfc-editor.org/in-notes/rfc793.txt [Page 18]
Padding: 05b4
Data: 0101 0402 0103 0307
==================================================================
接下来是第三个包:
Version(4bits): 4
IHL(4bits): 5
Type of Service(8bits): 00
Total Length(16bits): 0028
Identification(16bits): 2c2f
Flags(3bits):0B010
Fragment Offset:00
Time To Live(8bits): 40
Protocol(8bits): 06
Header Checksum(16bits): 68ce
Source Address: c0a8 120f
Destination Address: c0a8 1273
Options(19bits): 无(一般 IHL>5才有Options,参阅ftp://ftp.rfc-editor.org/in-notes/std/std5.txt)
Padding:无
Data: f804 1f48 1f3e 083f 911e c325 5010 0100 75f3 0000 0000 0000 0000
按照TCP报头分析第三个包:
Source Port: f804 (十进制为: 63492)
Destation: 1f48(十进制为: 8008)
Sequence Number: 1f3e 083f
Acknowledge Number: 911e c325
Data Offset: 5
Reserved: 0
Code: 0B010000 (URG|ACK|PSH|RST|SYN|FIN)
Window: 0100
CheckSum: 75f3
Urgent Pointer: 0000
Opations: 0000参阅ftp://ftp.rfc-editor.org/in-notes/rfc793.txt [Page 18]
Padding: 0000
Data: 0000
==================================================================
我们将这三个包中的关键数据摘出来:
第一次:
由DESKTOP-8TIBRLB.local.63492 > yangxiaoyu-HP-EliteBook-8460p.local.8008
Sequence Number: 1f3e 083e
Acknowledge Number: 0000 0000
Code: 0B000010 (URG|ACK|PSH|RST|SYN|FIN)
第二次:
由yangxiaoyu-HP-EliteBook-8460p.local.8008 > DESKTOP-8TIBRLB.local.63492
Sequence Number: 911e c324
Acknowledge Number: 1f3e 083f
Code: 0B010010 (URG|ACK|PSH|RST|SYN|FIN)
第三次:
由yangxiaoyu-HP-EliteBook-8460p.local.8008 > DESKTOP-8TIBRLB.local.63492
Sequence Number: 1f3e 083f
Acknowledge Number: 911e c325
Code: 0B000010 (URG|ACK|PSH|RST|SYN|FIN)
通过上面三个包, 我们可以很直观的感受到, 三次握手的过程:
1. 前置条件:
a) 有一个client 端和一个server端
b) Client端使用TCP上层的传输层协议进行通信
c) Server端监听端口
2. 首先, client 端向sever端发送TCP报, 指定随机的Sequence Number,和Acknowledge Number = 0,并且指定code中的SYN所占的bit位为1.
3. 然后, server 通过监听端口, 得到了client发送过来的TCP包, 发现其code中的SYN=1,且其他位为0,得知这个包的目的是请求建立可靠的连接,server端就会拿到包中的Sequence Number,将这个number + 1,得到自己的Acknowledge Number, 然后随机生成自己的Sequence Number,再将自己的code中的SYN和ACK所占的bit位都置为1. 组合成包,发送回去。
4. Client端监听自己的端口, 得到了server 端发过来的包, 发现这个包中的Acknowledge Number =自己发过去的Sequence Number + 1, 于是断定server端已经同意建立连接,于是将自己的上个包的Sequence Number + 1 得到当前包中的Sequence Number, 将server发送过来的包中的Sequence Number + 1得到Acknowledge Number。指定code中的ACK所占的bit位为1, 发送回去。
5. 图解:
f) Q&A
1) 如何记忆?
首先需要理解 Sequence Number 代表的是client端包的序号, 因此client端发送的第二个包的Sequence Number比第一个包多1.
然后需要记住 Acknowledge Number = 接受到的TCP包的Sequence Number +1
最后需要记住, 只有一个SYN=1, 代表请求连接, 只有一个ACK=1,代表连接已经建立。
2) 如果最后一个包ACK丢失了会出现什么情况?
Server端在发出SYN/ACK后, 会等待client端发送ACK报文, 如果在一定时间内没有收到, 则重新发送SYN/ACK, 超过了一定的次数, 就会自动关闭这个连接。你想的没错, 如果client端故意不回复这个ACK, 就会在server端占用资源,这就是基于TCP的DDOS攻击。
3) 为什么建立连接是3次握手而不是2次或者4次握手?
我在一本计算机教材上看到这么一个例子,非常有趣,如下:
红军给蓝军发送电文A,决定次日凌晨6点向白军发起攻击,请求蓝军协同作战。
蓝军收到报文A, 但是又需要让红军知道自己收到了报文, 因此回复报文B给红军。
红军收到了蓝军回复的报文B, 于是又发送了一封报文C给蓝军。
蓝军为了让红军知道自己收到了报文C,又发一封报文D给红军。
红军为了让蓝军知道自己收到了报文D,又发一封报文E给蓝军。
。
。
。
这个例子看起来非常愚蠢,但是在我看来,它体现了人们对100%可靠连接的迫切渴望,那么应该如何做,才能使得连接的可靠性接近或者等于100%呢?
答案如下:
(1)红军给蓝军发送电文,决定次日凌晨6点向白军发起攻击,请求蓝军协同作战,并等待蓝军的应答,如果在规定时间内没有收到应答,则重发请求;
(2)蓝军如果收到红军的作战报文后,则回送一个响应报文,表明已知道次日凌晨6点向白军发起攻击且愿意协同作战,并等待红军1的确认,如果在规定时间内没有收到确认报文,则重发响应报文;
(3)红军收到蓝军的响应报文,再向蓝军发送一个确认报文,并表明已知道蓝军将协同作战。
请注意, 这份答案和上面的区别在于第1和第2条中有如果在规定时间内没有收到确认报文,则重发报文.
完成!