目录
IP协议
传输层并不直接将数据传输到网络上,而是向下层交付到网络层 (IP)
IP协议具有定位主机,将数据包从A主机跨网络传输到B主机的能力
而仅有能力也不够,IP提供的是行动 ,而TCP提供策略(超时重传、拥塞控制等等的策略),就可以顺利将数据包送达
IP协议负责路径选择,通过多个路由器转发,最终到达目标主机

IP报头
IP报文格式:

- 4位首部长度:用于表示IP报头的长度 。它的单位是4字节 ,由于4位比特位最多可以表示到15,【选项】字段一般来说没有,因此IP报头的标准长度就是20字节,即4位首部长度为5。IP报头长度的范围在20,60
- 16位总长度:用于表示IP报文(报头+有效载荷)的长度。它的单位是1字节,最大值到65535。
通过该公式将报头与有效载荷分离:有效载荷长度 = 16位总长度 - 4位首部长度*4 - 8位协议:用于表示IP数据报携带的上层数据应该交给哪个协议处理(向上交付)。 通过协议号确定要向上交付给哪个协议。例如TCP=6、UDP=17,且传输层不只有这俩协议(DCCP、SCTP等)。而且IP之上也不只有传输层,例如还有网络层/控制协议ICMP、IGMP等等
- 16位首部校验和:用于校验报头的完整性。校验失败时,接收方会直接丢弃报文,若传输层是TCP协议,就会触发超时重传
- 8位生存时间:数据是通过路由器转发接力才能顺利到达 ,但如果中间有路由器发生故障,从而造成了例如环路问题等原因让数据包不停的在路由器中转发。
8位生存时间用于表示该数据包的转发跳数,每转发一个路由器,该值-1,当为0时丢弃该数据包。它的默认值并不是固定255,而是根据设备的不同来选择,例如Linux默认64,Windows默认128,路由器/交换机等默认255 - 4位版本号:用于标识该IP报文的IP协议版本号,目前只有两个值:IPv4:4,IPv6:6,该字段是IP报头第一个被读取的字段
- 8位区分服务:用来告诉路由器该数据包的优先级(例如是紧急件还是普通件),从而决定优先处理和转发策略,该字段在公网效果有限,主要用于企业内网或Qos
网段划分
IP地址由两部分组成:IP地址 = 目标网络 + 目标主机 ,当路由器转发数据包时,先根据网络号找到目标网络 ,再根据主机号在该网络中找到具体的主机。因为查找的本质也是排除,而这样只要查找到目标网络,就相当于排除了大部分的主机
举个例子,203.0.113.56(假设属于203.0.113.0网络)要发数据给203.0.117.100(假设属于203.0.117.0网络)。
当数据包到公网上后,会先找到该IP属于的子网,即203.0.117.0,再由该子网的路由负责找到具体主机

IP地址并不是随机划分的,而是有规律的,例如运营商在规划一块IP时,会按照省市来划分子网
中国电信内部的规划可能是113.64.x.x 分配给 广东电信, 113.65.x.x 分配给 贵州电信, 113.66.x.x 分配给 北京电信
广东电信再往下分, 113.64.1.x 给 广州, 113.64.2.x 给 深圳......
子网内的IP都由路由器所管理,它通过DHCP技术自动给子网内新增主机分配IP地址
IP划分
在过去,曾经提出一种划分网络号和主机号的方案,把所有IP 地址分为五类:

- A类 0.0.0.0到127.255.255.255
- B类 128.0.0.0到191.255.255.255
- C类 192.0.0.0到223.255.255.255
- D类 224.0.0.0到239.255.255.255
- E类 240.0.0.0到247.255.255.255
这种分类方法过于浪费IP,例如一个B类地址可以容纳6w多主机,A类则更多,但一个子网内不会存在这么多主机的情况
因此现在的IP划分方案一般为CIDR
它引入子网掩码 来区分网络号和主机号,将IP与子网掩码 按位与 得到的结果即 网络号
例如,当IP为140.252.20.68,子网掩码为255.255.255.0时,网络号即为它们二进制的按位与结果

为了更简洁,可以将该IP和子网掩码合并表示为140.252.20.68/24,后面的24意为子网掩码的前24位为1
子网掩码是在路由器内配置的
私有IP
若真的给每个主机都设定一个唯一的IP地址,就代表全球只有43亿台主机可以入网,这是远远不够的,因此一般来说我们的主机都没有公网IP,而只有内网IP(局域网),当转发数据时,路由器会将该数据转发到公网
私有IP的范围:
- 10.*,前8位是网络号,共16,777,216个地址
- 172.16.到172.31.,前12位是网络号,共1,048,576个地址
- 192.168.*,前16位是网络号,共65,536个地址
一般192.168.*用作于家用路由器,其余用作企业路由器
私有IP意味着只要在该局域网内IP不重复即可,但其他局域网中可能会有相同的IP
由于IP紧张问题,光122.77.241.0/24这个网络号,就可以下发到254台路由器(.0为网络号,.255为广播地址),而这每台路由器由可以连接254个家用路由器,以此缓解IP地址紧张问题(NAT技术)

假设192.168.1.201/24要给122.77.241.3/24发数据,该主机的家用路由器会先转发数据包到它上层的运营商路由器,再由运营商路由器转发到公网的路由器,由公网路由器转发给指定公网IP
一个路由器内至少有两个IP地址:
LAN口IP:该路由器管理的内网的IP ,用于内部通信。例如192.168.1.1,就代表这是192.168.1.0网络内的第一台主机,因此***.1的IP一般是分给路由器**的。当局域网内的主机想与外部通信时,需要先经过LAN口到达路由器,再从WAN口出去到达外部网路
WAN口IP:该路由器所连接的上层子网的IP ,用于外部通信,属于上层网络的主机。当外部主机要与局域网内主机通信时,需要先经过WAN口到达路由器,再通过LAN口到达目标主机
在转发数据时,源IP会不断被替换成路由器的WAN口IP,因为私有地址可以重复,目标主机不知道该转发给谁。当数据要转给内网的设备时,NAT技术会将目的IP转成指定内网IP

当源IP被替换成公网地址时,就可以在公网上转发了
路由器的功能有:转发数据,DHCP(组建局域网),NAT
路由
每个路由器都有自己的路由表(主机也有路由器的功能,因此主机也有自己的路由表),查看路由表可以用route命令(Linux)

- Destination:代表目标网络 ,即本机知道如何到达的目标网络, 若目标Ip是这些网段的其中一个,就可以直接转发给网段,无需向上层路由器转发(例如局域网内部通信),default即默认网关
- Gateway:代表网关 ,即下一跳的地址。*代表不需要网关
- Genmask:代表子网掩码,当要转发数据包时,会先遍历路由表中的Genmask和Destination,找到目标网段
- Flags:表示路由的状态和类型。例如U代表up(路由已启用/可用),G代表Gateway(下一跳地址为路由器地址)
- Iface:代表网络接口,lo代表local本地
Metric/Ref/Use这里不介绍
例如,现在有一个数据包的目的IP是192.168.56.3,遍历路由表中的子网掩码,依次与目标IP 按位与 ,再将结果与目标网络对比,若有相同的就直接转发到该网络。该数据包就会转发给192.168.56.0网段
若数据包的目标IP是202.10.1.2,遍历路由表中的子网掩码后也没有找到相同网段,就会转发给默认网关,让该网关继续查找路由表。只要路由器不认识该网段,就向上转发(默认网关),直到转发到认识该网段的路由器(例如公网路由器)
在不断转发时,网络号会不会变化?
会不断变化。例如一个数据包的目的IP是8.8.8.8,在国际骨干网路由器路由表中,可能是这样的
| Destination | Genmask | 含义 |
|---|---|---|
8.0.0.0 |
255.0.0.0(/8) |
只看前 8 位 ,匹配到 8.x.x.x 就往下一个方向扔 |
即为8.8.8.8/8,它的网段是8.0.0.0
到国内骨干网路由器后,会更精确
| Destination | Genmask | 含义 |
|---|---|---|
8.8.0.0 |
255.255.0.0(/16) |
看前 16 位,更精确地转发 |
即为8.8.8.8/16,它的网段是8.8.0.0
到内部网络路由器后,子网掩码就变为24位
| Destination | Genmask | 含义 |
|---|---|---|
8.8.8.0 |
255.255.255.0(/24) |
看前 24 位,精确定位到具体子网 |
到目标主机所在局域网后,子网掩码变为32位
| Destination | Genmask | 含义 |
|---|---|---|
8.8.8.8 |
255.255.255.255(/32) |
精确匹配到这一台主机 |
IP报文拆分
IP层(网络层)的下层是MAC帧层(数据链路层),而以太网标准规定,一个MAC帧中数据部分不能超过1500字节(MTU)(也不能小于46字节)
决定网络中报文大小是TCP,因此在TCP层的滑动窗口中会根据MSS大小将数据拆分成多个报文 ,以确保符合MAC帧的要求(MSS<MTU,MSS+TCP报头+IP报头<=MTU)
但如果传输层用的是UDP协议,就会发生大于1500字节报文的情况,就需要IP层出面拆分报文(若是TCP协议,IP层报文99%的情况都不需要拆分)
若是IP层拆分了报文,MAC帧层并不知道拆分了报文,只负责将报文发出去,当对方的MAC层收到报文后,也只负责将报文向上交付给IP层,由对方的IP层负责组装报文 并交给上层。可以说IP层负责MAC帧层与TCP/UDP层的解耦工作

在IP报头中,有3个字段上面没有讲,这三个字段用于解决IP的分片与重组:

16位标识长度:标记同一个原始 IP 数据报的所有分片。 发送端每产生一个新的 IP 数据报,这个计数器就加 1。当这个数据报被分片后,所有的分片都会复制并携带这个相同的标识值。
3位标志:这三个比特位每个位都代表不同的意义:

- 第一位是保留位,目前没有用,始终为0
- 第二位如果为1,代表禁止分片,即使报文大小超过了MTU,也不会被分片,而是直接丢弃
- 第三位如果为1,代表这只是其中一片,后面还有其他分片;如果为0,代表这是最后一个分片(或这个数据包没有分片)
13位页偏移:指出当前这个分片的数据,在原始 IP 数据报数据部分 中的起始位置。它的单位为8字节,因此除了最后一个分片外,每个分片的数据部分长度必须是 8 的整数倍,否则无法让后一个分片精确表示页偏移
当【还有更多分片】= 1时,就证明该【16位标识】的报文分片了 ;但如果最先收到的是源报文的最后一个分片,【还有更多分片】= 0,但只要判断页偏移>0,,也可以代表该【16位标识】的报文分片了
【16位标识】字段就可以确保同一个报文的分片都能被识别出来
而【更多分片】= 1、【16位页偏移】= 0 的分片就是起始分片,【更多分片】= 0,【16位页偏移】> 0 的分片就是末尾分片。
当报文开始重组时,可以用当前分片的【16位页偏移】 + 自身长度 算出下一个分片的页偏移应该是多少,这样就可以确保分片被收全 ,也可以确保分片被正确组装
而重组完成并交给传输层时,TCP/UDP报头的【16位校验和】就可以确保分片被正确重组 (其实在这之前,数据链路层的FCS就校验过一次了,如果FCS没查出来才会轮到TCP/UDP出场)
当一个报文被分片成了多个,任意一个分片丢失都会导致对整个源报文进行重传,因此分片会增加丢包概率
MAC帧协议
IP提供的是从主机A到主机B的能力,但从主机A到主机B,需要经过多个路由器,路由器可以直接转发的都是在一个子网里的,因此网络传输的本质是通过一系列的子网转发实现的

在局域网中 ,是通过MAC帧协议通信 的,每个主机的网卡都有一个唯一的sn码,该码称之为MAC地址 ,在全球范围内具有唯一性
MAC帧报头
MAC帧报文格式如下:

MAC帧协议采用定长的策略,报头和报尾固定字节数,以此分离报头与有效载荷
- 通过目的地址与源地址(各6字节,即48位的MAC地址)两个字段,让路由器在局域网内转发数据(标识唯一的主机,路由器就可以根据目的MAC地址找到唯一主机)
- 类型字段指示数据载荷里封装的是什么上层协议 ,不同的值代表不同的协议,例如0x0800代表IPv4数据报,0x0806代表ARP请求/应答......
通过判断类型字段中的值决定向上交付给什么协议(分用) - FCS处于报文尾部4字节,为帧校验序列 ,用于检测帧在传输过程中是否发生了比特错误,采用CRC-32算法
局域网通信原理
在早期以太网,同一局域网内的主机中,任何一个主机发消息,所有主机都可以收到,主机会查看该MAC帧的目的地址,若不是自己就会丢弃

在上图中,主机A给主机D发送MAC帧,就只有主机D会交付给上层
但是由于它们是用一条线连起来的,同一时间只能一个人发 ,否则会发生碰撞 ,此时用的是CSMA/CD 算法用于碰撞检测 :先听后发,边发边听,冲突停发,随机重发。
可以将局域网看作临界资源,任何时刻只有一个主机可以向临界资源中写入数据
为了减少碰撞概率,引入了交换机
将一个局域网划分为两个网段,左侧为网段A,右侧为网段B,同一网段内的通信依旧是转发给所有主机,例如主机A发消息给主机E

但如果主机A要发消息给主机D,即为跨网段转发 ,需要先转发给交换机 ,再由交换机根据目的MAC地址精准转发给主机D

若M1和M5是同时发消息,发生了碰撞,交换机也可以识别出来,不将碰撞数据做转发
此时将一个局域网划分为了两个碰撞域
在现代以太网,每个主机各独用一个网段 ,就不会发生碰撞 ,所有消息都先转发给交换机,再由交换机精确转发给目标主机(广播消息时仍然是所有主机都会收到,例如当主机A获取主机B的MAC地址时,需要广播转发)

IP地址负责描述数据传输的起点和终点,而MAC地址用于局域网内节点间的通信
MTU与MSS
MAC帧报文的数据字段的大小 ,称为MTU (Maximum Transmission Unit**),** 一般为1500字节 ,但也可以调整
MAC帧报文的数据字段即为IP报文(报头+有效载荷)的大小,若 IP 报头为标准报头20字节,有效载荷最大即为1480字节
IP有效载荷即为TCP报文(报头+有效载荷)的大小,若 TCP 报头为标准报头 20 字节,那么有效载荷最大即为 1460 字节(省略UDP)
TCP滑动窗口中,要分成一段一段的小报文发送的原因就在于此,要考虑数据链路层的MTU大小,而TCP中有效载荷的最大长度称为MSS ,该值在三次握手时就会协商好(例如取两者MSS最小值)TCP会尽量让滑动窗口中的每一片报文长度等于MSS,实际长度为 Min(剩余数据, 滑动窗口大小, MSS)
由于每个路由器的MTU可能不同 ,若在网络通信的路上路由器MTU小于报文的实际数据长度,IP层也会分片,但这并不影响由接收端主机重组IP报文

如果发送端发送的报文将不可分片标记位设为 1 ,那么中途当轮到MTU小于该报文的数据长度的路由器收到该报文后就会丢弃报文,并向发送端回传一个 ICMP 报文 ,并附上自己的MTU值 。发送端重发时,就会主动将报文切小,以符合路由器的 MTU 值
ARP协议
当数据经过层层转发终于到达目标主机所在网络时,要转发给目标主机用的不是IP地址,而是MAC地址(要封装成MAC帧)。但在发送方封装的报文中,只有目标主机的 IP 地址。因此需要有一个过程让路由器知道目标主机的MAC地址,这个过程就是ARP协议
ARP协议可以通过IP地址获取MAC地址 ,它处于数据链路层和网络层之间,在IP与MAC帧之间(可以看作在数据链路层)

IP 层完成路由选择后将数据下发给数据链路层,数据链路层 在封装 MAC 帧时发现缺少目标 MAC 地址,从而触发 ARP 协议
ARP协议报头:

- 硬件类型:表示数据链路层的物理网络类型,以太网为1,现在网络几乎都为以太网
- 协议类型:表示要映射的上层协议地址类型,几乎都为IPv4,值为0x0800。虽然0x08DD表示IPv6,但IPv6用的是NDP
- 硬件地址长度:指明 MAC 地址的长度(字节),值一般为6
- 协议地址长度:指明上层协议地址的长度(字节),因为上层协议几乎都为IPv4,因此协议地址长度一般为4
- op:表明该报文是请求还是应答 ,1为请求,2为应答
- 发送端硬件/IP地址:填发送方的信息,硬件地址为MAC地址
- 目的硬件/IP地址:填接收方的信息,++如果是请求,由于不知道目标主机的MAC地址,目的以太网地址填全0(00:00:00:00:00:00)++
即前四个字段一般是固定值
由于数据链路层不知道目标主机的MAC地址,就交给ARP层,ARP将报文字段填充好后,交给下层MAC帧协议并发送

ARP请求是以广播的形式发送 ,即发送给该局域网内的所有主机,广播MAC地址是FF:FF:FF:FF:FF:FF
假设主机A发起ARP请求寻找IP3的MAC地址,主机A将ARP报文封装成MAC帧后转发给交换机,由于目的MAC地址是全F,即广播转发给除发送方的所有主机

主机B&C&D收到后,由于帧类型是0806,所以分用交给 ARP 层 ,ARP 层会先看 OP 类型,因为是请求,直接看目的 IP 地址,不是自己的直接丢弃,因此,最后只有主机C处理ARP请求,并构建ARP应答
由于主机C已经知道是谁发来的ARP请求,ARP 应答报文的源 MAC、IP 和目的 MAC、IP 就可以直接填写,封装MAC帧报文时,直接填填写自己和对方的MAC地址
转发给交换机后,交换机会根据报文内的目的 MAC 地址直接转发给主机 A

主机A收到MAC帧后,由于帧类型是0806,直接交付给ARP层
ARP层先看op类型,发现是应答,将源MAC/IP地址的映射存入本地ARP表
此时再取出被挂起的 IP 数据包,封装目的 MAC,正式发送
ARP缓存表
并不是每次局域网转发都需要发起ARP请求,例如上面例子,当主机A收到ARP应答后,它会将该IP与MAC的映射关系存在本地的ARP缓存表中 ,短时间内再转发该IP时就可以直接查看ARP缓存表中的对应MAC地址 (不同操作系统的ARP缓存表项的生存时间不同)
并且当主机 C 收到主机 A 的 ARP 请求后,也会顺手将主机A的映射关系记录到本地ARP缓存表中
为什么ARP缓存表要有TTL(生存时间)?
当局域网内设备断开重连等操作时,它的 IP 与 MAC 地址会发生变化,因此TTL的存在可以防止无用记录长期占用内存
既然局域网中通信会用到 ARP 协议,由于整个的网络传输就是路由器在一个一个的子网中转发而完成的,那么当路由器转发给下一跳路由器时,也会需要ARP协议获取MAC地址
RARP
ARP 协议用于通过 IP 地址获取 MAC 地址 ,在调试环境中,可能会出现知道MAC但不知道IP的情况,而 RARP 协议是通过 MAC 地址获取 IP 地址的,现在早已被淘汰,被DHCP所取代
ARP欺骗
ARP缓存表默认遵循后来居上(最新覆盖旧有,动态ARP),例如原本有映射关系:IP1 : MAC1 ,后面来了一个ARP应答,IP1 : MAC2,就会将原先的映射覆盖掉
那么如果有黑客疯狂发送ARP应答,就会将正常ARP应答的映射关系覆盖掉

例如上图,在这之后主机A和网关在互相通信时,都会先将数据包转发给攻击者 ,若攻击者转发给真正要通信的主机,就可以窃听未加密的敏感流量 (如 HTTP 明文密码、FTP 传输等)、篡改数据包内容、甚至进行会话劫持 (中间人攻击);若不转发就会让双方断网(ARP断网)。这就是ARP欺骗
想防治 ARP 欺骗,可以用静态 ARP 表(默认为动态ARP)
ICMP
ICMP协议处于网络层与传输层之间(标准来说是网络层),用于测试网络连通性、丢包原因
ICMP报头:

ICMP 会直接将报文交给 IP 协议封装,完全不经过 TCP 或 UDP
例如 ping 、 traceroute 命令就是通过ICMP实现的
telnet是23端口, ssh是22端口, 那么ping是什么端口?
ping命令基于ICMP, **在网络层;**而端口号是传输层(TCP/UDP)的内容. 在ICMP中根本就不关注端口号这样的信息.