feat(WIKI): wiki 2025 BREAKING CHANGE: Older content is categorized into older folders

This commit is contained in:
camera-2018
2024-07-28 23:50:26 +08:00
parent 30d546dbd7
commit 4ff7c80ebf
798 changed files with 558 additions and 294 deletions

View File

@@ -0,0 +1,342 @@
# 9.1 计网速通
> Author: 柏喵樱
>
> copyright reserved
计算机网络是一个非常复杂的系统。在这一章节中,系统的底层实现将被隐去,只留下暴露给用户的内容。
这一章节为 Web 开发入门设计,用于速通 Web 开发和计网的交叉知识,故命名为“计网速通”。
## IP 地址与端口
`1.1.1.1:80`
如你所见,上面一串字符表示一个 IP 和端口,他的格式是 `IP:端口`
IP 是一个由小数点分割成四段的序列,每段数字的取值为 $[0,255]$ , 在上面的示例中IP 是`1.1.1.1`
而端口是一个数字,取值范围是$[0,65535]$ , 在上面的示例中,端口是`80`
所有在互联网上的计算机都会被分配到一个 IP用于标识自己。
现在先抛开具体的实现方式不提,给你一个既定的事实:互联网能够将数据从一个 IP 地址传递到另一个任意的 IP 地址。
现在你已经知道了怎样使用互联网传送数据,先不讨论怎么说,**理论上说只需要知道对方的 IP给他发数据就可以了**。
### 那么端口是干什么用的呢?
想象你的电脑上有很多的应用程序,他们都往互联网上同一个服务器发数据,互联网上的这个服务器也给他们回复数据。当接受到的所有的数据都到了操作系统手里,此时,操作系统如何知道,哪些个数据应该给哪些个应用程序?
解决方案也很简单给发出的数据打一个“标记”这个标记就是端口Port
想象一个港口,里面有很多的码头,一个应用程序他可以接管一个码头,用于自己传输数据。
我们可以从一些数据从 IP 地址 1.1.1.1 的 54321 号码头发送数据到 IP 地址 2.2.2.2 的 12345 号码头,同时在发送的数据上做标记,标记他来自什么地方的几号码头。回复数据的时候自然知道往什么地方回复了。
上面的描述也就是
`1.1.1.1:54321 -> 2.2.2.2:12345`
即,将数据从 1.1.1.1 的 54321 端口发送到 2.2.2.2 的 12345 端口
可以说这个数据包有以下属性
- 源 IP 1.1.1.1
- 源端口 54321
- 目的 IP 2.2.2.2
- 目的端口 12345
## TCP 与 UDP
TCP 和 UDP 两个协议的具体实现都是由操作系统提供的,应用程序发送 TCP 包和 UDP 包一般都是使用操作系统的 API 发送的,所以我们无需关系这两个协议的具体实现细节。
下面通过表格对比两个协议来告诉大家如何选择去使用哪一个协议。
||TCP|UDP|
|---|---|---|
|可靠性 | 有 | 无 |
|速度 | 慢 | 快|
表格很小,但是最本质的区别就是这些了。
TCP 的最大特点就是**可靠交付**,他有一个 ACK 确认机制,简单来说就是对于发送的数据,如果没有收到对方的 ACK 确认收到,他会不断尝试重发,直到他认为无法送达。
UDP 和 TCP 虽然经常一起被提起,也确实属于互联网的同一个层,但从他们的复杂度看,他们并不是两个对等的协议。比起 TCP 有一套非常复杂的算法实现可靠交付流量控制等协议UDP 真的就是单纯发了一个数据包过去,然后什么也不管。
不过不用担心,大家也没多少机会直接接触这两个协议,还是接触 HTTP 居多。如果真的需要做出选择,除非你知道你在做什么,选 TCP。
现在,你应该知道,虽然你不知道具体怎么做,但是从理论上说,你可以选择其中一种协议发送数据到另一台联网的计算机的某个端口上。
如果此时这台计算机的某个应用程序在这个端口使用了正确的协议监听这个程序他能够正确地获取到数据。两个程序之间的点对点p2p通信就这样建立了。
## DNS
DNS(Domain Name System) 域名系统
目前我们已经能够和服务器建立起可靠的连接了,但这与我们日常所见的并不一样。
对于日常使用,如果我要打开一个网页,我会选择使用比如`bilibili.com`这样的东西,这一串字符叫做**域名**
域名的最直观用途是代替你记忆 IP 地址,当你访问 `bilibili.com` 这个网址的时候,一般首先会调用操作系统 API操作系统会代替你发送域名解析请求到 DNS 服务器,最后 DNS 服务器会返回给你域名对应的 IP 地址。
其实你也可以拥有自己的域名这很简单。如果你要搭建你自己的网站,购买域名是逃不掉的,在国内的话还需要备案。
![域名解析后台](https://cdn.xyxsw.site/dnspod-domain.png)
如上图所示,一个域名有很多不同的解析类型,但是目前你只需要知道 A 记录是什么。
A 记录是目前互联网上最主要的记录类型,他的记录值是一个 IPv4 地址(就是上述的 IPv4 是版本号)。
举个例子,域名`aaa.bbb.cn`做 A 解析到 `1.1.1.1`,我们需要设置:
- 主机记录 aaa
- 记录类型 A
- 记录值 `1.1.1.1`
- 其他默认
此时如果你如果将这个域名作为网址使用,浏览器就会通过域名解析拿到 `1.1.1.1`,向 `1.1.1.1` 发送 HTTP 请求获取数据
## HTTP
HTTP 协议用于 WEB 服务器,一般多见于浏览器获取网页内容。浏览器会用 HTTP 协议发送 HTTP 请求到服务器,服务器处理 HTTP 请求并返回 HTTP 响应。很多的 APP小程序和电脑上的应用程序都在广泛地使用 HTTP
HTTP 协议有不少版本,现在互联网上最流行的是 HTTP/1.1 版本,浏览器一般最高支持 HTTP/2.0,最新版本是 HTTP/3.0,下面只讨论 HTTP/1.1
HTTP 的底层是 TCP他基于此规定了一套文本格式用于表达一些信息
单纯说说是说不明白的HTTP 报文分请求和响应两种格式,下面给出实例
> 如果你有兴趣做 HTTP 抓包,推荐用 Yakit本人实习正在做这个产品也欢迎反馈 bug
### 请求
``` http
POST /x/click-interface/web/heartbeat HTTP/1.1
Host: api.bilibili.com
Accept: application/json, text/plain, */*
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6
Content-Length: 397
Content-Type: application/x-www-form-urlencoded
Cookie: balh_server_inner=__custom__;dy_spec_agreed=1; balh_is_closed=; PVID=1; i-wanna-go-back=-1; CURRENT_BLACKGAP=0; buvid_fp_plain=undefined; DedeUserID=74145050; DedeUserID__ckMd5=a31c4db0fb996454; blackside_state=0; b_nut=100;
Origin: https://www.bilibili.com
Referer: https://www.bilibili.com/video/BV1Kx4y1Z7xb/?vd_source=9ec246e4a5695e749fc2f84871669501
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-site
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36 Edg/115.0.1901.188
sec-ch-ua: "Not/A)Brand";v="99", "Microsoft Edge";v="115", "Chromium";v="115"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
start_ts=1690809334&mid=74145050&aid=998480789&cid=1195467370&type=3&sub_type=0&dt=2&play_type=4&realtime=27&played_time=27&real_played_time=35&refer_url=https%3A%2F%2Fmember.bilibili.com%2F&quality=0&video_duration=186&last_play_progress_time=27&max_play_progress_time=27&spmid=333.788.0.0&from_spmid=&extra=%7B%22player_version%22%3A%224.2.4-rc.2132.0%22%7D
```
所见即所得除了部分敏感字段被隐去外HTTP 报文在网络中传输时,就长这样
#### 请求方法
首先看到第一行
`POST /x/click-interface/web/heartbeat HTTP/1.1`
`POST`是请求方法,具体如何使用没有明确的规定,可以参考 Restful 风格Restful 规定的请求方法有
- GET
- POST
- PUT
- DELETE
分别对应查,增,改,删四个动作,这四个动作统称增删查改,英文 CRUDCreate Read Update Delete
其中,一般来说 GET 和 DELETE 两个请求方法是不带负载 (后面有讲什么是负载) 的,但这也不是硬性规定。
如果你从浏览器地址栏打开一个网页,那么他首先会向对面服务器发送一个 GET 请求,而其他类型的请求往往是网页加载过程中 js 脚本向服务器获取数据所带来的的。
#### 请求路径 HTTP 版本号
早期的 Web 服务器采用纯静态 + 文件目录结构,这其实相当于说暴露一个文件夹在互联网上,然后大家使用文件路径获取这个文件夹中的一个特定的文件。
这个格式一直以来都得到了沿用,现代的路径早已经失去了这个固定意义,成为了一种分类和标识。
请求路径可以带请求参数的,上面的例子没有展现出来,类似于
`/shell?cmd=ls&a=b`
这种写法只是一种所有人都遵循的格式,这样的路径带 2 个参数,第一个名字叫`cmd`,参数的值是`ls`,第二个名字叫`a`,参数的值是`b`。
如果出现字符冲突,比如你需要一个参数值为`&`的参数,可以使用 URL 编码,写成`%26`,这是`%+16进制ascii码`的格式。
这一行最后跟一个 HTTP 版本号
#### 请求头header
紧接着的是请求头,其固定格式为`Key: Value`
一行一个请求头,不同的请求头有不用的用途,广泛认可的请求头有
- Host 主机名,也就是域名,如果使用 IP 访问,这里会写成 IP
- Content-Type 表示 Payload 的内容格式
- User-Agent 发 HTTP 包的人用的浏览器类型和版本号
- Cookie 用于存储认证信息等,由服务器设置,浏览器每次请求都会携带
别的可以暂时不知道
请求头也可以自定义,如果你觉得有必要你可以添加你自己的请求头
#### 负载payload
上面的实例是一个 application/x-www-form-urlencoded 类型的 payload这由 Content-Type 规定。他的格式和请求参数是一致的。
负载还有很多种不同的格式,比如 jsonxmlform-data Web 开发那一块应该会讲,这里就不提了。
### 响应
``` http
HTTP/1.1 200 OK
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: Origin,No-Cache,X-Requested-With,If-Modified-Since,Pragma,Last-Modified,Cache-Control,Expires,Content-Type,Access-Control-Allow-Credentials,DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Cache-Webcdn,x-bilibili-key-real-ip,x-backend-bili-real-ip,x-risk-header
Access-Control-Allow-Origin: https://www.bilibili.com
Access-Control-Expose-Headers: X-Bili-Gaia-Vvoucher
Bili-Status-Code: 0
Bili-Trace-Id: 014a52764364c7b4
Connection: keep-alive
Content-Type: application/json; charset=utf-8
Cross-Origin-Resource-Policy: cross-origin
Date: Mon, 31 Jul 2023 13:17:39 GMT
X-Bili-Trace-Id: 369754a5d2179290014a52764364c7b4
X-Cache-Webcdn: BYPASS from blzone03
Content-Length: 51
{
"code": 0,
"message": "0",
"ttl": 1
}
```
#### 协议版本 响应状态码
协议版本不提了
响应状态码有很多种
上面响应了 200 OK 这是最主要的一种对于请求成功的响应,其他常见的有
- 500 服务器内部错误
- 404 服务器找不到资源
- 403 没权限
- 301 永久跳转
- 302 暂时跳转
- 200 成功返回
其中跳转类型会附带 Location 响应头,响应头的内容是要跳转到的地方
#### 响应头
格式和请求头保持一致
在实例的响应头中可以看到很多由 Bilibili 自定义的响应头
其他和请求头基本一致不做讲解
#### 负载 (payload)
这是一个 json 格式的负载,具体参考 Web 开发章节
## TLS
现在大多数的网址都会使用 HTTPS 协议而不是 HTTP其区别在于HTTP 是把上面提到的报文直接放在 TCP 里传输此时如果有人抓包获取了你的报文他是可以看到完整内容的。为了安全TLS 诞生了。
HTTPS 的本质就是在将 HTTP 报文通过 TLS 进行发送,而不是直接通过 TCP 发送。
TLS 建立在 TCP 的基础上,他会通过加密来确保传输过程中数据的安全。
具体如何加解密在这里不讨论,比较复杂,这里只能指条路:服务器想要处理 TLS 握手构建安全传输,服务器需要证书和秘钥。这两个东西是由证书签发机构签发的,免费的证书签发机构最出名的是 Let's Encrypt签发证书最方便的脚本是 acme.sh。
## 常用协议端口
我们在打开一个网页的时候,是不是从来没有考虑过端口的问题?
这是因为 HTTP/HTTPS 协议有个默认端口,分别是 80 和 443不写就是默认端口
下面给一个常用端口列表,随便记一下差不多了
| 应用层协议 | 端口 | 传输层实现 |
| ---------- | ---- | ---------- |
| FTP | 21 | TCP |
| SSH | 22 | TCP |
| SMTP | 25 | TCP |
| DNS | 53 | UDP |
| HTTP | 80 | TCP |
| POP3 | 110 | TCP |
| HTTPS | 443 | TCP |
| Mysql | 3306 | TCP |
| RDP | 3389 | 默认 UDP |
| Redis | 6379 | TCP |
## 公网与内网 --- 真实环境分析
基本的内容介绍的差不多了,下面分析一个简单的网络案例,顺带介绍公网和内网的概念。
相信在看这篇文章的大家都正在使用互联网,如果你正在使用 windows 设备,你可以先按 `win`+`R` ,输入 `cmd`,在弹出的窗口输入 `ipconfig` 你可以看到里面有一串类似于下文的内容:
```powershell
无线局域网适配器 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 教程 <https://www.runoob.com/http/http-tutorial.html>

View File

@@ -0,0 +1,184 @@
# IP 协议
> Author: 柏喵樱
>
> copyright reserved
## IP 协议数据包结构
IP 协议是网络层最主要的协议,几乎所有的上层数据包都需要 IP 协议的承载,我们网络层的第一块内容将从 IP 协议讲起。
下图展示了 IP 协议的报文头部格式,这张图每行代表 32 个 bit也就是 4 个字节byte。如果不计算 Options 这种可选项的话IP 协议的报头长度为 20 个字节。
在头部的后面会携带负载payload这个词可能略显晦涩但实际上就是我们需要发送的数据。
<pre>
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
</pre>
## 版本
第一个字段是 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)

View File

@@ -0,0 +1,147 @@
# 子网与无类域间路由
在上一篇文章中,我们详细讲解了 IP 数据包的结构。一个 IP 数据包确实非常复杂,但现在请你忘掉他,仅在需要的时候翻看相关文章做参考。
你只需要知道一件事 —— IP 头里有一对 IP 地址,分别分别代表这个数据包从哪里来,到哪里去。
在组成一个比较大的网络前,我们需要给一个个孤立的 IP 地址分类。给 IP 分类可以让维护路由表变得更简单CIDR无类域间路由是一种非常良好的分类方法。
## CIDR
我们先看看什么地方会出现 CIDR 这个东西。如果你正在使用 Linux 操作系统,你可以输入命令`ip addr`,他会打印出一串大概这样的内容
> windows 的 CIDR 采用点分十进制掩码,后续介绍
``` bash
baimeow@server:~$ ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether bf:17:21:ab:44:ba brd ff:ff:ff:ff:ff:ff
inet 192.168.1.12/24 metric 100 brd 192.168.1.255 scope global dynamic ens18
valid_lft 2458sec preferred_lft 2458sec
inet6 fe80::bc57:71ff:febb:24b0/64 scope link
valid_lft forever preferred_lft forever
```
其中有 4 个 CIDR分别是 `127.0.0.1/8` `::1/128` `192.168.1.12/24` `fe80::bc57:71ff:febb:24b0/64`我们以 `192.168.1.12/24`为例。
他由一个 IP 地址和一个数字组成中间用正斜杠分割IP 地址就是你的设备的 IP这没有什么特别特殊的。而后面的这个 24 是掩码。这其实表达了很多层意思:
- 设备 IP 是 `192.168.1.12`
- 网络号是 `192.168.1.0`
- 掩码是 24
- 广播地址是 `192.168.1.255`
- 这个 IP 所在的子网拥有的范围的是 `192.168.1.0` - `192.168.1.255`
- 这个 IP 所在的子网可以分配的 IP 范围的是 `192.168.1.1` - `192.168.1.254`
为了理解上面这些东西都是怎么来的,我们需要理解这个掩码是如何作用在 IP 上的,我们先把 IP 地址写成二进制的格式(点分二进制)
`192.168.1.12` -> `11000000.10101000.00000001.00001100`
目前,我们的这个掩码值为 24他的意思是把 IP 地址分成,前 24 位,剩下的 8 位,这两部分,被切除的部分用 0 来填充,于是我们得到了
- 网络号`11000000.10101000.00000001.00000000` -> `192.168.1.0`
- 主机号`00000000.00000000.00000000.00001100` -> `0.0.0.12`
这里由于 /24 刚刚好切到了点上,所以就被非常直观地分成了这样两部分。
在 CIDR 的规则中,将拥有同样的网络号和同样的掩码的 IP 的集合作为一个子网。比如网络号为`192.168.1.0`,掩码为 24 的所有 IP 就是 `192.168.1.0` - `192.168.1.255`这些个 IP他们都在`192.168.1.0/24`这个子网里。
注意,“子网”并不是一个非常抽象或者特殊的概念,他只是从互联网这张大网里取了一段 IP 地址构成子网,就像集合的子集一样。只是我们现在正在使用 CIDR 的规则去划分子网,遵循着 CIDR 的规则用一个网络号和掩码去划分出这样一段 IP。
在这样的一个子网里,我们定义:
- 第一个地址是网络地址
- 最后一个地址是广播地址
- 剩下的地址可以分配给网络内的设备
以上定义是默认行为,其实是可以修改的,比如广播地址就可以不是最后一个地址。
严格意义上说,上面提到的子网一部分应该改称呼为网段,简单起见不细究了。
## 常见保留 IP
了解一下常见的保留 IP 吧,这些保留 IP 不会出现在公网,而是被用于其他特殊用途。
让我抄一下 Wiki 的表格。
| 地址块 ([CIDR](https://zh.wikipedia.org/wiki/无类别域间路由)) | 范围 | 地址数 | 效用域 | 用途 |
| :----------------------------------------------------------: | :---------------------------: | :---------: | :------: | :----------------------------------------------------------: |
| 0.0.0.0/8 | 0.0.0.0 0.255.255.255 | 16,777,216 | 软件 | 用于广播信息到当前主机。[[1]](https://zh.wikipedia.org/wiki/保留IP地址#cite_note-1) |
| 10.0.0.0/8 | 10.0.0.0 10.255.255.255 | 16,777,216 | 专用网络 | 用于[专用网络](https://zh.wikipedia.org/wiki/专用网络)中的本地通信。[[2]](https://zh.wikipedia.org/wiki/保留IP地址#cite_note-rfc1918-2) |
| 100.64.0.0/10 | 100.64.0.0 100.127.255.255 | 4,194,304 | 专用网络 | 用于在[电信级 NAT](https://zh.wikipedia.org/wiki/电信级NAT)环境中服务提供商与其用户通信。[[3]](https://zh.wikipedia.org/wiki/保留IP地址#cite_note-3) |
| 127.0.0.0/8 | 127.0.0.0 127.255.255.255 | 16,777,216 | 主机 | 用于到本地主机的[环回地址](https://zh.wikipedia.org/wiki/IPv4#环回地址Loopback_Address)。[[4]](https://zh.wikipedia.org/wiki/保留IP地址#cite_note-4) |
| 169.254.0.0/16 | 169.254.0.0 169.254.255.255 | 65,536 | 链路 | 用于单链路的两个主机之间的[链路本地地址](https://zh.wikipedia.org/wiki/链路本地地址),而没有另外指定 IP 地址,例如通常从[DHCP](https://zh.wikipedia.org/wiki/动态主机设置协议)服务器所检索到的 IP 地址。[[5]](https://zh.wikipedia.org/wiki/保留IP地址#cite_note-5) |
| 172.16.0.0/12 | 172.16.0.0 172.31.255.255 | 1,048,576 | 专用网络 | 用于[专用网络](https://zh.wikipedia.org/wiki/专用网络)中的本地通信。[[2]](https://zh.wikipedia.org/wiki/保留IP地址#cite_note-rfc1918-2) |
| 192.0.0.0/24 | 192.0.0.0 192.0.0.255 | 256 | 专用网络 | 用于 IANA 的 IPv4 特殊用途地址表。[[6]](https://zh.wikipedia.org/wiki/保留IP地址#cite_note-rfc5736-6) |
| 192.0.2.0/24 | 192.0.2.0 192.0.2.255 | 256 | 文档 | 分配为用于文档和示例中的“TEST-NET”测试网它不应该被公开使用。[[7]](https://zh.wikipedia.org/wiki/保留IP地址#cite_note-rfc5737-7) |
| 192.88.99.0/24 | 192.88.99.0 192.88.99.255 | 256 | 互联网 | 用于[6to4](https://zh.wikipedia.org/wiki/6to4)[任播](https://zh.wikipedia.org/wiki/任播)中继。[[8]](https://zh.wikipedia.org/wiki/保留IP地址#cite_note-8)(已废弃[[9]](https://zh.wikipedia.org/wiki/保留IP地址#cite_note-rfc7526-9) |
| 192.168.0.0/16 | 192.168.0.0 192.168.255.255 | 65,536 | 专用网络 | 用于[专用网络](https://zh.wikipedia.org/wiki/专用网络)中的本地通信。[[2]](https://zh.wikipedia.org/wiki/保留IP地址#cite_note-rfc1918-2) |
| 198.18.0.0/15 | 198.18.0.0 198.19.255.255 | 131,072 | 专用网络 | 用于测试两个不同的子网的网间通信。[[10]](https://zh.wikipedia.org/wiki/保留IP地址#cite_note-10) |
| 198.51.100.0/24 | 198.51.100.0 198.51.100.255 | 256 | 文档 | 分配为用于文档和示例中的“TEST-NET-2”测试 - 网 -2它不应该被公开使用。[[7]](https://zh.wikipedia.org/wiki/保留IP地址#cite_note-rfc5737-7) |
| 203.0.113.0/24 | 203.0.113.0 203.0.113.255 | 256 | 文档 | 分配为用于文档和示例中的“TEST-NET-3”测试 - 网 -3它不应该被公开使用。[[7]](https://zh.wikipedia.org/wiki/保留IP地址#cite_note-rfc5737-7) |
| 224.0.0.0/4 | 224.0.0.0 239.255.255.255 | 268,435,456 | 互联网 | 用于多播。[[11]](https://zh.wikipedia.org/wiki/保留IP地址#cite_note-rfc1112-11) |
| 233.252.0.0/24 | 233.252.0.0 - 233.252.0.255 | 256 | 文档 | 分配为用于文档和示例中的“MCAST-TEST-NET”它不应该被公开使用 |
| 240.0.0.0/4 | 240.0.0.0 255.255.255.254 | 268,435,455 | 互联网 | 用于将来使用。[[12]](https://zh.wikipedia.org/wiki/保留IP地址#cite_note-rfc6890-12) |
| 255.255.255.255/32 | 255.255.255.255 | 1 | 子网 | 用于受限广播地址。[[12]](https://zh.wikipedia.org/wiki/保留IP地址#cite_note-rfc6890-12) |
如果需要搭建自己的比如说家庭网络,寝室网络,一般会选择
- `10.0.0.0/8`
- `192.168.0.0/16`
- `172.16.0.0/12`
此外另外了解一下其他的特殊地址,避免冲突吧
- `169.254.0.0/16` DHCP 获取到 IP 前的临时 IP 地址
- `192.18.0.0/16` 一些代理软件的透明代理模式会解析域名到这里
- `172.17.0.0/16` Docker 默认网段
## 旧闻一则 —— ABCDE 类 IP
很久很久以前,一群自大的人给 IP 随意地划分了 ABCDE 类。很遗憾,我们仍需要了解一下这个历史包袱。
- A 类 0.0.0.0~126.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.1-239.255.255.254 多播
- E 类 240.0.0.0---255.255.255.255 保留段与广播地址
仅作了解,现今已经不具有实际意义了
## 正在消失的 —— 点分 10 进制掩码
当你在 windows 的 cmd 里执行 `ipconfig /all` 时,你可以看到一个点分十进制的掩码。
```cmd
无线局域网适配器 WLAN:
连接特定的 DNS 后缀 . . . . . . . :
描述. . . . . . . . . . . . . . . : Intel(R) Wi-Fi 6 AX200 160MHz
IPv4 地址 . . . . . . . . . . . . : 192.168.0.102(首选)
子网掩码 . . . . . . . . . . . . : 255.255.255.0
获得租约的时间 . . . . . . . . . : 2023年8月20日 19:49:53
租约过期的时间 . . . . . . . . . : 2023年8月21日 00:49:56
默认网关. . . . . . . . . . . . . : 192.168.0.1
```
上面的子网掩码是 `255.255.255.0`,其实就是`/24`
这种格式其实表达的信息更灵活,你可以在掩码的时候掩住前面一段后面一段,中间留一段做主机号,这是没有问题的。
问题在于有点过度设计的了,随意地掩盖住几位只会让网络运维人员心烦,久而久之用的越来越少,就算是用,也只会顺序掩盖前面几位,其实目前碰到的大多数这种格式的掩码他传达的信息 CIDR 也是可以表述的。了解一下,至少目前还是有很多人用这个写法的掩码的。

View File

@@ -0,0 +1,17 @@
# 9.2.3 网络层
> Author: 柏喵樱
>
> copyright reserved
本章节是网络层的开篇章节,我们先做两个约定:
- 没有提及 IP 协议版本,都是 IPv4IPv6 会单独介绍不详细展开)
- 路由表已经配置好了,给 IP 地址就能发到正确的地方(路由技术参照“路由与交换”章节)
以上两个约定适用于所有网络层章节。
在链路层我们已经实现了两个直接相连的设备之间的数据收发,也可以在总线类型的网络上完成数据手法,更成熟一点,可以借助交换机来构建一个具有一定规模的中心化网络。
但中心化是有极限的这必然无法承载这个整个互联网因此我们需要再往上一层定义一个新的概念IP 地址,并完成实现数据包的转发操作,将互联网推向去中心化。

View File

@@ -0,0 +1 @@
# 9.3 路由与交换

View File

@@ -0,0 +1 @@
# 9.4 隧道和代理

View File

@@ -0,0 +1 @@
# 9.5 路由佬入门指南

View File

@@ -0,0 +1,112 @@
# 9.计算机网络
> 本模块来自 DN11(Decentralized Network 11) 成员倾情奉献DN11 最初在生活区 11 号楼群中提出,旨在建立一个跨寝室的大内网。经过一年的发展,已经成为了横跨 11 号楼VidarTeam杭电助手等群体的中型实验性网络。
计算机网络无非一句话,将所有计算机设备连起来。
跨越全球的网络是何其的庞大能够将他们连起来是一项巨大的工程。我可以说Internet 是人类这近 50 年来最伟大的工程。
本讲义的计算机网络部分共分为 5 个章节
## 计算机网络速通
虽然名字看起来像是考前抱佛脚的章节,但他速通的并不是计网这一课程,是做简单 Web 开发所必须具备的计网知识。
在这个章节,我们会讨论到计算机网络的应用层和传输层,重点介绍一些应用层协议。对于传输层,我们只讨论他为 Web 开发提供了怎样的接口或者说功能。
上面提到“应用层和传输层”,或许你现在还不知道计算机网络的五层结构(也有其他划分,但是该划分利于学习),这也没关系,在本章节,可以暂时也不需要知道。
计算机网络这一课程其实往往并不太会涉及到这一块内容,或许网络开发一类的选修课程会讲解这一部分内容。
## 计算机网络基础
这里是计算机网络课程的重点内容,并且适当地做出一些拓展,使其更贴近于现行互联网,尽量让大家对计算机网络拥有一个完整且合理自洽的知识图谱。
写这篇讲义的我本人非常注重知识的自洽,就比如说计网的整个体系,他确实很庞大也需要这么庞大来解决全球的网络问题。
我认为如果你的知识并不能够自洽,那么在你的脑海中这其实就是异常的,不自然的,需要拐弯子才能想明白的。反之,在你的脑海中自洽的知识你是很容易理清其中逻辑的而且不容易忘,因为此时你会觉得“他就该这样,不然呢?”。
在这个章节我们会从物理层开始自底向上地介绍计算机网络,直到讲解完传输层,自底向上是符合历史逻辑的,得先有下层的支持才会有上层。
## 路由与交换
路由与交换的理论知识,并不涉及实践主要应付考试,但为了追求知识体系完整,会比考试内容稍多,但都是理解性质的。其实大家一般也没这个需求,除非专门做运维或者类似方向的开发,大伙都不需要了解具体怎么搭建网络,不会做过多的原理性讲解了。
如果你确实有在真实世界中搭建网络的需求,请移步路由佬入门指南或者拿好你的设备并考虑加入 DN11。
这里主要讨论一下路由器,交换机,各种路由协议和他们工作的位置,还有 NAT最终把这些东西排排好给大家一个完整的互联网模型对比真实互联网做了一些简化但该有的协议类型都会有
## 隧道和代理
其实到现在一个理想化的互联网全图景已经差不多讲解完了,现在要正式完全脱离计算机网络这一课程的范畴了。
隧道和代理也是计算机网络中重要的一部分,他们工作的比较高的层却提供着更低层次的功能(其实路由协议很多也这样)。
前面讲解到,通过配置路由协议可以进行路由交换完成组网,但这仅仅可用于物理设备,如果两台路由器之间并没有网线的直接连接,那么我们的路由协议根本无法工作。
其实真实互联网上充斥着这样的需求,比如异地组网之类的,隧道便应运而生,我们把原始数据包打包在另一个层次比较高的协议中进行传输,用高层的协议来模拟低层的协议。一条虚假的网线(其实不能和网线等价) —— 隧道便诞生了。
代理部分会讲解正向和反向代理,正向代理其实就是一种“隧道”外加上访问目标主机的网络资源的能力,反向代理更多是 Web 开发带来的需求,比如常见的 nginx 反向代理。
## 路由佬入门指南
很多人不理解,不理解也罢。
互联网不是一个很 cool 的东西吗?
这是一个遍布全球由无数独立个体一个一个连接起来而形成的一张网,这难道不酷吗?
在把网络配通的瞬间,所有的 ping 包返回了正确的响应,这难道不振奋人心吗?
身在此却能设计出方案,访问到无比遥远的地方的资源,是难道没有意思吗?
有这样的一个群体,我们普遍称呼他们为“路由佬”,他们便是这样一群,沉迷于配网的一群人。
本章节存在的意义和前面的章节不同,并非是教学,而是劝人快去配网,非常重实践,上面讨论的都是简化模型,理想模型,学习模型,再往下就是实验性网络和真实互联网了,这其实已经脱离了该讲义的宗旨了,所以只会概述概述概述。
## 画个饼先
```mermaid
graph LR
计算机网络 --> 计算机网络速通
计算机网络 --> 计算机网络基础
计算机网络 --> 路由与交换
计算机网络 --> 隧道与代理
计算机网络 --> 路由佬入门指南
计算机网络基础 ---> 物理层
计算机网络基础 ---> 链路层
计算机网络基础 ---> 网络层
计算机网络基础 ---> 传输层
计算机网络基础 ---> DNS与应用层概述
路由与交换 ---> 路由设备
路由与交换 ---> 路由协议
路由与交换 ---> NAT
路由与交换 ---> 真实互联网概述
隧道与代理 ---> GRE
隧道与代理 ---> WireGuard
隧道与代理 ---> L2TP/IPSec
隧道与代理 ---> 正向代理
隧道与代理 ---> 反向代理
路由佬入门指南 ---> openwrt/ikuai/ros/vyos介绍
路由佬入门指南 ---> 主路由,旁路由,单臂路由
路由佬入门指南 ---> 双节点异地组网
路由佬入门指南 ---> 多节点高可用网络概论
路由佬入门指南 ---> 大规模实验性网络概论
路由佬入门指南 ---> 走得更深入...
链路层 ---> 以太网
链路层 ---> ARP
网络层 ---> IP协议
网络层 ---> 子网与无类域间路由
网络层 ---> 路由
网络层 ---> IPv6概述
传输层 ---> 端口
传输层 ---> UDP
传输层 ---> TCP概述
传输层 ---> TCP握手挥手
传输层 ---> TCP滑动窗口
传输层 ---> TCP拥塞控制
路由协议 ---> RIP
路由协议 ---> OSPF
路由协议 ---> 自治域与BGP概述
```

Binary file not shown.

After

Width:  |  Height:  |  Size: 190 KiB