深入理解TCP/IP
1、TCP/IP与OSI的关系
网上学习网络模型时一会是七层osi模型,一会又五层,一会又是四层模型,着实五花八门让人费解,实际上七层模型是osi的标准,目前大家所讲的tcp/ip也是符合osi的标准的,不过是把其中几层合并到一层了而已,点击查看tcp/ip和osi的关系。TCP/IP实际上是一个协议簇,包含很多协议,比如TCP、IP、UDP、ICMP、RIP、TELNETFTP、SMTP、ARP、TFTP等,这些协议一起称为TCP/IP协议。常见协议简单介绍:
TCP(Transport Control Protocol)传输控制协议
IP(Internetworking Protocol)网间网协议
UDP(User Datagram Protocol)用户数据报协议
ICMP(Internet Control Message Protocol)互联网控制信息协议
SMTP(Simple Mail Transfer Protocol)简单邮件传输协议
SNMP(Simple Network manage Protocol)简单网络管理协议
FTP(File Transfer Protocol)文件传输协议
ARP(Address Resolation Protocol)地址解析协议
2、TCP/IP
完整的osi七层模型,在tcp/ip中被简化为了4层模型,其中应用层、表示层、会话层被压缩成了一个应用层,数据链路层、物理层被压缩为数据链路层。
2.1 应用层
应用层顾名思义退就是和应用相关,既然和应用相关,那么不同应用肯定就不一样,这一部分的东西需要自定义,就是程序员需要实现的,比如HTTP、FTP、SMTP、NFS等。既然是互联网应用,数据传输肯定得有双方,就是我们说的客户端应用、服务端应用,而应用层这里就是制定客户端和服务端交互的规范,说白了就是保证客户端发的东西服务端能识别,服务端发的东西客户端也能识别。以http为例,http中就制定了请求行、请求体、请求头等,发送的时候必须有这些东西,服务端才能够解析,而相应的服务端响应时也得有对应的东西,这样客户端才能够解析出响应信息。这里只是制定规范,真正的传输还要用到后面的tcp,所以通常说http是基于tcp,就是这个道理。
2.2 传输控制层(TCP,不讲UDP)
关键词: 可靠性、三次握手四次挥手、拆包
tcp负责建立连接,断开连接,控制数据包大小等,建立连接就是常说的三次握手四次挥手。建立连接的过程分为3步:
- 客户端发送连接请求的标识符SYN
- 服务端回复SYN+ACK
- 客户端回复ACK
具体的交互可以使用抓包工具wireshark查看,或者使用tcpdump命令行工具。
# 先打开监听
sudo tcpdump -nn -i <网卡> port 80
# 访问baidu,端口80
curl https://www.baidu.com
[S]: SYN --------发送建立连接请求标志 [.]: ACK-----点代表ACK [P]: ---------发送
如下前三行就是三次握手过程,注意看握手成功后,每次客户端给服务端发消息,服务端都会给客户端回复一个[.],代表确认,这就是为什么说tcp是可靠的连接,反过来也一样,服务端给客户端响应消息,客户端也会回复 一个[.], 注意看,服务端给客户端发消息时,分了好几次,这就是控制数据包,不是说一次性把所有的数据都返回到客户端,这个大小是受到网卡控制的,体现了tcp对数据包大小的“控制”,
#客户端发送连接SYN
11:13:07.566166 IP 192.168.189.36.48460 > 14.215.177.38.80: Flags [S], seq 889820627, win 64240, options [mss 1460,sackOK,TS val 412117082 ecr 0,nop,wscale 7], length 0
#服务端回复SYN+ACK
11:13:07.609539 IP 14.215.177.38.80 > 192.168.189.36.48460: Flags [S.], seq 4077951874, ack 889820628, win 8192, options [mss 1380,sackOK,nop,nop,nop,nop,nop,nop,nop,nop,nop,nop,nop,wscale 5], length 0
#客户端回复ACK连接建立成功
11:13:07.609598 IP 192.168.189.36.48460 > 14.215.177.38.80: Flags [.], ack 1, win 502, length 0
#客户端正式发送GET请求
11:13:07.609870 IP 192.168.189.36.48460 > 14.215.177.38.80: Flags [P.], seq 1:78, ack 1, win 502, length 77: HTTP: GET / HTTP/1.1
#服务端给客户端回复ack,代表服务端告诉客户端,我收到了你的消息,--------tcp可靠性的体现
11:13:07.648210 IP 14.215.177.38.80 > 192.168.189.36.48460: Flags [.], ack 78, win 908, length 0
11:13:07.651005 IP 14.215.177.38.80 > 192.168.189.36.48460: Flags [.], seq 1:2721, ack 78, win 908, length 2720: HTTP: HTTP/1.1 200 OK
11:13:07.651006 IP 14.215.177.38.80 > 192.168.189.36.48460: Flags [P.], seq 2721:2782, ack 78, win 908, length 61: HTTP
11:13:07.651038 IP 192.168.189.36.48460 > 14.215.177.38.80: Flags [.], ack 2721, win 497, length 0
11:13:07.651070 IP 192.168.189.36.48460 > 14.215.177.38.80: Flags [.], ack 2782, win 497, length 0
11:13:07.657940 IP 14.215.177.38.80 > 192.168.189.36.48460: Flags [P.], seq 2721:2782, ack 78, win 908, length 61: HTTP
11:13:07.657979 IP 192.168.189.36.48460 > 14.215.177.38.80: Flags [.], ack 2782, win 501, options [nop,nop,sack 1 {2721:2782}], length 0
11:13:08.652666 IP 192.168.189.36.48460 > 14.215.177.38.80: Flags [F.], seq 78, ack 2782, win 501, length 0
11:13:08.788214 IP 14.215.177.38.80 > 192.168.189.36.48460: Flags [.], ack 79, win 908, length 0
11:13:08.788215 IP 14.215.177.38.80 > 192.168.189.36.48460: Flags [F.], seq 2782, ack 79, win 908, length 0
11:13:08.788268 IP 192.168.189.36.48460 > 14.215.177.38.80: Flags [.], ack 2783, win 501, length 0
2.3 网络层
关键词:路由表、下一跳
#查看路由表
route -n
传输控制层建立好连接后,对收据也拆好包后,应该把数据包丢给谁呢? 当数据包准备好以后,要从路由表中找到下一跳的位置,如下是我的路由表,我们来举例说明网络层的工作原理。
$ route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 192.168.189.137 0.0.0.0 UG 20600 0 0 wlp5s0
10.10.0.0 192.168.93.1 255.255.0.0 UG 100 0 0 enp4s0
172.17.0.0 0.0.0.0 255.255.0.0 U 0 0 0 docker0
192.168.0.0 192.168.93.1 255.255.0.0 UG 100 0 0 enp4s0
192.168.92.0 0.0.0.0 255.255.255.0 U 100 0 0 enp4s0
192.168.93.1 0.0.0.0 255.255.255.255 UH 100 0 0 enp4s0
192.168.189.0 0.0.0.0 255.255.255.0 U 600 0 0 wlp5s0
2.3.1 实例1,访问内网走enp4s0网卡
当我们执行ping 192.168.92.33
,网络层会拿这个ip分别和路由表子网掩码(mask)从大到小分字节按位与计算,
- 先和第6行255.255.255.255进行与计算,得到的还是192.168.92.33,然后看这个结果是否和网络号Destination是否一致,192.168.92.33和0.0.0.0不一样,继续找下一个路由按照同样的方式计算,直到找到相等的
- 接下来和第7行255.255.255.0计算,依然不行
- 接下来和第5行 255.255.255.0计算得到192.168.92.0匹配上了,匹配上之后,再看网关是0.0.0.0代表没有下一跳了,直接把数据包通过对应的enp4s0网卡把数据发出去了
2.3.2 实例2,访问外网走wlp5s0网卡
当我们执行ping baidu.com
,经过dns拿到百度的ip:110.242.68.66,网络层会拿这个ip分别和路由表子网掩码(mask)从大到小分字节按位与计算,
- 先和第6行255.255.255.255进行与计算,得到的还是110.242.68.66,然后看这个结果是否和网络号Destination是否一致,110.242.68.66和0.0.0.0不一样,继续找下一个路由按照同样的方式计算,直到找到相等的
- 接下来和第7行255.255.255.0计算,依然不行
- 接下来和第5行 255.255.255.0计算得到110.242.68.0 还是不行
- 一直到和第一行0.0.0.0进行与计算得到0.0.0.0,才匹配上,这时确定到下一跳是192.168.189.137,这个也是我的手机无限热点 那么数据包如何才能准确发送到192.168.189.137这个地址上?这就要用到链路层,继续查看后续章节
2.4 数据链路层
关键词:arp广播
## 查看arp缓存
arp -a
## 抓arp类型的包
sudo tcpdump -nn -i <网卡> arp
实战抓取wlp5s0网卡上的arp广播
## 1. 开启抓包
sudo tcpdump -nn -i wlp5s0 arp
## 2. 使用另一个windows电脑也连接到我的手机热点,随便ping一个wlp5s0网卡能处理的ip,
ping 192.168.189.55
此时在看抓包的日志打印如下:
$ sudo tcpdump -nn -i wlp5s0 arp
[sudo] chenkun 的密码:tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on wlp5s0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
11:49:41.819450 ARP, Request who-has 192.168.189.55 tell 192.168.189.36, length 28
11:49:42.824331 ARP, Request who-has 192.168.189.55 tell 192.168.189.36, length 28
11:49:43.837669 ARP, Request who-has 192.168.189.55 tell 192.168.189.36, length 28
11:49:43.837669 ARP, Request who-has 192.168.189.55 tell 192.168.189.36, length 28
接上面的2.3.2章节最后,数据如何准确发到192.168.189.137上? 为了实验清晰,我上面还特意用了另一个电脑(和抓包电脑区别开来),但是抓包电脑依然能获取到广播来的日志,说明了网关是无差别的给所有连接到此网段的电脑都发了消息,谁有这个ip,则谁把自己的mac地址返回去。 上面实验是我ping了一个不存在的ip,所以没有正常返回,如果ping一个存在的ip正常返回如下,会响应一个mac地址给请求方,在实际网络环境中,一般情况不可能让你直连服务器,会有很多层路由器,所以一层一层的返回 mac地址,就形成了一个链,所以这就是链路层名字的 由来。
$ sudo tcpdump -nn -i wlp5s0 arp
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on wlp5s0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
12:02:01.497715 ARP, Request who-has 192.168.189.36 tell 192.168.189.137, length 28
12:02:01.497733 ARP, Reply 192.168.189.36 is-at 00:93:37:25:27:0e, length 28