第一课:网络理解——从底向上
核心问题
当你打开一个网页,到底发生了什么?网络只是「能上网」吗?
一、物理层:一切的起点
首先,我们想要传输一个东西,需要什么?最基本的——
物理层。我们的交流可以做得很简单:我打印一张图片,人力跑腿给你,然后你再跑回来。这 sound fine——马拉松的故事就是这么干的,RFC 玩笑里的「鸽联网」(IP over Avian Carriers)也是这么干的,以及那句经典:「永远不要低估一辆装满硬盘在高速公路上飞驰的大卡车」。
物理层是一切的起点。我们在这里定义现实中如何传输:从 RJ45 网线上闪烁的电平到空气中激荡的 WiFi 微波。这一层规定了哪些信号是 0、哪些是 1,传输速率如何协商。虽然网络的核心逻辑大部分不在这里,但这一层是你连接物理现实的地方,几乎决定了你整个传输可能的上限。
我们 SE 做的活和 EE 确实不太一样(EE 也很有意思!),往上走。
二、OSI 七层模型 vs TCP/IP 四层模型
为什么要先看模型?
在正式讲每一层之前,先搞清楚我们到底有几层。这是一个常见混乱点:教科书讲七层,实际互联网跑的是四层。
OSI 七层模型(理想蓝图)
TCP/IP 四层模型(实际世界的协议栈)
为什么不一样?
OSI 是 ISO 组织在 1970 年代设计出来的理想蓝图——「网络应该这样分层才优雅」。但 TCP/IP 不是一天建成的,它是在实际部署中长出来的。表示层和会话层的功能在 TCP/IP 里被应用层自己消化了:TLS 管加密、UTF-8 管编码、HTTP Cookie 管会话——不需要专门的层。
关键认知:OSI 告诉你网络可以怎么设计,TCP/IP 告诉你网络实际怎么跑。抽象很好,但抽象不是建好之后才出现的——它是在摔打中长出来的。
三、逐层走过
链路层:认识你的邻居
有了物理层能传 0 和 1 之后,问题来了:没有规范的 0/1 只是噪声。就像是——你已经修好了路,然后我们得看看邻居是谁。
链路层做的事:
发现对方:谁是这条线/这个 WiFi 信道另一端的设备
切片成帧:把比特流切成有意义的帧(Frame),加上头部和尾部
MAC 地址:每张网卡出厂时烧录的唯一标识——你的物理身份证
广播:在同一个广播域内,我可以喊一声「谁是 xx:xx:xx:xx:xx:xx?」所有人都能听到
一个 MAC 广播域的范围是什么? 就是一个局域网段(LAN segment)——同一个交换机下、或者同一个 WiFi 接入点下,还没有经过路由器的范围。限制广播域很重要:如果全世界所有设备都在一个广播域里,每喊一声全世界都要回应,网络瞬间就炸了。
网络层:IP 如何让世界变得可寻址
光有链路层的邻居们其实不够。为了让网络变得越来越大、为了让消息能传播到远方、为了让你的设备可以四处移动——我们引入网络层。
为什么不能直接用 MAC?
MAC 地址是出厂固定的,跟地理位置无关——你的手机从北京飞到深圳,MAC 不变,但网络拓扑变了。全网广播 MAC 不现实——几十亿设备,每发一个包就要全地球广播?做不到。
但还有一个更根本的原因:MAC 地址是扁平命名空间——没有层级,没有前缀,没有任何结构。就像给全世界每个人一个随机编号,你想找一个人,只能挨个问。IP 地址有网络前缀,同一个网络的 IP 可以聚合成一条路由条目
10.0.0.0/8,路由表可以保持简洁。如果全球几十亿设备只靠 MAC 寻址,每个路由器要记住所有设备的 MAC,路由表不可想象。IP 地址解决了这两个问题:IP 是逻辑地址,可以按网络拓扑重新分配,带有位置信息(网络前缀告诉你在哪个网络里);更重要的是,IP 的层级结构让路由聚合成为可能——路由器不需要知道每个设备,只需要知道「去往这个网段走哪个方向」。
但 MAC 不是累赘——它提供了另一种灵活性。正因为它永久不变,你的设备可以无缝移动到不同网络:MAC 还是那个 MAC,到了新网络只需 DHCP 拿一个新 IP,就能继续通信。你不需要手动告诉每一台交换机「嘿,我换地方了」。如果反过来,每换一次网络就得换 MAC 地址——那你每到一个新 WiFi 都得重新烧录网卡,或者重新注册。MAC 的「不变」和 IP 的「可变」是一对完美的搭档:一个提供稳定的硬件身份,一个提供灵活的逻辑寻址。
ARP 缓存也减少了广播的量。同一个局域网内,第一次通信需要 ARP 广播去问 MAC,但问到了就缓存起来。之后的通信直接查表,不再需要广播。所以 MAC 不是只有广播开销——它还有缓存的收益。
ARP:IP 如何变成 MAC
网卡只认 MAC 地址。你 ping 一个 IP——你的电脑怎么知道该把帧发给哪个 MAC?
ARP(Address Resolution Protocol)的工作流程:
你的电脑要发包给
192.168.1.5先查自己的 ARP 缓存表:
192.168.1.5 → xx:xx:xx:xx:xx:xx?有没有?缓存没有 → 在局域网内广播:「谁是 192.168.1.5?告诉 192.168.1.3!」
那个设备收到后单播回复:「我是!我的 MAC 是 xx:xx:xx:xx:xx:xx」
你的电脑把这条记录写入 ARP 表,然后就能发包了
这就是网络层(IP)到链路层(MAC)的映射——ARP 是两层之间的翻译官。你可以把它理解为:IP 是「收件人姓名+地址」,MAC 是「当前他所在的这个房间里的座位号」。从地址到座位的翻译,就是 ARP。
路由表:当目标不在本地
如果目标 IP 不在同一个子网(比如你想访问 8.8.8.8),ARP 广播是问不到的——DNS 服务器不在你的局域网里。
这个时候,路由表上场了:
你的电脑查路由表 → 发现目标不在本地子网
匹配到默认路由
0.0.0.0/0→ 下一跳是网关(通常是路由器,比如192.168.1.1)你 ARP 网关的 MAC,把包发给网关
网关查自己的路由表 → 转发给下一跳 → 再下一跳 → …… → 到达目标
路由表的本质:一张「去往某个网络,下一跳是谁」的查找表。每一跳只看目的地 IP 的网络前缀,找到最长匹配的路由条目,然后转发。你不需要知道整条路径——每一跳只需要知道下一步。
这就是为什么 Internet 能扩展到全球:每一跳只做局部决策,整体路径由全网协作完成。
MTU 与分片:链路层和网络层的两次切割
到目前为止我们讲了两层封装:
链路层把数据封装成帧(Frame),加上 MAC 头和尾
网络层把数据封装成包(Packet),加上 IP 头
但有一个很现实的问题:帧装不下太大的东西。
MTU(最大传输单元)
MTU 是链路层能承载的最大载荷——不包含链路层自己的头和尾,只看它能装多少上层数据。
以太网的 MTU 是 1500 字节。这是一个历史遗留的数字——1970 年代的 Ethernet 标准就这么定的,沿用至今。不同的链路技术有不同的 MTU:
链路层的分片——以太网不分片
每一条链路有自己的 MTU。如果一个帧比链路的 MTU 大——以太网的做法是:直接丢弃,然后向上层报告。「太大了,我不传,你自己想办法。」链路层不帮你切。切数据是谁的活?网络层。
网络层的 IP 分片
当一个 IP 包大于下一跳链路的 MTU 时,路由器会把 IP 包切碎——这就是 IP 分片(IP Fragmentation)。
分片的核心规则:
每个分片都是一个独立的 IP 包(有自己的 IP 头),在网络中独立路由
分片可能在中间路由器上再次被分片(MTU 更小的链路)
重组只在最终目的地进行,中间路由器从来不做重组
IPv4 分片标识靠 IP 头里的三个字段:Identification(同一批分片共享一个 ID)、Fragment Offset(这个分片在原始数据里的位置)、MF 标志(More Fragments——后面还有吗?)
举例:原始数据 4000 字节,经过一个 MTU 1500 的链路:
原始: [IP头 20B] [数据 3980B]
↓ 分片
分片1: [IP头 20B] [数据 1480B] ← offset=0, MF=1
分片2: [IP头 20B] [数据 1480B] ← offset=1480, MF=1
分片3: [IP头 20B] [数据 1020B] ← offset=2960, MF=0(最后一片)
注意每个分片都有一个 20 字节的 IP 头——MTU 1500 减去 IP 头 20 字节,所以每个分片的数据部分最多 1480 字节。
DF 标志与路径 MTU 发现
IP 包里有一个 DF(Don't Fragment,禁止分片) 的标志位。如果 DF=1 并且包大于 MTU——路由器直接丢弃,并回复一个 ICMP 错误:「Packet too big,需要分片但我被禁止了,这个链路的 MTU 是 XXX。」
这看起来像是一个限制,但它促成了一种更好的做法——路径 MTU 发现(PMTUD):
发送端先假设路径 MTU 等于本地链路的 MTU(比如 1500),设置 DF=1
如果路上某条链路的 MTU 更小(比如中间有个 PPPoE 链路 MTU 1492),路由器丢弃并回复 ICMP
发送端收到 ICMP 后降低 MTU 到 1492,重发
重复直到包成功到达——此时找到了整条路径上所有链路中最小的那个 MTU
为什么这比分片好?因为分片有代价:每片一个 IP 头(20 字节 × N 片 = 开销)、接收方要内存缓存所有分片等重组、丢一片就要全部重传。PMTUD 把切数据的活交给发送端(通常在传输层配合 TCP MSS 来完成),避免了中间路由器的分片开销。
IPv6 的激进做法
IPv6 直接禁止了中间路由器的分片。路由器遇到太大的包直接丢并回复 ICMPv6。分片只允许在发送端做。这是对 IPv4 三十年教训的总结:分片是路由器最不想干的活,因为它慢,而且复杂。
帧分片 vs IP 分片——一张图说清楚
应用层: [ HTTP 响应 15000 字节 ]
传输层: [TCP头][ TCP段1 ][TCP头][ TCP段2 ] ... ← TCP MSS 根据 MTU 调整
网络层: [IP头][ 包1 ][IP头][ 包2 ] ... ← IP 分片(如果需要)
链路层: [MAC头][ 帧1 ][尾][MAC头][ 帧2 ][尾] ... ← 每帧不超过 MTU
关键区别:
传输层分段(TCP MSS):发送端在传输层就把数据切成不超过 MTU 的小块——这是最优雅的做法,避免了 IP 层分片
网络层分片(IP Fragmentation):当 TCP MSS 不管用(比如源和目的之间的 MTU 变了),中间的 IP 层兜底分片——粗暴但有效
链路层不分片:帧就是帧,大了直接丢
实际中,TCP 通过 MSS(最大分段大小)协商,几乎总能避免 IP 分片的发生——TCP 会在握手时告诉对方「我能接受的最大段是 XXX(通常是 MTU - 40 = 1460)」,这样 TCP 段自然就不会超过 MTU。IP 分片更多是一个理论上必须存在、但实际上希望永远不触发的安全网。
CIDR 与子网划分
以前用「五类地址」划分网络(A 类、B 类、C 类……),但太浪费了。一个 C 类只有 256 个地址,很多组织不够用;一个 B 类有六万多个,又太多。
CIDR(无类域间路由) 彻底改变了这个局面。
写法:192.168.1.0/24
/24表示前 24 位是网络前缀(标识哪个网络),剩下 8 位是主机号(标识网络里的哪台设备)子网掩码:
255.255.255.0(就是前 24 位全是 1,后 8 位全是 0)可容纳主机数:2^8 - 2 = 254 台(减去全 0 的网络地址和全 1 的广播地址)
常见前缀:
几个特殊地址:
127.0.0.1:回环地址(loopback)——你自己。说「我的服务器是 127.0.0.1,大家来玩」等于说「我在我家卧室里开派对,大家进来吧」——别人进不来。私网地址:
10.0.0.0/8、172.16.0.0/12、192.168.0.0/16——这三段是保留给内部网络的,不在公网路由。组播地址:
224.0.0.0/4——一对多传输。
预告:CIDR 解释了 IP 怎么在子网内分配,但谁拥有这些 IP 段?互联网的顶层如何把几十亿个 IP 组织起来?——这涉及到 AS(自治系统)和 BGP(边界网关协议),我们会在 DNS 章节讲完域名之后一并展开。因为 IP 是机器的门牌号,域名才是你的——而 AS 和 BGP 解释了为什么「拥有一个固定 IP」不是普通人该有的幻想。
DHCP:自动获得网络配置
你的设备刚连上网络的时候,什么都不懂。它不像 MAC 是先天知道的——它只知道自己在 255 里叫。
DHCP 四步握手:
Discover:客户端向
255.255.255.255广播大喊「有人吗?我要 IP!」Offer:DHCP 服务器回复「这儿有!给你
192.168.1.100,租期 24 小时」Request:客户端确认「好,我就要这个了」
Acknowledge:服务器最终确认「成交,附赠子网掩码、网关地址、DNS 服务器地址」
你的手机、电脑、平板都靠这套流程,连上 WiFi 几秒钟内自动配好所有网络参数。你会拿到:IP 地址、子网掩码、默认网关、DNS 服务器地址——四个缺一不可。
IPv6:更大的地址空间,更干净的寻址
IPv4 有 43 亿个地址。听起来很多——但 2026 年的今天,地球上活跃的网络设备远超这个数字。NAT 是应急手段,不是解药。IPv6 的根本动机就一个:地址空间从 32 位扩到 128 位。不是「多一点」,是多了 2^96 倍——多到可以为地球上的每一粒沙子分配一个 IP。
但更大的地址空间带来的不只是「够用了」。它让地址分配回归了层级化、可聚合的优雅结构:全球路由表不再是一堆碎片的拼凑,而是可以按前缀自然地聚合。寻址效率大幅提升。
基于这个新地基,IPv6 顺势把邻居发现和地址配置融为了一体。
NDP(邻居发现协议)
IPv6 没有 ARP。替代它的是 NDP(Neighbor Discovery Protocol),基于 ICMPv6。
NDP 干了比 ARP 多得多的事情:
关键:NDP 不是跑在链路层广播上的——它用组播,只发给需要关心的节点,而不是让整个广播域所有设备都中断一次。
SLAAC(无状态地址自动配置)
IPv6 的地址配置可以不要 DHCP 服务器(虽然 DHCPv6 也存在)。
流程比 DHCP 简洁得多:
设备接入网络,给自己生成一个链路本地地址(fe80::/10)——这个地址只在当前链路段有效,不需要任何配置
设备发送 RS(Router Solicitation,路由器请求):组播问「这网络上有路由器吗?给我前缀」
路由器回复 RA(Router Advertisement):通告网络前缀(比如
2001:db8:1::/64)、自己是不是默认网关、要不要用 DHCPv6设备拿到前缀后,用 EUI-64(从 MAC 地址推导出接口 ID)或者随机生成一个接口 ID,拼出完整的 128 位 IPv6 地址
在正式使用前,设备发送 DAD(Duplicate Address Detection):问「这个地址有人用了吗?」——没有人回应,就确认唯一,开始使用
整个过程不需要任何中央服务器。这就是「无状态」的含义——路由器不需要维护一张「谁拿了哪个 IP」的表。
隐私扩展
EUI-64 从 MAC 地址推导接口 ID 有一个问题:你走到哪,接口 ID 后半段都不变——你在咖啡馆、机场、家里,虽然前缀换了,但地址的后 64 位暴露了你是同一个设备。这给追踪者提供了便利。
所以现代操作系统默认启用了隐私扩展:接口 ID 随机生成,定期轮换,而不是从 MAC 推导。你在不同网络里是完全不同的 IPv6 地址,无法关联。
为什么 IPv6 要把邻居发现和地址配置放一起
因为这两个问题的本质是同一个:「我是谁?邻居是谁?路由器在哪?」
IPv4 把它们拆成了 ARP(纯链路层查询)+ DHCP(集中式配置),这两个协议彼此不知道对方在干什么。IPv6 的 NDP 统一处理——因为查询邻居、通告前缀、发现路由器都发生在同一个场景里:「设备刚加入一个网络,需要搞清楚周围环境。」把相关的事情放在一起处理,设计上干净得多。
传输层:TCP 和 UDP
IP 只负责把包送到目的主机,但一台主机上可能有几十个程序在用网络。端口号登场:区分同一台机器上的不同服务。
TCP:可靠的、面向连接的——就像打电话,先接通,确认对方在,然后有序地对话,保证每一句都被听到。适合:网页浏览、文件下载、邮件。
UDP:不可靠的、无连接的——就像发短信,扔过去就行,不管对方收没收到。适合:视频通话、在线游戏、DNS 查询(快比可靠更重要)。
Socket:网络抽象给你的编程节点。绑定一个 socket 到本地的某个端口,远端设备对你来说就是一个可读可写的端口。网络通信在应用层变成了一件很直觉的事:打开、读写、关闭——跟操作文件一样。
ICMP:不是用来传数据的,是用来 debug 的。你的 ping 和 traceroute 都是靠 ICMP 实现的——它告诉你「这条路通不通」「走到第几跳断了」。
应用层:TLS、编码与 HTTP
TLS/SSL:从 Alice 和 Bob 讲起
以前靠 ActiveX 控件来「保护安全」,但今天不需要了——我们有 TLS。这个故事从零开始,层层加码。
序幕:明文的危险
Alice 想给 Bob 发一条消息:「我的银行卡密码是 123456」。她和 Bob 之间的通信经过咖啡馆的公共 WiFi。
Eve 坐在角落,打开了 Wireshark。Alice 发出的一切——每一个字母——Eve 都能看到。因为 HTTP 是明文的,什么都不加密。
这就是我们面对的第一个问题:任何人都能偷听。
第一层:对称加密
Alice 和 Bob 想了一个办法——约定一个密钥(比如一个很长的随机字符串),用这个密钥把所有消息加密后再发。Eve 抓到包,看到的是一堆乱码。
太好了,问题解决……了吗?
问题来了:Alice 和 Bob 怎么安全地约定这个密钥?他们是异地,不能见面。如果在网络上直接传密钥——Eve 也看到了,那加密就白做了。这就是密钥交换问题。
第二层:非对称加密(公私钥)
数学家发明了一种巧妙的方法:生成一对密钥,它们是数学上关联的,但从一个推导出另一个极其困难。
公钥:可以给任何人,甚至可以贴到电线杆上
私钥:死也不能给,放在自己最安全的地方
规则很简单:用公钥加密的,只有私钥能解开;用私钥签名的,公钥可以验证。
Bob 生成一对公私钥,把公钥发给 Alice。Alice 用 Bob 的公钥加密一个临时对称密钥,发给 Bob。Bob 用私钥解密,拿到对称密钥。
此后,两人用对称密钥高速通信。
Eve 抓到了 Alice 发给 Bob 的加密消息——但她没有 Bob 的私钥,解不开。非对称加密解决了密钥交换问题。
(实际中用的是 Diffie-Hellman 密钥交换——Alice 和 Bob 各自生成一半秘密,在公开信道上拼出一个只有他们俩知道的共享密钥。原理不同但直觉类似:公开的信息 + 各自的秘密 = 共享的密钥。)
第三层:中间人攻击
但是等等。Eve 不只是一个被动的偷听者——她可以主动介入。
Eve 坐在 Alice 和 Bob 中间(逻辑上),做了以下操作:
Bob 发公钥 → Eve 截获,换成自己的公钥 → 发给 Alice
Alice 以为那是 Bob 的公钥 → 用「Eve 的公钥」加密对称密钥 → 发出
Eve 截获 → 用自己的私钥解密 → 拿到了 Alice 的对称密钥
Eve 用 Bob 的真公钥加密 → 发给 Bob
Bob 毫不知情,以为在和 Alice 直接对话
结果:Alice 和 Bob 以为他们在秘密通信,其实 Eve 能看到一切——她解密 Alice 的消息,偷看完,再加密发给 Bob。Bob 的回复她也如法炮制。
这就是中间人攻击(MITM,Man-in-the-Middle)。加密本身没有破,但 Eve 成了通信链条上的一环。
核心问题变了:不再是「怎么加密」,而是——Alice 怎么知道她收到的公钥真的属于 Bob,而不是 Eve 伪造的?
第四层:证书与 CA(权威机构背书)
思路:找一个双方都信任的第三方来作证。
这个第三方叫 CA(Certificate Authority,证书颁发机构)。Bob 去找 CA:「这是我的域名 bob.com,这是我的公钥,请给我做身份证明。」
CA 验证 Bob 确实拥有 bob.com(通常通过让 Bob 在网站上放一个指定文件或配置一条 DNS 记录来证明),然后用自己的私钥在 Bob 的公钥上签名,生成证书。
证书里包含:Bob 的域名、Bob 的公钥、有效期、CA 的签名。
当 Alice 访问 bob.com 时:
Bob 的服务器出示证书
Alice 的浏览器拿出内置的 CA 公钥(操作系统和浏览器出厂时就预装了受信任的根 CA 列表)
用 CA 公钥验证证书上的签名 → 签名有效 → 证书里的公钥确实属于
bob.com用这个公钥安全交换对称密钥 → 开始加密通信
地址栏出现 🔒 图标
Eve 这次的攻击失败了——她没有 CA 的私钥,无法伪造一个能让 Alice 的浏览器验证通过的证书。如果 Eve 用自签名证书冒充 Bob,浏览器会弹出一个巨大的红色警告。
第五层:证书链
为什么不直接让根 CA 给每个网站签名?因为根 CA 的私钥一旦泄露,整个互联网的安全就崩塌了——所以根 CA 的私钥锁在物理保险柜里,从不联网。
实际的运作方式是证书链:
根 CA(内置在系统里)
└→ 中间 CA(根 CA 签名授权)
└→ Bob 的证书(中间 CA 签名)
你的浏览器验证这条链上的每一环:根 CA 签名了中间 CA → 中间 CA 签名了 Bob → 信任链完整。这样根 CA 的私钥极少被使用,安全得多。
第六层插曲:怎么获得一张证书?从纸质证明到 ACME
理解了证书链的信任模型之后,一个自然的问题是:Bob 怎么让 CA 给他签证书?CA 凭什么相信 Bob 就是 bob.com 的主人?
旧时代:你真的要交材料。OV(组织验证)和 EV(扩展验证)证书要求你提交营业执照、公司注册文件、法人身份证明,CA 人工审核。审核周期几天到几周,费用几百到几千美元。这就是为什么以前只有公司和机构才搞得起 HTTPS。
ACME 时代:Let's Encrypt 在 2016 年改变了这个局面。ACME(自动证书管理环境)协议的思路很简单——不需要证明你是谁,只需要证明你控制了这个域名。
怎么证明域名控制权?两种挑战方式:
HTTP-01 挑战:CA 给你一个随机 token,你在你的网站
http://bob.com/.well-known/acme-challenge/<token>路径下放一个包含 token 的文件。CA 访问这个 URL,读到正确的 token → 证明你能往这个域名的服务器上放文件 → 你就是域名的控制者。DNS-01 挑战:CA 给你一个随机 token,你在
bob.com的 DNS 里加一条 TXT 记录_acme-challenge.bob.com,值为那个 token。CA 查询这条 DNS 记录 → 证明你能修改这个域名的 DNS → 你就是域名的控制者。DNS-01 的优势:不需要开放 HTTP 端口,可以给内网机器签发证书,可以签发通配符证书(*.bob.com)。
ACME 客户端(certbot、acme.sh、Caddy 内置)自动完成上述流程,几分钟搞定,一分钱不花,90 天自动续签。
ACME 的代价:
加密强度跟付费证书完全相同——都是同样的 RSA/ECDSA 密钥,同样的 TLS 协议
但 ACME 只验证「你能控制域名」,不验证「你是谁」。钓鱼网站也可以用 ACME 给自己签一个
bankofamerica-secure.com的有效证书——浏览器照样显示 🔒。🔒 图标只保证你在和这个域名的合法控制者通信,不保证这个域名是一个好人ACME 没有可用性保证——Let's Encrypt 挂了你的证书续签就会失败,不过它极少挂,而且有多个兼容的 ACME CA(ZeroSSL、Google Trust Services)
90 天有效期迫使自动化——手动续签根本不可行,这其实是刻意设计:短有效期限制了证书泄露的危害窗口,也倒逼运维自动化
TLS 的三重保险
TLS 不是只做一件事,它同时保证三个东西:
回到最初那个问题:有人怕校园网或代理监控他的银行卡密码——他需要担心吗?
只要浏览器地址栏是 https:// 且证书有效、🔒 图标正常——不需要。中间人看不到明文密码。
那什么是合理的担心?元数据隐私。中间人知道你在访问 bank.com,知道你访问了多长时间、传了多少数据。他们不知道内容,但知道你在跟谁说话——在有些情况下,光这个信息就足够危险了。要保护元数据,你需要 VPN 或 Tor——但那又是另一个故事了。
第六层:当有人叫你安装证书——为什么这很危险
理解了证书链,你现在知道 TLS 安全的前提是什么:你的系统信任的根 CA 列表没有被污染。
但有一种情况:学校的校园网让你「安装这个证书才能上网」,公司的 IT 部门让你「安装我们的根证书来检查加密流量」。
你装了之后会发生什么?
那个机构拥有了一个被你信任的根 CA。他们可以用自己的 CA 给任何网站签发证书——bank.com、mail.qq.com、github.com——你的浏览器都会信任,因为它信任了那个根 CA。然后他们架一个中间人代理,解密你的流量,检查内容,再加密发给真正的目标网站。从浏览器的角度看,🔒 图标还在,一切正常。
这不是「他们破解了 TLS」,而是你亲手把钥匙给了他们。
这里没有技术漏洞——问题是:你是理性人吗?
你敢说你安装的那个证书只用于「合法的网络管理」吗?
你知道那个证书的私钥存在谁的服务器上、有谁可以访问吗?
就算那个机构是善意的——如果他们的 CA 私钥被黑客偷了,黑客可以冒充任何网站给你看,你知道吗?
操作系统和浏览器给你内置的根 CA 列表,是经过几十年安全审计、法律约束、行业监督的。你安装一个来路不明的根证书,等于说:「我信任这个证书的持有者,超过信任整个互联网安全体系。」请确认你清楚你在做什么。
这就是为什么现代操作系统在安装自定义根证书时会弹出最严重的警告——不是因为厂商多事,而是因为他们知道这个操作的后果。
HTTP/1.1
理解了前面的所有层之后,HTTP 就很简单了——它就是应用层的一个文本协议:一个请求方法、一个 URL、一堆 Header 元数据、一个返回状态码和一个 Body(文档)。
请求:
GET /index.html HTTP/1.1,附带Host: example.com响应:
HTTP/1.1 200 OK,附带Content-Type: text/html,然后是一堆 HTML常见方法:
GET(拿)、POST(交)、PUT(改)、DELETE(删)、HEAD(只拿头)常见状态码:
200 OK—— 成了301/302—— 搬家了,去新地址吧(重定向)403 Forbidden—— 你没权限,别想了404 Not Found—— 不存在500 Internal Server Error—— 服务器自己炸了,不关你事
你也可以写一个 HTTP 服务器——没有那么多黑魔法,就是一个读请求、写响应的程序。
四、DNS:IP 是机器,DNS 才是人
IP 地址是给机器读的,但人记不住 142.250.80.46——人能记住的是 google.com。
域名是你自己的品牌。不是 QQ 号,不是微信号——那是平台的,不是你的。域名是你的数字身份,是你的一亩三分地。你可以绑定邮箱、博客、项目主页、个人网站——一切开始于一个域名。
但域名不是凭空工作的。如果 IP 是机器的门牌号,域名是你给门牌号起的人名——那你需要理解:门牌号从哪来?谁拥有这个门牌号段?整个互联网如何协调几十亿个门牌号不冲突?
AS 与 BGP:互联网的「国与国之间」
你可能会想:「如果我有一个固定的公网 IP 就好了。我想去哪去哪,别人也能随时找到我,岂不美哉?」
这个想法很自然,但它背后有一个没意识到的问题:IP 地址不是你想有就有的。 你不是在数字荒原上圈一块地——你是在一个由无数组织通过商业协议和政治博弈共同维护的全球地址系统里,请求一个门牌号。
固定 IP 为什么是幻想(对普通人而言)
全球 IP 地址由 IANA(互联网号码分配机构)统一管理 → 分给五大区域注册机构(APNIC、ARIN、RIPE 等)→ 再分给 ISP(运营商)→ 最后 ISP 分给你。
你在家里拨号拿到的 IP 是动态的——运营商有一个地址池,每次你上线就租一个给你,下线就回收给别人用。你想搞一个固定 IP?申请、审核、加钱。公网 IPv4 总共就 43 亿个,现在几乎分配殆尽,运营商精打细算地周转。
Cloudflare 的 1.1.1.1 看起来只是一个普通的数字,但背后是 Cloudflare 这家公司拥有整个 1.1.1.0/24 这个 IP 段。Cloudflare 能拥有它,不是因为它抢注得早——是因为它是一个拥有 AS 号的互联网基础设施公司,获得了区域注册机构的分配。
所以那个幻想——「我有一个固定 IP,想去哪去哪」——相当于说「我想要一个固定的经纬度坐标,把我家定义在地球表面的那个点上」。但地球上每一寸土地已经有主权归属。互联网的 IP 空间也一样:每个 IP 段都已经被分配给了某个组织,你不是在填空白,你是在已经画好边界的地图上找一个位置。
AS(自治系统)
互联网的顶层不是由一个个路由器拼成的——是由一个个 AS(Autonomous System,自治系统) 拼成的。
一个 AS 是一组路由器的集合,在同一个管理机构下运行统一的路由策略。每个 AS 有一个唯一的 AS 号(ASN)。
每个 AS 拥有一个或多个 IP 段。Cloudflare 的 AS13335 拥有 1.1.1.0/24——所以它能对全世界说「1.1.1.1 是我的」。你没有 AS 号,没有 AS 号就不能拥有 IP 段,不能拥有 IP 段就不能宣告——所以你不能拥有一个属于你自己的公网固定 IP。这就是为什么你需要域名:域名不需要你是 AS,你只需要注册一个域名,然后把它指向你当下能用的任何一个 IP——固定的也好,动态的也好,Cloudflare 的也好。
BGP(边界网关协议)
AS 之间怎么互相知道对方的 IP 段?通过 BGP——互联网的「外交部」。
每个 AS 通过 BGP 向邻居宣告:
「我拥有
1.1.1.0/24。到达这个网段,可以通过我——路径是 AS13335。」
BGP 路由器维护的不是「下一跳 IP」的小表,而是全球 AS 级别的路径表——目前大约 100 万条路由条目。它不管你在一个 AS 内部怎么路由(那是 OSPF/RIP 的事),它只管AS 到 AS 之间怎么走。
BGP 选择路径的依据不是「最短跳数」,而是策略——运营商之间签商业协议:谁给谁付钱、哪条线路优先。这就是为什么跨运营商的访问可能很慢:电信的用户访问联通机房的服务器,BGP 路径上流量要从电信的 AS 跨越到联通的 AS,经过有限的互联带宽。
Anycast:同一个 IP,全球多个位置
这就是 1.1.1.1 的魔法:
Cloudflare 在全球几十个数据中心同时用 BGP 宣告同一个 IP 段。当你的包发往 1.1.1.1 时,BGP 路由表把它导向离你最近的那个数据中心。你在北京 ping 是 3ms,在纽约 ping 也是 3ms——连到的是不同的物理服务器。DNS 的根服务器和大型 CDN 都靠 Anycast 实现全球低延迟。
所以你看:「拥有一个 IP」这件事,根本不是普通人玩的游戏。但拥有一个域名,人人都可以。 你把域名解析到 Cloudflare,Cloudflare 用 Anycast 帮你把流量分发到全球——你不需要自己有 AS 号,不需要 BGP,不需要跟运营商签协议。你只需要知道,DNS 把你的域名翻译成 IP,然后互联网的路由基础设施帮你送到。
校园网是什么
校园网本质上是一个 AS 或者一个 AS 的一部分。比如 CERNET(AS4538)连接全国高校。每个大学在 CERNET 下面有自己的 IP 段。
你宿舍上网的路径:
你的电脑 → 宿舍交换机 → 楼宇汇聚 → 校园核心路由器 → CERNET → 运营商骨干 → 目标
特征:几万人共享出口带宽(晚高峰卡)、内部互访不走公网(同校传文件飞快)、教育网专属资源(论文数据库走 CERNET 免费)、可能接多出口按目的 IP 选路(策略路由)。
为什么跨网慢
电信、联通、移动各有各的 AS,它们之间的互联带宽有限——毕竟商业上不是一家人。晚高峰跨网,就像所有车挤一座窄桥。这就是为什么大网站要在各运营商机房部署服务器——尽量让用户不出自己的运营商内网就完成访问。
总结:DNS 之所以重要,不只是因为「人能记住域名」,而是因为域名让普通人可以参与互联网的地址系统——你不需要拥有 AS 号、不需要 BGP 宣告、不需要固定 IP。你只需要一个域名,然后把它指向你当下能用的任何地方。
DNS 解析过程
你在浏览器输入 www.example.com:
浏览器查自己的 DNS 缓存 → 有就直接用
操作系统查自己的缓存和 hosts 文件
向本地 DNS 递归解析器(通常是你的路由器或者运营商提供的)发起查询
递归解析器从根域名服务器开始迭代:
问根服务器:「
.com的 NS 在哪?」问
.com服务器:「example.com的 NS 在哪?」问
example.com的权威服务器:「www.example.com的 A 记录是?」拿到结果:
www.example.com → 93.184.216.34
递归解析器把结果返回给你的浏览器,浏览器拿到 IP,可以发起 HTTP 请求了
常见 DNS 记录类型
DNS 劫持与安全
因为 DNS 查询默认是明文的(UDP 53 端口),中间人可以伪造响应,把你引到假网站。这就是 DNS 劫持。
解决方案:
DNSSEC:给 DNS 记录加数字签名,防止篡改
DNS over HTTPS(DoH)/ DNS over TLS(DoT):把 DNS 查询加密,中间人看不到也改不了
这仍然是正在进行中的战斗——DNS 是互联网最脆弱也最关键的环节之一
URL 的结构
https://www.example.com:443/path/to/page?key=value#fragment
└─┬──┘ └──────┬───────┘└┬┘└────┬──────┘└───┬───┘└──┬────┘
scheme host port path query fragment
一切都是这个格式——理解 URL 就理解了你在互联网上能定位到的几乎一切资源。
五、NAT 与虚拟专用网
NAT:共用公网 IP
全球 IPv4 地址早就用完了。你家所有设备(手机、电脑、平板、电视)都用一个公网 IP 上网——这就是 NAT。
你的路由器维持一张 NAT 表:内部IP:端口 → 公网IP:随机端口 → 目标服务器。服务器回包时,路由器查表,把包转发回正确的内部设备。
代价:NAT 破坏了互联网的端到端原则。外部设备无法主动连接你内网的设备——因为公网上只有你的路由器,你的电脑对外部是不可见的。这就是为什么有些 P2P 软件没法直接建立连接。解决思路:STUN(帮你知道你的公网 IP 和端口)、TURN(中继转发)、UPnP/NAT-PMP(自动端口映射)。
意外的好处——天然的防火墙:NAT 最初只是为了解决地址不够用,但它意外地提供了一层被动防御。因为外部发来的包如果没有对应的 NAT 映射条目,路由器直接丢弃——外面的人根本找不到你内网的设备。换句话说,NAT 让内网设备「默认不可见」。在 IPv4 时代,这大幅降低了普通家庭被直接扫描攻击的风险。这也是为什么 IPv6 的推广需要考虑「没有 NAT 之后,防火墙该怎么做」——在没有 NAT 的纯 IPv6 网络里,每个设备都有公网地址,安全策略必须显式配置,而不是靠 NAT 顺便帮你挡住。
防火墙
NAT 的「被动防御」只是一个粗糙的副作用。真正的防火墙是主动设计的安全边界。
无状态防火墙:只看每个包本身——源 IP、目的 IP、端口。规则通常是白名单模式:允许什么,其余全丢掉。比如:「只允许外部访问我的 80 和 443 端口,其他端口一概拒绝。」
有状态防火墙:不只是看单个包,还追踪连接状态。它记得「这个包是内部先发起的连接的回复」,于是放行。来自外部的新连接请求(SYN 包)尝试访问内部端口——直接丢弃。这就是你家路由器默认的行为:你可以上网,外面的人连不进来。
最简规则——白名单思维:
允许 出站 所有 (你可以访问任何网站)
允许 入站 已建立连接 (你发起的请求的回复可以进来)
拒绝 入站 所有新连接 (外部不能主动连你)
NAT、防火墙和分层的关系:NAT 在网络层干活(改 IP 头和端口),但它的行为在传输层产生了防火墙般的效果(追踪连接状态)。它们不是一回事,但在家庭路由器里,NAT 往往和防火墙规则一并工作——这就是为什么很多人分不清它们。简单来说:NAT 的主要目的是地址不够用,防火墙的主要目的是安全策略。NAT 顺便帮了点安全的忙,但它不是安全方案。
虚拟专用网
场景:两地的网络想要连起来,拉一条超长专线不现实。
最简单的想法:公开一个服务器,让它帮我把数据转发到内网——这是一种跳板/代理的思路。但如果我们加上加密和认证,让中间的公开网络对你来说像是一条私人专线——这就是 VPN。
一个 VPN 需要回答三个问题:
你是谁? → 认证(密码、证书、密钥对)
数据会不会被偷看? → 加密
数据有没有被篡改? → 完整性验证
IPSec 是最标准的三层 VPN 实现,直接嵌入网络层。但我们还有更新的手段。WireGuard 就是一个很好的例子:简单——一个端口就好;来了才回复(不响应未认证的包,端口扫描扫不到);核心逻辑:你的私钥解密对方用你公钥加密的数据,每个 peer 都持有一对公私钥,互相配置对方的公钥。
一个常见的疑问:「为什么我们常见的都是三层 VPN?」因为 IP 是互联网的通用语言——三层 VPN 可以承载任何上层协议(TCP、UDP、ICMP),适用于绝大多数场景。二层 VPN(如 VXLAN)更常用于数据中心和云计算——把物理上分散的机器连成同一个虚拟局域网。
六、Debug 的方法论
网络出问题是常事。学会 debug 比学会配置更重要。
在开始分层排查之前——先检查物理层的幽灵。 网线松了吗?USB 网卡驱动掉了没(dmesg 看一眼)?路由器是不是摸起来烫手——过热导致间歇性丢包?WiFi 信号是不是隔了三堵墙?很多时候,你对着 MTU、TCP 连接数、防火墙规则排查了半小时,最后发现是网线没插紧或者路由器该重启了。物理层的问题比你想象的多得多。花十秒钟做物理检查,可能省下几十分钟的分层排查。
分层排查原则:从底层开始。网线插了吗?IP 拿到了吗?DNS 解析成功了吗?每一层都能独立验证。
基本工具:
核心心态:不要猜,要验证。每一步你都可以检验。理解了每一层在做什么,你就不会被「连不上网」吓到——你会有条不紊地一层层排查过去。
实战:访问一个网站出问题,怎么逐层排查
你输入 https://example.com,浏览器没加载出来。你的第一反应不应该是「网炸了」然后开始重启路由器——你应该看浏览器到底告诉了你什么。
场景一:ERR_NAME_NOT_RESOLVED 或 NXDOMAIN
DNS 解析失败。这个域名不存在,或者你的 DNS 坏了。但你先别急着修自己的网络——你还没确定问题在谁那边。
操作流程(先确认外部,再排查本地):
用在线 DNS 检测工具(whatsmydns.net 之类)查一下这个域名的全球解析情况 → 如果全球各大 DNS 节点都解析成功,说明网站本身没问题,问题在你本地的网络环境
如果在线工具显示全球都解析失败 → 这是对方域名配置的问题(A 记录或 CNAME 记录配错了、域名过期了、DNS 托管商挂了),跟你没关系
全球正常、你本地不行 → 开始排查你本地的 DNS:
dig example.com A @8.8.8.8→ 换 Google DNS 绕过你本地的递归解析器。能通→你的本地 DNS 服务器有问题(运营商 DNS 抽风,或者你配的自定义 DNS 挂了)检查
/etc/resolv.conf(Linux)或网络设置里的 DNS 服务器地址是不是配错了
如果是你自己管理的域名 → 去 DNS 托管商检查 A 记录或 CNAME 记录还在不在。很多时候是改完忘了等 TTL 生效,或者手滑删了记录
结论:先确认网站确实可通,再看是不是自己的网络环境问题——这样更保险。 在线工具一步就能排除对方的问题,省得你修了半天自己的 DNS 才发现根本没坏。
场景二:ERR_CONNECTION_REFUSED
DNS 解析成功了,拿到了 IP,但对方服务器拒绝连接。
操作流程:
ping <IP>→ 如果 ping 通,说明网络可达,但目标端口没在监听(服务没启动?端口号写错了?)curl -v http://<IP>:80→ 直接请求,看返回什么如果 ping 不通 → 跳到场景五,继续往下排查
结论:能通但拒绝连接 = 服务端没在听。不是你的问题。
场景三:502 Bad Gateway
服务器返回了 HTTP 502。大概率不是你的问题。
502 的意思是:前端代理(Nginx/Cloudflare)正常工作,但它背后的源站(真正的应用服务器)挂了或者返回了无效响应
浏览器、网络、DNS 都正常——问题在对方的服务器架构内部
你能做的:等他们修。刷新一下有时候管用(因为他们可能在重启服务)
其他常见状态码速查:
500:服务器内部错误,跟你没关系502:网关错误,代理找不到源站503:服务暂时不可用(通常是在维护)504:网关超时,源站响应太慢
这四兄弟你都只能等对方修。
场景四:连接被重置(ERR_CONNECTION_RESET / RST)
TCP 连接被对方一个 RST 包粗暴地掐断了。
操作流程:
先刷新。有时候就是偶尔的网络波动,重试就好了
如果一直 RST:
用在线连通性测试网站(比如
isitdownrightnow.com或downforeveryoneorjustme.com)确认是不是只有你不行如果只有你不行 → 可能是 SNI 阻断。某些网络中间设备会检查 TLS 握手中的 SNI 字段(你要访问的域名),匹配到黑名单就直接 RST。换个网络(比如手机热点)试试,如果可以了——说明是在你的网络上被阻断了
如果只有你不行且换网络也不行 → 检查是不是你的代理/VPN 在中间做了什么事,或者你本机的防火墙/杀毒软件在拦截
结论:偶发 RST = 刷新就好。持续 RST 且只有你不行 = 大概率是网络层面的阻断或本地安全软件拦截。
场景五:连 IP 都 ping 不通
这是网络层或以下的故障。
操作流程(从底向上):
链路层:
ip addr看有没有分配到 IP。没有?检查网线/WiFi 连接。有 IP 但 169.254 开头?这说明 DHCP 挂了,你拿了个自动分配的无效地址链路层继续:检查路由表
ip route。默认路由(default via x.x.x.x)在不在?网关的 IP 正常吗(应该是跟你的 IP 同一个子网)?网络层:
ping <网关IP>→ 能通说明本地网络和路由器之间正常。不通?可能路由器挂了,或者你连的不是你以为的那个 WiFi网络层继续:
ping 8.8.8.8→ 能通说明你能出网关到达公网。不通但网关能通?检查路由器的 WAN 口状态(登录路由器管理页面看看有没有拿到公网 IP)DNS:IP 能通但域名不通?回到场景一,查 DNS
定位法则:先确定你在哪一层断了。
前三步都在本地就能排查——你不需要公网就能验证 80% 的基础问题。
场景六:证书错误(NET::ERR_CERT_*)
浏览器弹出「您的连接不是私密连接」或者「证书无效」。
先不要点「继续访问(不安全)」。看一眼错误细节:
证书过期 → 站长忘记续签了。Let's Encrypt 的证书只有 90 天有效期,很多个人站点忘了自动续期
证书域名不匹配 → 证书是给
example.com签的,但你访问的是www.example.com(或者反过来)。检查一下 URL自签名证书 → 这是对方自己签的,不是 CA 签的。可能是内部系统(公司内网、路由器管理页面),也可能是一个配置错误的网站
证书颁发者不受信任 → 你的系统不认这个 CA。可能:
你之前装过某个组织的根证书(回忆一下——学校让你装过吗?公司 IT 让你装过吗?)→ 你正在被中间人攻击(或者合法的流量检查,取决于那个组织是否可信)
操作系统的根证书列表太旧了(更新系统)
⚠️ 铁律:绝不在显示证书警告的页面上输入密码。🔒 图标没了 → 加密还在但身份认证失效了 → 你可能在和 Eve 通信。
场景七:407 Proxy Authentication Required
HTTP 状态码 407。你通常不是从浏览器报错页面看到它——更多是在终端里 curl 一个 API 或者在代码里调接口时碰到。
407 的意思是:你的请求经过了一个代理服务器,代理需要认证,但你没给凭据(或者给错了)。
和 401 Unauthorized 的区别:401 是目标服务器要求认证;407 是中间的代理要求认证。目标还没见到你的请求——代理就把你拦下了。
常见触发场景:
公司内网的代理:所有出站流量必须通过代理,代理要求员工登录(域账号或专用账号)
某些付费代理服务
处理方式:
先搞清楚代理要什么认证:Basic Auth(用户名密码 Base64 编码)还是 NTLM(Windows 域认证)
curl 里加
-U username:password或在请求头里手动加Proxy-Authorization: Basic <base64>首先要确认代理地址本身对不对:
echoHTTPS_PROXY
配置代理的常见好处:
权限控制:公司内网代理限制谁能访问什么,按员工身份分级
缓存加速:代理缓存热门资源(全公司几百人下载同一个 npm 包,内网直接返回,不耗出口带宽)
审计:记录所有外发请求——你访问了什么、什么时候、传了多少数据
终端里配代理的标准操作:
export HTTP_PROXY=http://proxy.company.com:8080
export HTTPS_PROXY=http://proxy.company.com:8080
# 某些不走代理的例外
export NO_PROXY=localhost,127.0.0.1,.internal.local
配完之后 curl、pip、npm 会自动走代理,不需要每个工具单独配置。
一句话:HTTP_PROXY 环境变量告诉你的工具「走哪个门」,407 是那扇门告诉你「进门要先刷卡」。只配了门没配卡,就撞 407。
总结流程——你拿到一个报错,怎么想
浏览器报错
├→ 包含 "DNS" / "NXDOMAIN" / "resolve" → 场景一,查 DNS
├→ 包含 "refused" → 场景二,服务没启动
├→ 包含 "502" / "500" / "503" / "504" → 场景三,等对方修
├→ 包含 "reset" / "RST" → 场景四,重试,排查阻断
├→ 包含 "cert" / "不安全" → 场景六,别输密码,看证书细节
├→ 包含 "407" / "proxy" → 场景七,检查代理地址和凭据
└→ 什么都没有/连接超时 → 场景五,从底向上逐层 ping
记住一句话:每一层都可以独立验证。永远不要猜——用工具去问。
七、课后测试
哪些地址不是公网地址?为什么它们不能直接在公网路由?
一个 MAC 广播域的范围是什么?为什么我们要限制广播域的大小?
为什么上层应用要用 IP 或 DNS 解析的 IP 作为通信目标,而不是直接使用 MAC 地址?
有人说「我的服务器是 127.0.0.1,请大家来玩」。这里犯了什么错误?(请解释回环地址的含义)
你的数据包从知道目标 IP 到真正发出去,中间经历了什么?网卡只认 MAC,IP 如何变成 MAC?如果目标不在本地子网,数据包经过网关时,NAT 是如何通过共用 IP 伪装成你的?
接上题,NAT 破坏了网络的端到端性,会带来什么后果?试着解释为什么一些 P2P 软件没法直接和你建立连接。(提示:内网地址不可全局路由,可搜索 STUN)
单个 IP 包没有状态。很多应用程序希望像读写本地文件一样使用网络连接——数据之间要有顺序、不能丢。我们的解决方案是什么?
有人害怕校园网或者代理监控他的银行卡密码。试着从 TLS 的角度解释为什么他的担心是不必要的(以及,什么是他仍然需要担心的)。
TCP 和 UDP 各自的特点是什么?各自适合什么场景?试着猜猜以下应用用的是 TCP 还是 UDP:网页浏览、视频通话、DNS 查询、文件下载、在线游戏。
HTTP 状态码有哪些常见的?各自什么意思?哪些问题你可以自己解决,哪些是服务器端的问题?
试着阐述虚拟专用网的作用。为什么我们常见的都是三层 VPN?(提示:想想 IP 在整个网络架构中的位置)
课后扩展:虚拟机网络、Linux 网络调参、虚拟网卡、TUN/TAP 设备——整个网络栈的每一层都可以被虚拟化。
八、扩展提高:网络世界的更多角落
以下内容供感兴趣的同学自行探索。每一段是一个独立的小专题,三五分钟就能建立基本概念。
一个洞见:互联网的核心协议(IP、TCP、BGP)定型于几十年前,全量升级整个网络几乎不可能——你不可能某天一觉醒来全世界的路由器都换了新协议。但工业界并没有因此停下。Overlay 网络在现有 IP 之上虚拟出新一层(Tailscale、VXLAN),SDN 把控制逻辑从硬件抽到软件(Google 的 B4 广域网控制器把链路利用率拉到接近 100%),QUIC 在 UDP 之上重写了整个传输层——这些都是在不更换底层基础设施的前提下,在更高层或者终端修改实现来解决问题的范例。网络没有全量升级的机会,但我们有在现有地基上盖新楼的办法。
HTTP 生态进化
WebSocket:HTTP 是「你问我才答」,但聊天、游戏、股票行情需要「服务端主动推给你」。WebSocket 在 HTTP 握手之后把连接升级为全双工通道——双方随时可以发消息,不需要反复握手。和 HTTP 的区别就像写信 vs 打电话。
HTTP/2:HTTP/1.1 一个连接同一时间只能处理一个请求(队头阻塞),而且每次请求都要带一坨重复的 Header。HTTP/2 引入了多路复用——一个 TCP 连接上同时跑多个请求流,互不阻塞;Header 压缩(HPACK)去掉了重复传输;服务端可以主动推送资源(比如 HTML 里引用的 CSS,不等你请求就提前给你)。但 HTTP/2 仍然跑在 TCP 上——TCP 层的丢包还是会阻塞所有流。
HTTP/3(QUIC):直接把 TCP 换成了 UDP。QUIC 在 UDP 之上实现了类似 TCP 的可靠传输,但做了关键改进:每个流独立,流 A 丢包不影响流 B 的数据到达;支持 0-RTT 握手,之前连接过的服务器可以零延迟恢复通信;连接迁移——WiFi 切 4G 不需要重新握手。目前 YouTube、Google 全部走 HTTP/3,你已经在用了。
CORS(跨域资源共享):浏览器出于安全默认禁止一个域名的 JS 去访问另一个域名的数据(同源策略)。CORS 是一种协商机制:目标服务器通过 HTTP Header 声明「我允许哪些域名跨域访问我」。浏览器发一个预检请求(OPTIONS)去问,目标同意才放行。你写前端 fetch 报跨域错误——不是 bug,是设计。
HTTP 缓存:浏览器不会每次都重新下载同一个文件。Cache-Control 头告诉浏览器「这个资源可以缓存多久」,ETag 头提供版本号——内容没变就用本地的,不用重新下载。CDN 节点也是靠这一套机制决定要不要回源站拉新内容。
CDN:你在北京访问一个托管在纽约的网站,原始服务器在万里之外。CDN 在全球部署边缘节点,把你的静态资源(图片、CSS、JS)提前缓存到离你最近的节点。DNS 解析时把你导向最近的 CDN 节点 IP(通常靠 Anycast),你实际访问的是北京的 CDN 节点,不是纽约的源站。原理简单:把数据提前搬到离用户近的地方。
传输层深入
TCP 报文结构:每个 TCP 段有一个 20 字节的头。关键字段:
端口号(源 + 目的):找到哪个进程
序列号(SEQ)和确认号(ACK):给每个字节编号,接收方确认「我已经收到第 N 个字节了」,保证不丢不重不乱
标志位:SYN(建立连接)、ACK(确认)、FIN(结束)、RST(强制断开)
窗口大小:告诉对方「我还能收多少」,防止发送方发太快把接收方撑死——这就是流量控制
RST 攻击:TCP 的 RST 标志是设计来优雅处理异常的——「我不认识这个连接,请断掉」。但攻击者可以伪造一个 RST 包:只要猜对源/目的 IP、端口和序列号(在窗口范围内的 SEQ),接收方就会立刻断开连接。早期 TCP 序列号可预测,RST 攻击很容易。现代系统要求 RST 的序列号精确匹配,难度大了很多——但在同网络内依然可行。
UDP 报文结构:比 TCP 简单太多——源端口、目的端口、长度、校验和,然后就是数据。没有序号,没有确认,没有流量控制。快,但不负责。所以 QUIC 在 UDP 之上自己做了一套可靠的传输层。
BBR(拥塞控制算法):传统 TCP 拥塞控制(CUBIC)靠「丢包」判断拥塞——丢包就减速。问题是路由器缓冲区满了才丢包,等丢包时延迟已经爆了(这叫 bufferbloat)。Google 的 BBR 不再基于丢包,而是持续探测链路可用带宽和最小延迟,找到一个既不塞满缓冲区又能跑满带宽的平衡点。YouTube 部署 BBR 后吞吐量大幅提升,QUIC 也用 BBR 作为默认算法。BBR 没有改 TCP 协议——它只换了内核里的拥塞控制实现。这就是「修改实现而不动协议」的例子。
RDMA(远程直接内存访问):TCP 的开销不只在网络——数据到达网卡后还要经过内核协议栈层层处理、拷贝到用户空间,CPU 开销巨大。RDMA 让网卡直接读写远端机器的内存,绕过 CPU 和内核,延迟从毫秒级降到微秒级。高性能存储和 AI 训练集群大量依赖 RDMA。这算另起炉灶——不是修补 TCP,而是完全绕开它——但只在数据中心内部可行,出了数据中心还是 TCP 的天下。
网络控制与安全
TTL 与 DPI:IP 头里有一个 TTL(Time To Live)字段,每经过一跳减 1,减到 0 包就被丢弃。本意是防止包在环路里永久循环。但运营商和校园网用它干另一件事:检测你在共享上网(开热点)。你手机发出来的包 TTL 通常是 64,经过你的电脑再转发会变成 63——运营商一看 TTL 不对,就知道后面还有设备。配合 DPI(深度包检测)分析 HTTP Header、TLS 握手特征,可以精确识别你是否在共享流量。
绕过公司防火墙(HTTPS 隧道):很多公司防火墙只允许 80 和 443 端口出站。你想 SSH 回家里的服务器(端口 22),被防火墙拦了。一个自然的想法:在你的服务器上监听 443 端口,跑一个能区分「这是普通 HTTPS 还是隧道流量」的东西。你把 SSH 流量包装成 HTTPS 请求发过去,防火墙看到的是 CONNECT home.example.com:443——标准的 HTTPS 代理请求,放行。到了你的服务器,反向拆包还原成 SSH。VPN 也是同样的思路——WireGuard、OpenVPN 都可以跑在 443 端口上,伪装成 HTTPS 流量。
SSH 与 SOCKS 代理:一条 SSH 命令 ssh -D 1080 user@server 就在你本地 1080 端口开了一个 SOCKS 代理。浏览器配置代理为 socks5://127.0.0.1:1080,你的所有浏览流量就通过加密的 SSH 隧道走了——对你来说在访问本地端口,实际出口是你的远程服务器。SSH 只是远程登录工具?远不止。
洋葱网络(Tor):加密不止一层,是三层。你的数据被层层加密,像洋葱一样。经过三个节点:入口节点知道你是谁但不知道你去哪,中间节点什么都不知道,出口节点知道你去哪但不知道你是谁。没有任何一个节点同时知道你是谁和你在访问什么。代价:慢——经过三跳,延迟显著增加。
FakeIP 与 TProxy:透明代理技术。FakeIP 是代理软件(如 Clash)给域名分配一个假的、本地的 IP,当你的流量去访问这个假 IP 时,被路由规则抓到代理进程,代理再用真实 IP 去连接。全过程你的应用程序不知道自己走了代理——这就是「透明」。TProxy(透明代理)是 Linux 内核的一个特性,可以在不修改包的情况下把流量重定向到代理进程。两者配合:流量经过你的设备,不知不觉地被代理了。
架构与协议
SDN 与 Overlay 网络:传统网络里,每个交换机/路由器独立决策(分布式)。SDN(软件定义网络)把控制平面抽出来交给一个中心控制器,转发设备只管转发。Overlay 网络是在现有的物理网络之上再虚拟一层网络:Tailscale 就是一个典型的 Overlay——它在任何网络环境下(NAT 后面、防火墙后面、4G 热点下)用 WireGuard 在节点之间建立加密隧道,组成一个虚拟的私有网络。你感觉设备之间是直连的,实际上数据可能绕了半个地球,但 Tailscale 帮你协调了 NAT 穿透和端到端加密。
OSPF(开放最短路径优先):BGP 是 AS 之间的路由协议,OSPF 是 AS 内部的路由协议。一个大学校园网内部有几百台路由器,它们之间怎么协同?OSPF 让每台路由器知道全网的拓扑图(链路状态),然后用 Dijkstra 算法算出到每个子网的最短路径。链路断开时,全网路由器在几秒内重新计算——这就是为什么拔掉一根网线,内网通常几秒就恢复。
DNS 谁在管:ICANN(互联网名称与数字地址分配机构)是顶层管理者——管根区、管 IP 分配、管 AS 号分配。域名注册局(Registry)管顶级域名:.com 是 Verisign 管的,.cn 是 CNNIC 管的。域名注册商(Registrar)是面向消费者的:你在 Namecheap、阿里云注册域名,他们就是 Registar。你付的域名年费,Registrar 抽一部分,Registry 抽一部分,ICANN 再抽一小笔。
怎么继续学
官方文档在哪:
RFC(Request for Comments)是互联网协议的标准文档。TCP 是 RFC 9293,HTTP/1.1 是 RFC 9112,TLS 1.3 是 RFC 8446。都是公开免费阅读的:
rfc-editor.org。RFC 写得很干,但它们是「源代码」——没有任何二次解读,直接看设计者是怎么想的。IETF(互联网工程任务组)是写这些 RFC 的组织。他们的网站
ietf.org有工作组邮件列表,你甚至可以看到现在的工程师们在吵下一代协议怎么设计。
推荐书目:
《计算机网络:自顶向下方法》(Kurose & Ross):最经典的大学教材,从应用层讲到物理层,每一版都更新到最新的协议。配合 Wireshark 实验,边看边抓包。
《TCP/IP 详解 卷一》(Stevens):协议层面的圣经,适合想理解每一个字节含义的人。卷二(实现)是看 BSD 内核代码,卷三是具体协议的实战分析。
《High Performance Browser Networking》(Ilya Grigorik):免费在线阅读,讲浏览器里的网络——从 TCP 到 TLS 到 HTTP/2 到 WebRTC,实战导向。
学习方法:
装 Wireshark,抓自己的包。访问一个 HTTP 网站,看三次握手、TLS 握手、HTTP 请求——你在纸上读十遍,不如亲眼抓一次。
搭一个小实验环境:两台虚拟机,配一个子网,用
nc监听、curl请求、tcpdump看包。写一个最简单的 HTTP 服务器:任何语言几十行就够。当你亲手写了一个能响应
GET /的程序,HTTP 就从神秘协议变成了「我也可以」。关注 IETF 和网络工程师的博客:网络不是静态的——QUIC、HTTP/3、MASQUE 都是近几年才标准化的新东西。网络是活的,还在进化。
想要传递的感觉
网络不是「魔法」,是一层一层搭起来的技术栈
分层设计的美妙之处:你可以替换掉某一层,而不引起上层的变化——这就是抽象的力量
理解每一层在做什么,你就不会被「连不上网」吓到——你会有条不紊地一层层排查
域名是你自己的品牌,是你在数字世界的一亩三分地——从域名开始,你可以拥有自己的数字身份
与后续课的钩子
→ 第二课:理解的网络之后,下一步是让你的电脑自动做事情——自动化与编程
→ 第三课:开源社区的网络效应——志同道合的人通过互联网协作,这建立在今天讲的每一层之上