diff --git a/.vitepress/sidebar.js b/.vitepress/sidebar.js index 8e81bb5..e6a4520 100644 --- a/.vitepress/sidebar.js +++ b/.vitepress/sidebar.js @@ -661,8 +661,12 @@ export function chapter9() { text: '9.计算机网络', collapsed: false, items: [ - { text: '9.计算机网络', link: '/9.计算机网络/9.计算机网络' }, - { text: '9.1计网速通',link: '/9.计算机网络/9.1计网速通' }, + { text: '9 计算机网络', link: '/9.计算机网络/9.计算机网络' }, + { text: '9.1 计网速通', link: '/9.计算机网络/9.1计网速通' }, + { text: '9.2.1 物理层' }, + { text: '9.2.2 链路层' }, + { text: '9.2.3 网络层' , link: '/9.计算机网络/9.2.3网络层'}, + { text: '9.2.3.1 IP 协议', link: '/9.计算机网络/9.2.3.1IP协议' }, ] } ] diff --git a/9.计算机网络/9.1计网速通.md b/9.计算机网络/9.1计网速通.md index d6e3249..ae02efa 100644 --- a/9.计算机网络/9.1计网速通.md +++ b/9.计算机网络/9.1计网速通.md @@ -277,6 +277,67 @@ TLS 建立在 TCP 的基础上,他会通过加密来确保传输过程中数 | RDP | 3389 | 默认UDP | | Redis | 6379 | TCP | +## 公网与内网 --- 真实环境分析 + +基本的内容介绍的差不多了,下面分析一个简单的网络案例,顺带介绍公网和内网的概念。 + +相信在看这篇文章的大家都正在使用互联网,如果你正在使用windows设备,你可以先按 `win`+`R` ,输入 `cmd`,在弹出的窗口输入 `ipconfig` 你可以看到里面有一串类似于下文的内容: + +``` +无线局域网适配器 WLAN: + + 连接特定的 DNS 后缀 . . . . . . . : + 本地链接 IPv6 地址. . . . . . . . : fe80::4835:c258:e07d:acc3%24 + IPv4 地址 . . . . . . . . . . . . : 192.168.0.109 + 子网掩码 . . . . . . . . . . . . : 255.255.255.0 + 默认网关. . . . . . . . . . . . . : 192.168.0.1 +``` + +IPv4 地址一栏有一个形似 `192.168.XXX.XXX`的地址,这是一个典型的内网地址,类似的还有很多,比如说 + +- 192.168.0.0 - 192.168.255.255 +- 10.0.0.0 - 10.255.255.255 +- 172.16.0.0 - 172.31.255.255 + +看到以上任意一个都是非常合情合理的,虽然还有其他内网地址,但是那些都比较冷门,可能一辈子碰不到,不用记忆。 + +因此,除了上面列出的 IP 地址,请将他们一律视为公网地址,公网地址是独一无二的,绝对的,内网地址在不同的子网里可以重复使用,是相对的。 + +此外下面还有子网掩码和默认网关,掩码会在后续的内容中介绍,现在知道你只需要知道: + +- 上面显示的 `IPv4 地址` 是你这台设备的 IP 地址 +- 家庭和寝室网络子网掩码默认 `255.255.255.0` +- 默认网关是路由器在内网的 IP,你的设备需要路由器的帮助将数据包从内网转发到公网 + +此刻你可能会有一个疑问,作为一台联网的计算机设备,我可以把数据发送到公网的服务器上,因为我知道他的公网IP,而且这是独一无二的,只要我联网,互联网上的路由设备会尽力帮我把数据送到地方。 + +### 但是,返回的数据该怎么办? + +显然,对面不可能把数据包发给一个内网地址,他只有发给一个公网地址,互联网上的路由设备才知道他要去哪,才能帮他将数据送到地方。 + +问题的答案很简单,我们的路由器,他通过 PPPoE 拨号的方式向运营商拿到了一个公网IP。他在把数据包转发到互联网上前,做了一个网络地址转换的操作,把数据包的源地址替换成了他的公网IP,再找了一个随机端口号,在那里将修改后的数据发送到公网,**这个转换的操作会被路由器记录**。 + +这样,公网上的服务器在收到数据包后也能知道,这个包来自于哪个公网IP的哪个端口,回复的时候就知道发到什么地方了。 + +路由器拿到公网上的服务器回复的数据包后,可以根据做网络地址转换时的记录,逆向推导出他应该将包发送到内网的哪台机器的哪个端口,就完成了数据的收发。 + +绝大多数的家庭或者寝室网络都遵循着这个规则。 + +### 那为什么要这么做呢? + +对于一般家庭网络,有两个简单的理由 + +- 安全,只有你主动连接才能拿到回复,互联网上的设备无法主动访问你的设备 +- IPv4 不够用啦 + +### 其他特殊IP地址 + +- 127.0.0.1 本机,用于自己的设备给自己的设备另一个端口发送数据 +- 169.254.x.x 保留地址,向路由器获取内网地址前会临时使用这个地址,如果你发现你的电脑正在使用这个地址,路由器可能坏了 +- 198.18.x.x 保留地址,但是有些软件会使用这个地址来实现透明代理(tun) + +好,我们的计网速通章节,到此结束,这些计算机网络知识应该足够你做简单的 Web 开发了 + ## 参考资料 - HTTP 教程 diff --git a/9.计算机网络/9.2.3.1IP协议.md b/9.计算机网络/9.2.3.1IP协议.md new file mode 100644 index 0000000..85b2c8b --- /dev/null +++ b/9.计算机网络/9.2.3.1IP协议.md @@ -0,0 +1,185 @@ +# IP协议 + +> Author: 柏喵樱 +> +> copyright reserved + +## IP 协议数据包结构 + +IP 协议是网络层最主要的协议,几乎所有的上层数据包都需要IP协议的承载,我们网络层的第一块内容将从 IP 协议讲起。 + +下图展示了 IP 协议的报文头部格式,这张图每行代表 32 个 bit,也就是 4 个字节(byte)。如果不计算 Options 这种可选项的话,IP 协议的报头长度为 20 个字节。 + +在头部的后面,会携带负载(payload),这个词可能略显晦涩,但实际上就是我们需要发送的数据。 + +
+ 0                   1                   2                   3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|Version|  IHL  |Type of Service|          Total Length         |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|         Identification        |Flags|      Fragment Offset    |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|  Time to Live |    Protocol   |         Header Checksum       |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|                       Source Address                          |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|                    Destination Address                        |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+|                    Options                    |    Padding    |
++-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+                Example Internet Datagram Header
+
+## 版本 + +第一个字段是IP协议版本号,用于标识IPv4和IPv6两个版本,这两个版本的报文格式是不同的。上图展示的是 IPv4 的报文格式 + +## IHL(Internet Header Length) + +就是IP协议的头部部分的长度,单位是 4byte,由于 IP 头一般长度为 20byte,所以这个值一般为 5。如果存在Options字段,这个值会相应增加。 + +## Type of Service + +服务类型,标记服务类型最初是为了对不同服务的数据包做不同的转发策略,比如说哪些数据包应该被优先转发,应该更注重转发延时还是更注重吞吐量一类的问题,除非到运营商层面一般接触不太到。 + +## 数据包总长度 + +Total Length 很好理解就是包括 IP 头在内的 IP 报文的总长度,报文长度上限就是 MTU。 + +## Identification & Flags & Fragment Offset + +这三个字段放在一起讲,他们都是用于控制分片的。 + +我们的 MTU 他一般是 1500,去除 20 bytes 的头部他还能够携带 1480 bytes 的数据,但是现实中的负载很容易就能够超出这个大小,这时候就需要将内容切片分块发送。 + +切片时,会切出许多 1480 bytes 的切片,和剩下的不足 1480 bytes 的部分。对于以上的所有切片,都会给他们加一个自己的 IP 头。这些 IP 头有一个共同点,就是他们具有一个相同的 Identification 用于识别(identify)他们原先是一块的。 + +现在还存在两个问题, + +1. 服务器接收到一个分片后,不知道要不要继续接收 +2. 分片很有可能乱序抵达,服务器不知道分片的顺序 + +对于第二个问题,引入了 Fragment Offset(分片偏移量),他的单位是 byte,用于标识这一个分片的数据,是从原来超长负载的哪个位置开始的。比如对于一个长度为 5000 bytes 的负载,他的几个分片的 Fragment Offset 依次为 0,1480,2960,4440。在收到数据后,服务器只需要按照这个字段重新组装即可。 + +对于第一个问题,引入了 Flags(标志位), Flags 里有三个 Flag,其中最后一位的意义是“后面还有更多分片“,这就相当于告诉服务器,你要继续等待接收其他分片。而当最后的分片抵达时,服务器在知道这是最后的分片的同时,他也能从这个分片的 Fragment Offset里得知前面应该有多少数据,如果缺失,服务器也能继续等待接收。 + +关于Flags的其他两位,最高位是目前保留不使用,永远为0。后面那位的意义是不要分片,这一般是不设置的,他这句话是对传输过程中的路由设备讲的,因为如果途径 MTU 低于当前包长度的链路可能会进行二次分片。如果设置了这个 Flag,转发时再碰到 MTU 低的链路这种包会被直接丢弃同时返回一个 ICMP 包告诉源IP地址的设备发生了什么。 + +## TTL(Time To Live) + +TTL 是一个unsigned int,代表数据包的剩余生存时间,指的是数据包在互联网中还能转发多少时间,单位是秒。 + +虽然单位是秒,但是一般情况下转发耗时是远远低于一秒的,根据 IP 协议的规定,无论转发耗时多少,TTL 应当至少 -1,所以在实践中 TTL 往往指的是转发了几次。 + +一般发往互联网的数据包初始 TTL 为 64 或 128,你可以试试 ping 命令,他会显示一个TTL,这是对面服务器回复的包到自己的设备的时候的 TTL。 + +```powershell +PS C:\Users\bs> ping baidu.com + +正在 Ping baidu.com [39.156.66.10] 具有 32 字节的数据: +来自 39.156.66.10 的回复: 字节=32 时间=43ms TTL=47 +来自 39.156.66.10 的回复: 字节=32 时间=144ms TTL=47 +来自 39.156.66.10 的回复: 字节=32 时间=43ms TTL=47 +来自 39.156.66.10 的回复: 字节=32 时间=42ms TTL=47 + +39.156.66.10 的 Ping 统计信息: + 数据包: 已发送 = 4,已接收 = 4,丢失 = 0 (0% 丢失), +往返行程的估计时间(以毫秒为单位): + 最短 = 42ms,最长 = 144ms,平均 = 68ms +``` + +TTL 减少到 0 的时候,这个数据包会被丢弃,所以如果互联网中出现路由配置错误,以至于产生了一个环,TTL 能够帮助数据包及时停止转发,避免事故扩大最终导致网络设施瘫痪。 + +当路由设备由于 TTL 为 0,而丢弃这个数据包的时候,路由设备还会向源 IP 回复一个 `TTL超时`的 ICMP 报文 + +```powershell +PS C:\Users\bs> ping baidu.com -i 2 + +正在 Ping baidu.com [39.156.66.10] 具有 32 字节的数据: +来自 192.168.1.1 的回复: TTL 传输中过期。 +来自 192.168.1.1 的回复: TTL 传输中过期。 +来自 192.168.1.1 的回复: TTL 传输中过期。 +来自 192.168.1.1 的回复: TTL 传输中过期。 + +39.156.66.10 的 Ping 统计信息: + 数据包: 已发送 = 4,已接收 = 4,丢失 = 0 (0% 丢失), +``` + +traceroute 就是利用这个性质来实现的,通过从 0 开始遍历 TTL 的方式,可以拿到转发过程中的所有路由器的 ICMP 回复,从这些回复中可以读取到这些路由器的 IP。 + +当然 traceroute 不是万能的,真实互联网中广泛存在拦截,不响应 ,改写等等行为,会导致 traceroute 产生丢失或者藏跳等等比较迷惑的结果。 + +```powershell +PS C:\Users\bs> TRACERT.EXE bilibili.com + +通过最多 30 个跃点跟踪 +到 bilibili.com [8.134.50.24] 的路由: + + 1 8 ms 13 ms 2 ms 192.168.0.1 [192.168.0.1] + 2 1 ms 1 ms 2 ms 192.168.1.1 [192.168.1.1] + 3 8 ms 8 ms * 100.66.0.1 + 4 * * * 请求超时。 + 5 * * * 请求超时。 + 6 * * * 请求超时。 + 7 * * * 请求超时。 + 8 * * 8 ms 61.139.121.77 + 9 * * * 请求超时。 + 10 78 ms * * 113.96.5.134 + 11 * 83 ms 43 ms 121.14.50.241 + 12 45 ms 42 ms 41 ms 121.14.24.82 + 13 * * * 请求超时。 + 14 * * * 请求超时。 + 15 * * * 请求超时。 + 16 * * * 请求超时。 + 17 42 ms 50 ms 40 ms 8.134.50.24 + +跟踪完成。 +``` + +上面就是一个真实案例,有很多路由设备在丢弃数据包时并没有给出 ICMP 回复。 + +## 协议 + +协议(Protocol)指的是负载中的数据所使用的协议。这就很广泛了,比如 + +- TCP + +- UDP + +- ICMP + +- Telnet + +- OSPF + +具体可以参考 [List of IP protocol numbers - Wikipedia](https://en.wikipedia.org/wiki/List_of_IP_protocol_numbers) + +## 头部校验和 + +头部校验和(Header Checksum)用于检验传输的数据是否出错,一旦出错直接丢弃。 + +在计算头部的校验和的时候,头部校验和这个字段会被置零,再使用特定算法计算得到校验和,填写到这个位置。 + +这个校验和算法比较简单,就是头部以 16 bits 为单位,取补码再求和 + +注意,由于 TTL 在每次转发中都会改变,所以实际上,每次转发都会重新计算校验和。 + + +## IP地址 + +正如上图的 `Source Address` 和 `Destination Address` 字段所展示的一样,一个 IP 地址占用 4 byte 的存储空间。在书面的写法上,我们用 `.` 将每一个 byte 分割开,例如 `1.1.1.1` 这样更便于人类处理和分类。 + +有一些 IP 地址被用作特殊用途,除了这些 IP 地址外的地址都是公网 IP,一个公网 IP 在整个互联网范围内按照规范来说,只能由一台网络设备占有(也有例外,anycast)。但互联网是复杂的,也有人占用这些地址作为自己的内网地址(例如 tr069),这个由网络运维人员自行分析情景把握。 + +网络地址的分类需要更多的前置知识,我们后续再介绍。 + +## 可选项 + +可选参数(Options)比较繁琐,一般没啥用,有兴趣的可以看看下面参考资料中 RFC 791 对此的描述。 + + +## 参考资料 + +- [RFC 791 - Internet Protocol (ietf.org)](https://datatracker.ietf.org/doc/html/rfc791) +- [Reserved IP addresses - Wikipedia](https://en.wikipedia.org/wiki/Reserved_IP_addresses) +- [List of IP protocol numbers - Wikipedia](https://en.wikipedia.org/wiki/List_of_IP_protocol_numbers) \ No newline at end of file diff --git a/9.计算机网络/9.2.3网络层.md b/9.计算机网络/9.2.3网络层.md new file mode 100644 index 0000000..c74875a --- /dev/null +++ b/9.计算机网络/9.2.3网络层.md @@ -0,0 +1,18 @@ +# 9.2.3 网络层 + +> Author: 柏喵樱 +> +> copyright reserved + +本章节是网络层的开篇章节,我们先做两个约定: + +- 没有提及IP协议版本,都是IPv4( IPv6 会单独介绍不详细展开) + +- 路由表已经配置好了,给IP地址就能发到正确的地方(路由技术参照“路由与交换”章节) + +以上两个约定适用于所有网络层章节。 + +在链路层我们已经实现了两个直接相连的设备之间的数据收发,也可以在总线类型的网络上完成数据手法,更成熟一点,可以借助交换机来构建一个具有一定规模的中心化网络。 + +但中心化是有极限的,这必然无法承载这个整个互联网,因此,我们需要再往上一层,定义一个新的概念,IP 地址,并完成实现数据包的转发操作,将互联网推向去中心化。 + diff --git a/9.计算机网络/9.2计网基础.md b/9.计算机网络/9.2计网基础.md deleted file mode 100644 index 9d9eb05..0000000 --- a/9.计算机网络/9.2计网基础.md +++ /dev/null @@ -1 +0,0 @@ -# 9.2计网基础 diff --git a/9.计算机网络/9.计算机网络.md b/9.计算机网络/9.计算机网络.md index dec12a1..a0586c9 100644 --- a/9.计算机网络/9.计算机网络.md +++ b/9.计算机网络/9.计算机网络.md @@ -95,7 +95,7 @@ 链路层 ---> 数据帧/MAC/CRC 链路层 ---> PPP 链路层 ---> ARP - 网络层 ---> IP地址 + 网络层 ---> IP 协议 网络层 ---> 子网/掩码/CIDR 网络层 ---> IPv6概述 传输层 ---> 端口