IP
HTTP 管说什么,TCP 管说清楚,而IP 只管一件事:把这个包送到那个地址去。它是整个互联网唯一的"公共语言"——上面跑什么协议它不管,下面走光纤还是 WiFi 它也不管。这一节把 IP 地址、子网掩码、CIDR、NAT 这几个让无数人头疼的东西,用门牌号和快递分区讲透。
你在网上买了个东西,卖家在广州,你在北京。这个包裹是怎么找到你的?
没有任何一个人知道全程怎么走。广州的快递员只知道"北方的件都装上这辆车";到了转运中心,分拣员只知道"北京的件放这个笼子";到了北京分拨,只知道"海淀的件给那辆车";到了海淀站点,快递员才知道"这栋楼在哪、这个单元在哪、这一户在哪"。
每一站都只知道"下一站往哪儿送",没有一站掌握全局。
IP 干的活儿一模一样。你的数据包从家里出发,经过十几台路由器才到达目标服务器——而这十几台路由器里,没有任何一台知道完整路线。每一台只做一个动作:看包上写的目标地址,查一下自己的表,扔给下一台。
这一节要讲的就是:那个"地址"是怎么写的,那张"表"是怎么查的,以及为什么你家的地址号码全世界有几亿人在同时用。
先把这一节的术语翻译成人话
IP 这一节是整个网络篇最"数字密集"的一节,术语也最容易糊。先把它们翻译成人话过一遍。建议这张表看完全篇再回来重读一次——第一遍看不懂很正常,因为每一行背后都有一个小节在解释。
| 术语 | 换成大白话 | 生活里对应的东西 |
|---|---|---|
| IP 地址(Internet Protocol Address,网络上一台机器的地址) | 说白了就是"门牌号" | 小区里的"3 号楼 502" |
IPv4(第 4 版,四段十进制数字,如 192.168.1.5) | 说白了就是"老式短号码,快用完了" | 七位数的老电话号码 |
IPv6(第 6 版,八段十六进制,如 2001:db8::1) | 说白了就是"新式长号码,多到用不完" | 加了区号又加了位数的新号码 |
| 网络号 / 主机号(地址的前半段表示"哪个小区",后半段表示"哪一户") | 说白了就是"小区名 + 门牌号" | "中关村花园" + "3 号楼 502" |
| 子网掩码(Subnet Mask,一把尺子,用来划出地址里哪几位是"小区") | 说白了就是"划线的那把尺子:这条线左边是小区名,右边是门牌" | 填地址时的分拣规则:前几个字看到就够决定送哪个片区了 |
CIDR(Classless Inter-Domain Routing,写法如 /24,表示"前 24 位是小区") | 说白了就是"用一个数字代替那把尺子" | "前六个字是地区"这句话本身 |
| 公网 IP(全球唯一、能被外面直接找到的地址) | 说白了就是"能寄快递到的正式地址" | 写在营业执照上的门牌地址 |
| 私网 IP(只在自己家 / 公司内部有效的地址) | 说白了就是"内部编号,出了这栋楼就没人认" | 办公室内线号码:8812 只在公司里有意义 |
| NAT(Network Address Translation,把内部地址换成对外地址) | 说白了就是"前台替全楼人收发信,出去时换成大楼地址" | 公司前台登记转交:只有一个总机号,靠登记本分辨谁的 |
| 网关(Gateway,本地网络通往外面的出口) | 说白了就是"小区大门" | 小区唯一的门卫岗,出小区必须走这 |
| 路由表(Routing Table,"往哪个方向去哪个下一跳"的对照表) | 说白了就是"分拣台上贴的那张分区表" | 分拣中心墙上贴的"华北→3 号门,华南→7 号门" |
| TTL / 跳数限制(Time To Live / Hop Limit,这个包最多还能被转发几次) | 说白了就是"最多再转几手,转完还没到就扔" | 快递单上写"超过 10 次中转就退回",防止包裹在网里绕圈 |
| 分片(Fragmentation,包太大装不下,被切成几个小包) | 说白了就是"一大件拆成几箱寄" | 装修材料切成几段装车 |
| MTU(Maximum Transmission Unit,一条线上一个包最多能装多少字节) | 说白了就是"这条线路的纸箱尺寸上限" | 快递公司规定的单箱尺寸 |
| 广播地址(这一段网络里"全体收听"的地址) | 说白了就是"整栋楼的大喇叭" | 学校广播室通知全体 |
这一整节可以用一句话串起来:IP 地址是门牌号,子网掩码是"划出小区名的那把尺子",路由表是分拣台上的分区表,NAT 是替全楼收发信的前台。其余全是细节。
IP 只承诺一件事,而且这件事它做得挺敷衍
IPv4 定义在 RFC 791(1981 年 9 月,Jon Postel 编辑),IPv6 定义在 RFC 8200(2017 年,它取代了早先的 RFC 2460)。这两份规范里,IP 给出的承诺少到令人意外:
它只承诺"尽力把这个包往目标地址的方向送"。行话叫 Best-Effort Delivery(尽力而为的投递)。换成大白话:"我尽量送,送不到不赔。"
具体来说,IP 明确不保证以下所有事情:
| IP 不保证什么 | 说白了就是 | 谁来补这个坑 |
|---|---|---|
| 不保证送达 | 包可能中途被扔掉,而且不通知你 | TCP 的确认与重传(§ 3.2) |
| 不保证顺序 | 先发的可能后到,因为可能走了不同的路 | TCP 的序号与重排 |
| 不保证不重复 | 同一个包可能被送到两次 | TCP 的去重 |
| 不保证内容完整 | IPv4 的头部有校验和但只校验头部,不校验数据;IPv6 连头部校验和都取消了 | TCP / UDP 的校验和,以及链路层的校验 |
| 不保证时延 | 这个包可能 10 毫秒到,也可能 3 秒到 | 没人能保证,只能靠应用层容忍(§ 3.3 的抖动缓冲) |
| 不保证走同一条路 | 连着发的两个包可能走完全不同的路线 | 不需要补——这正是它抗故障的原因 |
这么敷衍的一个协议,凭什么成了整个互联网的地基?答案恰恰在这份敷衍里。
因为 IP 什么都不承诺,所以它什么都不需要记住——路由器转发一个包时,不需要知道这个包属于哪次通信、前面有没有别的包、后面还会不会有。相当于分拣中心的传送带:一件件过,看一眼地址扔进对应的口,扔完就忘。它压根不记得刚刚过去的是谁的包,也不关心这一批一共有几件。
这份"不记事"带来三个巨大的好处:
- 路由器可以做得极快不用查连接状态、不用维护会话表,只需要"看目标地址、查表、转发"三个动作。现代核心路由器每秒能转发天文数字级别的包,靠的就是这个动作足够简单、能做成专用硬件。
- 中间任何一台机器坏了,网络自己会绕开因为没有任何状态存在那台机器上。相当于快递中转站着火了,包裹改走另一条线路就行——因为没有任何一份"只有这个站才有"的记录。这正是互联网最初的设计目标:局部损坏,整体照常运转。
- 上下都可以自由替换IP 上面可以跑 TCP、UDP、QUIC 甚至以后发明的新东西;IP 下面可以走以太网、WiFi、光纤、5G、卫星。IP 是中间那个谁都认的"通用接口"——这就是所谓"万物皆可 IP"。
这个设计哲学有个流传很广的说法叫"沙漏模型":上面应用协议千千万,下面物理介质千千万,中间收窄成一个 IP。好比全国的快递公司、卡车品牌、包装规格千差万别,但"收件地址怎么写"全国统一——正因为这一条统一了,其他的才能各干各的。
如果你只记住这一节的一个类比,请记住这个。它能同时解释路由表、网络号、子网掩码和默认路由这四样东西。
想象一个快递分拣中心。传送带上一件件包裹过来,分拣员站在旁边,墙上贴着一张表:
发往「北京市 海淀区 ...」 → 扔进 3 号笼
发往「北京市 朝阳区 ...」 → 扔进 4 号笼
发往「北京市 ...」(其他区)→ 扔进 5 号笼
发往「上海市 ...」 → 扔进 9 号笼
其他任何地方 → 扔进「总仓」那个大笼子
请注意分拣员干活的三个特征,它们和路由器一模一样:
① 他只看地址的前面几个字,压根不看后面。"北京市海淀区"这六个字就够他做决定了——具体是哪栋楼哪一户,他不关心,那是后面站点的事。这就是网络号的概念:路由器只看地址的前半段。而"前几个字算前半段"这个规则,就是子网掩码。
② 他不知道包裹之后会怎么走,也不需要知道。他只负责"扔进哪个笼子"这一个动作。整条路线是一站一站接力接出来的,没有任何一站掌握全程。这就是所谓"逐跳转发"(hop-by-hop)。
③ 表上永远有最后一行"其他任何地方 → 总仓"。这一行至关重要——没有它,凡是表上没列的地址就只能原地堆着。而全国有几十万个地名,不可能全列上。这一行在网络里叫默认路由(default route),写成 0.0.0.0/0,意思是"所有我不认识的地址,一律往这儿送"。你家路由器上那条指向运营商的路由,就是这一行。
还有一条匹配规则要记住:表上可能有好几行都对得上,这时候选"写得最细的那一行"。比如包裹去"北京海淀",表上"北京海淀→3 号笼"和"北京→5 号笼"都对得上,分拣员选前者,因为它更具体。这在路由里叫最长前缀匹配(Longest Prefix Match)——好比公司规章里"财务部报销"和"全公司报销"两条都适用时,按更具体那条办。
IPv4 地址:为什么是四段,为什么最大 255
先把这个最基础的东西彻底说清,因为后面所有关于子网的困惑,根源都在"没真正理解这四段数字是什么"。
IPv4 地址本质上就是一个 32 位的二进制数。就这么简单。32 个 0 和 1 排成一串,一共 32 个格子。
但 32 个 0 和 1 写出来是 11000000101010000000000100000101——人根本没法读、没法记、没法在电话里念给同事。所以人们做了一件很朴素的事:把这 32 位切成四段,每段 8 位,然后把每段翻译成十进制数字,中间用点隔开。
【IPv4 地址的真身】
二进制(机器看的):
11000000 . 10101000 . 00000001 . 00000101
↓ ↓ ↓ ↓
192 . 168 . 1 . 5
十进制(人看的):192.168.1.5
★ 为什么每段最大是 255?
因为一段是 8 位二进制,8 个格子每格填 0 或 1,
最大就是 11111111 = 255。
所以 192.168.1.256 是一个非法地址 ——
它压根写不出来,因为 256 需要 9 个格子。
★ 为什么是四段?
因为 32 ÷ 8 = 4。这个分段纯粹是为了人好读,
对机器来说那三个点压根不存在。
★ 一共有多少个 IPv4 地址?
2 的 32 次方 = 4294967296,约 43 亿个。
【43 亿是多少?换算成可感知的量】
全球人口约 80 亿 ——
也就是说,IPv4 地址的总数
还不够全世界每人分一个。
而今天一个人身上可能有手机、电脑、手表、
耳机、电视、冰箱……全都要地址。
★ 这就是 IPv4 地址耗尽问题的全部由来。
"每段最多 255"这件事一旦从"背下来的规定"变成"8 个格子最多就这么大",你就再也不会写错地址了。而后面讲子网掩码时,我们要做的所有事情都是在这 32 个格子上画一条竖线——所以务必先把"地址就是 32 个格子"这个画面装进脑子里。
顺便说一个几乎没人提但很有意思的细节:那个"四段点分十进制"的写法只是习惯,不是规范强制的唯一写法。历史上不少软件还接受十六进制、八进制甚至"少于四段"的写法,这曾经带来一些安全上的混淆问题。今天你只需要记住标准写法,但知道"点分十进制只是给人看的一层包装"这件事,理解会更牢。
一个地址里的两半:哪个小区,哪一户
现在进入这一节最关键的概念。一个 IP 地址不是一个整体,它是两半拼起来的:
- 前半段 = 网络号(Network ID)表示"这是哪一片网络"。说白了就是"哪个小区"。
- 后半段 = 主机号(Host ID)表示"这片网络里的第几台机器"。说白了就是"哪一户"。
为什么非要分成两半?因为这直接决定了路由器要不要费劲。回到快递分拣的画面:分拣员看"北京海淀"这几个字就能决定往哪个笼子扔,他压根不需要看"3 号楼 502"。路由器也一样——它只看网络号,就够决定"往哪个方向转发"了。
这个设计的意义有多大?算一笔账你就知道了:
【为什么必须分成"小区 + 门牌"两半】
假设不分半,路由器要为每一个地址存一条记录:
43 亿个地址 → 路由表要有 43 亿行
→ 每转发一个包都要在 43 亿行里查一遍
→ 完全不可能实现
分成两半之后:
路由器只需要记"网络号 → 往哪走"
→ 整个海淀区几万台机器,在表上只占一行
→ 表的行数从"地址数量"降到"网络数量"
★ 换成大白话:
全国有几亿个具体门牌号,
但快递分拣中心墙上那张表只需要写几百个地名。
因为"送到某个片区"之后,
细分的活儿交给那个片区自己去做。
★ 这就是"分层聚合"的威力,
和 § 3.4 里 DNS 的"逐层委派"是同一个思路:
谁也不掌握全局,每一层只管自己那一级的粗粒度决策。
同一个网络号下面的机器,有一个非常重要的性质:它们之间可以直接通信,不需要经过路由器。相当于同一个小区里两户人家串门,走小区内部的路就行,不用出小区大门。而要找不同网络号的机器,就必须先出小区大门——那个门就是网关(Gateway)。
这一点解释了你在生活中遇到过的一个现象:为什么手机连上家里 WiFi 之后,能直接投屏到电视、能直接访问路由器管理页面,哪怕外网断了也照样能用。因为它们在同一个小区里,串门不需要出门。断的是小区大门外的路,跟小区内部没关系。
子网掩码:那把在 32 个格子上划线的尺子
好,现在最关键的问题来了:一个地址给你,你怎么知道前面几位是网络号、后面几位是主机号?
答案是:你看不出来。地址本身不带这个信息。这就是为什么必须有子网掩码——它是另一个数字,专门告诉你"那条线画在第几位"。
子网掩码(Subnet Mask)的写法和 IP 地址长得一样(比如 255.255.255.0),但它的含义完全不同:它是一串"前面全是 1、后面全是 0"的二进制数,1 的部分对应网络号,0 的部分对应主机号。
【子网掩码怎么起作用的】
IP 地址: 192 . 168 . 1 . 5
二进制: 11000000.10101000.00000001.00000101
子网掩码: 255 . 255 . 255 . 0
二进制: 11111111.11111111.11111111.00000000
└────── 全是 1 ──────┘└─ 全是 0 ─┘
这段是"小区" 这段是"门牌"
于是这条线画在第 24 位:
网络号 = 192.168.1.0 ← 小区名
主机号 = .5 ← 这一户
★ 掩码里 1 的个数就是"网络号占几位"。
上例是 24 个 1,所以写成 /24 —— 这就是 CIDR 写法。
【为什么掩码必须是"前面连续的 1"?】
因为那条线只能画在一个地方。
10101010 这样的掩码在数学上能算,
但它意味着"第 1、3、5、7 位算小区",
这在现实里毫无意义 ——
相当于地址里挑着几个字算地区名,
第二个字和第四个字算,第三个字不算。
规范和所有实现都要求掩码是连续的 1 开头。
子网掩码之所以让人头疼,是因为它总被当成"一个要背的数字"。其实它就是一句话:"地址前面几个字,我拿来当地区看。"
回到分拣中心。假设包裹地址统一写成十二位数字,比如 110108003502。分拣员墙上贴着一句话:
"前六位是片区,后六位是具体门牌。"
于是他看到 110108|003502,只关心前面的 110108——这就是他要匹配的东西。那句"前六位是片区"就是子网掩码,写成 CIDR 就是 /6(这里只是打比方,真实 IP 是按二进制位算的)。
现在关键的一步来了:这条线可以移动,而且移动它会同时改变两件事。
线往右移(网络位变多,比如从 /24 移到 /26):片区划得更细了 → 片区数量变多,但每个片区里能装的门牌变少。好比本来"整个海淀区"算一个片区,现在细分成"海淀北部、海淀中部、海淀南部、海淀西部"——片区多了四倍,每个片区管的户数少了四分之三。
线往左移(网络位变少,比如从 /24 移到 /22):片区划得更粗 → 片区数量变少,但每个片区能装的门牌变多。好比把海淀、朝阳、东城、西城合成一个大片区——片区少了,但一个片区里的户数翻了几倍。
这就是子网划分的全部内容,一句话:你在 32 个格子上挪那条竖线,往右挪就是"多分小区、每个小区少装人",往左挪就是"少分小区、每个小区多装人"。总人数是固定的,你只是在决定怎么分组。
为什么要分?三个非常实在的理由:① 隔开——财务部和访客 WiFi 分在不同小区,串门要经过门卫,好管好防;② 减少吵闹——同一个小区里的"喊话"(广播)所有人都听得到,小区太大就吵得没法工作;③ 好规划——每个部门一个小区,看地址就知道是谁,排查问题快得多。
再给一张最实用的对照表。这张表建议直接记住常用的那几行,因为它是网络配置里天天用到的:
| CIDR | 子网掩码 | 地址总数 | 可用主机数 | 说白了就是 |
|---|---|---|---|---|
/8 | 255.0.0.0 | 16777216 | 16777214 | 一个超级大区,能装一千六百多万台 |
/16 | 255.255.0.0 | 65536 | 65534 | 一个大区,六万多台——大企业整个园区的量级 |
/22 | 255.255.252.0 | 1024 | 1022 | 一千台出头,中型办公楼 |
/24 | 255.255.255.0 | 256 | 254 | 最常见的一档,家用路由器默认就是这个 |
/25 | 255.255.255.128 | 128 | 126 | 把一个 /24 对半劈开 |
/26 | 255.255.255.192 | 64 | 62 | 一个 /24 切成四份,一个部门一份 |
/28 | 255.255.255.240 | 16 | 14 | 十几台,一个小机柜 |
/30 | 255.255.255.252 | 4 | 2 | 只够两台——专门用来连两台路由器之间的那根线 |
/31 | 255.255.255.254 | 2 | 2(特例,见 RFC 3021) | 点对点链路的省地址写法 |
/32 | 255.255.255.255 | 1 | 1 | 就指定这一个地址,常用于路由和防火墙规则 |
为什么"可用主机数"总是比"地址总数"少 2 个?这是最常被问的问题。因为每一段网络里有两个地址被征用了,不能分给机器:
- 第一个地址:网络地址主机位全是 0 的那个(如
192.168.1.0),它代表"这一整片网络"本身,不指任何一台机器。相当于"中关村花园小区"这个名字——它是小区的名字,不是某一户。 - 最后一个地址:广播地址主机位全是 1 的那个(如
192.168.1.255),发给它的包本网段所有机器都会收到。相当于小区的大喇叭——喊一声全小区都听见。
/30 那一行特别值得看一眼:四个地址,扣掉网络地址和广播地址,只剩两个可用。这正好够连接两台路由器——一根线,两头各一个地址,一个不浪费。网络工程师配置骨干链路时大量用这个,因为地址太贵,一个都不能浪费。
CIDR 的来历:从"只有三种尺码"到"随便剪裁"
现在讲一段历史,因为不知道这段历史,你就无法理解为什么 /24 这种写法看着这么别扭却这么重要。
最早的 IPv4 不是按位划线的,而是只有三种固定尺码,叫"有类地址"(Classful Addressing):
| 类别 | 网络位 | 一个网络能装多少台 | 说白了就是 |
|---|---|---|---|
| A 类 | 前 8 位 | 约 1677 万台 | 超大号,全世界只有 126 个这样的网络 |
| B 类 | 前 16 位 | 约 6.5 万台 | 大号 |
| C 类 | 前 24 位 | 254 台 | 小号 |
问题一眼就能看出来:只有三种尺码,跳档太大。
换成大白话,这就好比一家快递公司只提供三种纸箱:小箱装 254 件,中箱装 6.5 万件,大箱装 1677 万件。中间什么都没有。
于是荒谬的事情发生了:一家公司有 300 台机器。小箱(254 台)装不下,只能要中箱(6.5 万台)——于是 6.4 万多个地址被白白占着,一个都不能给别人用。相当于你要寄 300 件东西,快递公司说"小箱只能装 254 件,那您用中箱吧",然后你订了一个能装六万五千件的集装箱,里面就躺着 300 件货。
这种浪费在 1990 年代初已经到了危急程度,而且它同时引发第二个问题:路由表爆炸。因为大家都只能按这三种尺码申请,网络数量增长得极快,全球路由器的表越来越长,快要撑不住了。
CIDR(Classless Inter-Domain Routing,无类别域间路由,规范是 RFC 4632,它整理并取代了 1993 年的一系列早期文档)就是为解决这两件事发明的。它的核心思想只有一句:
"别管什么 A 类 B 类了,那条线你想画在第几位就画在第几位。"
【CIDR 带来的改变】
有类地址时代(只有三种尺码):
需要 300 台 → 只能拿 B 类(65534 个)→ 浪费 65234 个
需要 500 台 → 只能拿 B 类 → 浪费 65034 个
需要 5 万台 → 拿 B 类,勉强合适
CIDR 时代(任意尺码):
需要 300 台 → 给 /23(510 个可用)→ 浪费 210 个
需要 500 台 → 给 /23(510 个可用)→ 浪费 10 个
需要 5 万台 → 给 /17(32766 个)或 /16,按实际需要挑
★ 换成大白话:
从"只卖 S / M / XXXL 三个码"
变成"按你的尺寸现剪现做"。
【CIDR 的第二个作用:路由聚合】
假设一家运营商手上有这四段地址:
203.0.112.0/24
203.0.113.0/24
203.0.114.0/24
203.0.115.0/24
它对外只需要宣告一条:
203.0.112.0/22 ← 一条顶四条!
因为 /22 正好把这四个 /24 全包住了。
→ 全球路由表少了 3 行
★ 这个动作叫路由聚合(route aggregation)。
换成大白话:本来要在分区表上写
"海淀北、海淀中、海淀南、海淀西"四行,
现在只写一行"海淀"就够了 ——
反正它们都走同一个方向。
★ 这是 CIDR 真正救命的地方:
它不只省地址,更重要的是把全球路由表
的增长速度压了下来。
那个 /22 顶四个 /24 的算术值得多看一眼,因为它揭示了 CIDR 的数学本质:每往左挪一位,覆盖范围翻一倍。所以 /23 = 两个 /24,/22 = 四个,/21 = 八个……好比折纸:每对折一次,层数翻一倍。挪一位就是对折一次。
今天你几乎不会再听到"A 类 B 类"这种说法(除了考试题里),但有一个残留很值得知道:前面讲的私网地址段,它们的划分正好对应着当年的类别,所以三段的大小很不一样——这一点马上就要讲。
私网地址:为什么全世界几亿人共用 192.168.1.1
你家路由器的地址很可能是 192.168.1.1。你邻居家的也是。你公司的可能是 10.0.0.1。这些地址在全世界被重复使用了几亿次,而且完全合法。
这套安排定义在 RFC 1918(Address Allocation for Private Internets,1996 年 2 月)里,它明确划出三段地址专门给内部网络用,永远不会出现在公网上:
| 地址段(CIDR) | 地址范围 | 地址数量 | 对应的老类别 | 典型用在哪 |
|---|---|---|---|---|
10.0.0.0/8 | 10.0.0.0 ~ 10.255.255.255 | 约 1677 万个 | 一个 A 类 | 大企业、云服务商内网、大规模数据中心 |
172.16.0.0/12 | 172.16.0.0 ~ 172.31.255.255 | 约 104 万个 | 16 个连续的 B 类 | 中型企业;Docker 默认网段常在这个范围 |
192.168.0.0/16 | 192.168.0.0 ~ 192.168.255.255 | 65536 个 | 256 个连续的 C 类 | 家用路由器、小办公室——你最常见到的就是这一段 |
请特别注意中间那一行,它是最容易被记错的。
私网的第二段是 172.16.0.0/12,也就是从 172.16 到 172.31 这十六个,不是"整个 172",也不是只有 172.16。为什么是 /12 而不是 /16?因为它覆盖了十六个连续的 B 类网络——16 = 2 的 4 次方,所以从 16 位往左挪 4 位,就是 12。
所以 172.15.x.x 和 172.32.x.x 都是公网地址,不属于私网。这个边界记错会导致很实际的配置事故。
私网地址这件事,用办公室内线来理解一秒就通。
你在一家公司上班,前台内线是 8001。你朋友在另一家公司,前台内线也是 8001。这两个 8001 之间完全没有冲突,因为它们只在各自那栋楼里有意义。
你在自己公司拨 8001,接的是自己公司前台;你朋友拨 8001,接的是他公司前台。两个人都用同一个号码,但谁也不会串线——因为这个号码出了这栋楼就不存在。
那怎么打给外面的人?你得先拨一个 0(或者 9,各公司规矩不同)转外线。这个"拨 0 转外线"的动作,就是把内部号码换成"公司总机 + 外拨"的过程——这正是 NAT 做的事。
反过来,外面的人怎么找到你?他不能直接拨 8001——那个号码在外面不存在。他只能拨公司总机,然后跟前台说"我找财务部的小李",前台再帮他转到 8001。这解释了私网最重要的一个后果:外面的人无法主动找到你,除非有人在前台替你留了转接规则。
为什么要这么设计?因为电话号码不够用了——如果全国每一个内线都要一个独立的正式号码,号码资源早就耗尽了。"内部随便编号 + 出门统一换成总机号"这一招,让号码需求从"每个人一个"降到"每家公司一个"。
顺带的好处也很实在:外面的人默认打不进来。这不是刻意设计的安全机制,但它事实上挡掉了绝大多数来自外部的主动扫描和攻击尝试。很多人把这当成"路由器自带防火墙",其实那只是私网加 NAT 的副作用。
除了这三段私网,IPv4 里还有几段有特殊用途的地址,遇到它们时能一眼认出来会很有用:
| 地址段 | 叫法 | 说白了就是 | 你什么时候会见到 |
|---|---|---|---|
127.0.0.0/8 | 回环地址(Loopback) | "我自己"——发给它的包压根不出网卡 | 127.0.0.1 或 localhost,本地开发天天用 |
169.254.0.0/16 | 链路本地地址(RFC 3927) | "我没拿到地址,只好自己随便编一个" | 这是个重要信号:看到它说明 DHCP 失败了,见下方 |
0.0.0.0 | 未指定 / 全部 | 作监听地址时意思是"所有网卡都监听" | 服务器配置里极常见 |
255.255.255.255 | 受限广播地址 | "本网段全体收听" | DHCP 客户端刚开机时就用它喊话 |
224.0.0.0/4 | 多播地址 | "发给订阅了某个组的那些机器" | IPTV、局域网设备发现(§ 3.3 讲过) |
100.64.0.0/10 | 共享地址空间(RFC 6598) | "运营商内部再套一层的地址" | 见下方"运营商级 NAT" |
169.254.x.x 那一行是最实用的一条排障知识,值得单独记住。
如果你的电脑地址是 169.254. 开头,几乎可以确定一件事:它没能从路由器那里拿到地址,于是按规范自己随便挑了一个来用。换成大白话:好比你去新单位报到,人事一直没给你工位号,你只好自己随便找了张桌子坐下——能坐,但没人知道你在哪,谁也找不到你。
这种情况下的表现非常典型:能看到 WiFi 显示已连接,图标是好的,但什么网页都打不开。排查方向应该是 DHCP(发地址那个服务)出了问题,而不是去折腾浏览器或 DNS。这个协议在 §3.6 会细讲。
动手划一次子网:把一栋楼分给四个部门
光讲原理不够,走一遍实际计算你才真的会。这是子网划分最典型的一道题。
【任务】
公司拿到一段地址:192.168.10.0/24(254 个可用)
要分给四个部门,每个部门要能装 50 台左右机器:
· 研发部 · 销售部 · 财务部 · 访客 WiFi
【第一步:算需要多少位主机位】
每个部门要 50 台 → 主机位要能表示 50 个以上
主机位 6 位 → 2^6 = 64 个地址,扣掉网络地址
和广播地址 = 62 个可用 ✓ 够了
主机位 5 位 → 2^5 = 32 个 → 30 个可用 ✗ 不够
所以主机位取 6 位 → 网络位 = 32 - 6 = 26
→ 每个子网是 /26
【第二步:看能分几个】
原来是 /24,现在每个子网 /26
→ 网络位从 24 增加到 26,多了 2 位
→ 2^2 = 4 个子网 ✓ 正好四个部门
【第三步:算出四段的边界】
/26 的每一段大小 = 256 ÷ 4 = 64 个地址
于是边界就是 0、64、128、192:
┌──────────────────────────────────────────────┐
│ 研发部 192.168.10.0/26 │
│ 网络地址 192.168.10.0 ← 不能给机器 │
│ 可用范围 192.168.10.1 ~ 192.168.10.62 │
│ 广播地址 192.168.10.63 ← 不能给机器 │
├──────────────────────────────────────────────┤
│ 销售部 192.168.10.64/26 │
│ 网络地址 192.168.10.64 │
│ 可用范围 192.168.10.65 ~ 192.168.10.126 │
│ 广播地址 192.168.10.127 │
├──────────────────────────────────────────────┤
│ 财务部 192.168.10.128/26 │
│ 可用范围 192.168.10.129 ~ 192.168.10.190 │
│ 广播地址 192.168.10.191 │
├──────────────────────────────────────────────┤
│ 访客WiFi 192.168.10.192/26 │
│ 可用范围 192.168.10.193 ~ 192.168.10.254 │
│ 广播地址 192.168.10.255 │
└──────────────────────────────────────────────┘
子网掩码全部是 255.255.255.192
(因为 /26 → 第四段是 11000000 = 192)
【检查一下】
4 个子网 × 62 台 = 248 台可用
原本一个 /24 是 254 台
→ 划分子网"损失"了 6 个地址
→ 因为多了 3 组"网络地址 + 广播地址"要征用
★ 这就是划子网的代价:分得越细,
被征用的地址越多。
换成大白话:一栋楼隔成四个独立单元,
就得多修三道墙、多设三个门卫岗 ——
每道墙都占地方。
那 6 个"损失"的地址值不值?绝对值。用 6 个地址换来"访客 WiFi 里的人无法直接看到财务部的机器",这笔交易任何管网络的人都会毫不犹豫地做。
还有一个更精细的做法叫 VLSM(Variable Length Subnet Mask,可变长子网掩码——说白了就是"每个子网可以用不同的尺码")。上面的例子里四个部门用了同样的 /26,但现实中部门规模差别很大:
【VLSM:按实际需要给不同尺码】
研发部 100 台 → /25(126 可用) 192.168.10.0/25
销售部 50 台 → /26(62 可用) 192.168.10.128/26
财务部 20 台 → /27(30 可用) 192.168.10.192/27
访客 10 台 → /28(14 可用) 192.168.10.224/28
备用 192.168.10.240/28
★ 关键技巧:先给最大的分,再给小的。
因为大块必须落在"对齐"的边界上 ——
一个 /25 只能从 0 或 128 开始,不能从 64 开始。
★ 换成大白话:好比装修隔间,
先划出最大的那间主卧,再用剩下的地方
隔次卧、书房、储物间。
反过来先隔小间的话,剩下的碎地方
就凑不出一间大房了。
最后那条"对齐"的规则是初学者最容易踩的坑,值得再说一句:一个 /25 的起点只能是 0 或 128;一个 /26 的起点只能是 0、64、128、192。你不能说"我从 100 开始要一个 /26"——那在二进制上是画不出那条线的。好比贴瓷砖:大块砖必须从格线开始铺,不能从半格的位置起头。
NAT:一个地址,全家人用
私网地址解决了"内部够用",但留下一个问题:内部地址在公网上不存在,那家里的设备怎么访问外网?
答案是 NAT(Network Address Translation,网络地址转换,相关规范见 RFC 3022)。它做的事一句话说完:包从内网往外走的时候,路由器把源地址从私网地址改写成自己的公网地址,并在一张表上记一笔;回包来的时候,照表把地址改回去。
但这里有个关键细节:光改地址不够。因为家里五台设备同时上网,回包全都发到同一个公网地址,路由器怎么知道哪个包该给谁?
答案是端口号。路由器不只改地址,还改源端口——给每一条对外连接分配一个不同的端口,靠这个端口来分辨。这种做法叫 NAPT(Network Address Port Translation,网络地址端口转换),也常被叫做 PAT 或"地址伪装"。你家路由器干的就是这个,虽然大家习惯统称它 NAT。
【NAT 转换表:路由器的那本登记簿】
家里有三台设备,公网地址是 203.0.113.7
【设备发出去的包】
手机 192.168.1.5:51000 → 要访问 93.184.216.34:443
电脑 192.168.1.8:49500 → 要访问 93.184.216.34:443
平板 192.168.1.9:51000 → 要访问 93.184.216.34:443
↑ 注意:手机和平板用了同一个端口号,
在内网里这没问题(地址不同)
【路由器改写后发出去的包】
203.0.113.7:60001 → 93.184.216.34:443
203.0.113.7:60002 → 93.184.216.34:443
203.0.113.7:60003 → 93.184.216.34:443
↑ 三条连接被分配了三个不同的对外端口
【路由器的登记簿】
┌──────────────┬────────────────┬─────────────────┐
│ 对外端口 │ 内部地址:端口 │ 目标 │
├──────────────┼────────────────┼─────────────────┤
│ 60001 │ 192.168.1.5:51000 │ 93.184.216.34:443 │
│ 60002 │ 192.168.1.8:49500 │ 93.184.216.34:443 │
│ 60003 │ 192.168.1.9:51000 │ 93.184.216.34:443 │
└──────────────┴────────────────┴─────────────────┘
【回包来了】
93.184.216.34:443 → 203.0.113.7:60002
路由器查表:60002 → 192.168.1.8:49500
于是改写目标地址,转给电脑。
★ 关键洞察:NAT 本质上是"用端口号换地址"。
一个公网地址理论上能撑起数万条并发连接,
因为端口号有 65536 个可用。
★ 换成大白话:
公司只有一个总机号,
前台的登记簿上记着"外线 60002 这通电话是财务部小李的"。
回电进来,前台一查簿子,转给小李。
★ 那个"分机识别码"就是端口号。
NAT 的功劳非常大,值得说清:它是 IPv4 地址在耗尽之后还能撑这么多年的最主要原因。因为它把地址需求从"每台设备一个"降到了"每户一个"。相当于把"每个人一个正式号码"改成"每家一个总机号,家里的人靠分机码区分"——号码需求一下降低了几个数量级。
但它带来的代价同样明确,而且这些代价你在生活中都能感觉到:
| 代价 | 具体表现 | 说白了就是 | 怎么绕 |
|---|---|---|---|
| 外面无法主动连进来 | 你在家搭了个服务,外网访问不到 | 外面的人拨总机说不出你的分机码 | 端口映射(在前台留一条转接规则) |
| 破坏了端到端原则 | 路由器必须理解并改写传输层的内容,不再是"只搬运不拆包" | 前台不但转信,还得拆开信封改里面的落款 | 无法绕,这是 NAT 的本质 |
| 连接有超时 | 登记簿上的条目会被清掉,长时间不说话的连接就断了 | 前台的登记本定期清理,太久没动静的划掉 | 定期发心跳包(§ 3.3 讲过) |
| P2P 直连困难 | 双方都在 NAT 后面,谁也无法主动连谁 | 两家公司的员工,两边前台都不放陌生来电 | UDP 打洞(§ 3.3 详讲过) |
| 某些协议会失灵 | 凡是"在数据内容里写了自己 IP 地址"的协议都会出错 | 信里写着"请回复到我家地址",可那个地址外面不认 | 路由器为特定协议做专门处理 |
最后一行值得举个例子说清,因为它是 NAT 最"哲学"的问题。有些协议会把自己的 IP 地址写进数据内容里(比如某些文件传输和语音协议)。NAT 改写了包头上的地址,但数据里面那个地址它不知道要改——于是对方按数据里写的那个私网地址回过来,永远也到不了。
好比你在信封上写了公司地址(这个前台会正确处理),但信的正文里写着"请回复到我家的 8001 号房间"——收信人照着正文那个地址回,信就寄丢了,因为那个房间号只在你们楼里有效。为了解决这类问题,路由器得专门认识这些协议、连数据内容一起改,这类功能通常叫 ALG(应用层网关)。这已经严重违背了"路由器只看地址不拆包"的原则,也是 IPv6 想彻底摆脱 NAT 的重要动机。
还有一层要知道的现实:运营商级 NAT(CGN / CGNAT,Carrier-Grade NAT)。当运营商自己的公网地址也不够用时,它会让很多家用户共用一个公网地址——也就是在你家的 NAT 之上再套一层 NAT。这时候你家路由器上显示的"公网地址"其实是运营商内部地址(常见于前面表里那个 100.64.0.0/10 段)。
换成大白话:相当于你家的分机号先接到楼里的总机,楼里的总机再接到整个园区的总机——你在自己家里做的任何端口映射,到了园区总机那一层完全无效。这就是为什么很多人发现"在路由器上设了端口映射,外网还是访问不到"——因为你只在自己那一层留了转接规则,上面还有一层你管不了。
IP 头部:一个包上都写了什么
把 IPv4 的头部摊开看一遍,能让前面所有概念落到实处。它最小 20 字节,字段不多但每个都有用:
【IPv4 头部(RFC 791)】
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
+-------+-------+---------------+-------------------------------+
|版本(4)|头长(4)| 服务类型(8) | 总长度(16) |
+-------+-------+---------------+-----+-------------------------+
| 标识(16) |标志3| 片偏移(13) |
+---------------+---------------+-----+-------------------------+
| TTL(8) | 协议号(8) | 头部校验和(16) |
+---------------+---------------+-------------------------------+
| 源 IP 地址(32) |
+---------------------------------------------------------------+
| 目的 IP 地址(32) |
+---------------------------------------------------------------+
| 选项(可有可无,很少用) |
+---------------------------------------------------------------+
| 数据 ... |
【几个最值得记住的字段】
版本 4 表示 IPv4,6 表示 IPv6。就一个数字之差。
总长度 整个包(头+数据)多少字节。16 位 → 理论最大 65535 字节。
TTL Time To Live,字面是"存活时间",
★ 但它实际数的是"还能被转发几次",不是秒数。
每经过一台路由器减 1,减到 0 就把包丢掉
并给源头发一个 ICMP 超时通知。
→ 这就是 traceroute 能画出整条路线的原理(见 § 3.6)
→ IPv6 干脆把它改名叫 Hop Limit(跳数限制),
这个名字才是它真正在做的事
协议号 上层跑的是什么:6=TCP 17=UDP 1=ICMP
★ 这个字段就是"分用"的依据 ——
收到包之后交给谁处理,全看这一个数字。
标识 / 标志 / 片偏移
这三个配合完成"分片与重组",见下一节。
源/目的地址 各 32 位,就是前面讲的那 32 个格子。
★ 注意:IPv4 头部有校验和,但它只校验头部,不校验数据。
IPv6 干脆把头部校验和整个删掉了 ——
理由是链路层和传输层都已经在校验了,
路由器每一跳都重算一遍校验和纯属浪费。
TTL 这个字段值得特别理解,因为它的名字骗了所有人。
它叫"存活时间",听起来像秒数,但实际上它数的是"还能被转发几次"。每经过一台路由器,这个数字减 1;减到 0 就把包扔掉,不再往下传。
为什么需要它?因为路由表配错了是会出现环路的。好比分拣中心 A 的表写着"这类件送 B",而 B 的表写着"这类件送 A"——于是这个包裹在 A 和 B 之间来回跑,永远到不了目的地,还白占传送带。TTL 就是那句"这件东西中转超过 N 次还没到,就地销毁",它保证了任何一个包都不可能永久在网络里打转。
IPv6 把这个字段改名叫 Hop Limit(跳数限制)——这个名字才是它一直在做的事,只是被 IPv4 那个误导性的旧名字掩盖了几十年。
而且这个字段有个意外的用处:它让"看清整条路线"变成可能。先发一个 TTL=1 的包,第一台路由器就会把它扔掉并回一个通知,于是你知道了第一跳是谁;再发 TTL=2 的,你就知道了第二跳……一层层往外探,整条路线就画出来了。这就是 traceroute 命令的全部原理,§3.6 讲 ICMP 时会细说。
分片:一件大货被拆成几箱寄
每条链路都有一个包大小的上限,叫 MTU(Maximum Transmission Unit,最大传输单元——一个包最多能装多少字节)。以太网上典型是 1500 字节。
如果一个包超过了下一段线路的 MTU,怎么办?IPv4 的做法是路由器直接把它切开——这叫分片(Fragmentation)。
【分片的过程】
一个 4000 字节的 IP 包,要走 MTU=1500 的链路:
原包:[IP 头 20][──── 数据 3980 字节 ────]
被切成三片:
片 1:[IP 头 20][数据 1480] 标识=X 偏移=0 还有更多=1
片 2:[IP 头 20][数据 1480] 标识=X 偏移=185 还有更多=1
片 3:[IP 头 20][数据 1020] 标识=X 偏移=370 还有更多=0
↑ 三片共用同一个标识号,
靠它认出"这几片是一件东西"
↑ 偏移告诉接收方"这一片放在第几个位置"
↑ 最后一片的"还有更多"标志是 0
【★ 关键规则:重组只在最终目的地做,中途不重组】
即便某一段线路的 MTU 很大,路由器也不会把
已经切开的片重新拼起来 —— 因为它压根不知道
其他片会不会走同一条路。
【★ 致命问题:任何一片丢了,整个包全废】
三片里丢一片,接收方拼不出完整的包,
只能把已收到的两片也全扔掉。
算笔账:单片丢包率 1%
→ 三片全到的概率 = 0.99³ ≈ 97%
→ 失败率从 1% 涨到约 3%,翻了三倍
★ 换成大白话(这段和 § 3.3 讲 UDP 时是同一个道理):
你把一整卷地板切成三段分别托运,
哪一段丢了,剩下两段都铺不成 ——
而且快递公司只按件计算丢件率,
你拆得越多,整件货失败的概率越高。
因为分片的代价这么大,IPv6 做了一个很干脆的决定:路由器不许分片。
IPv6 的规则是:包太大,路由器直接扔掉,并回一个消息告诉发送方"太大了,这条路最多能过这么大"。然后由发送方自己把包做小一点重发。
这个机制叫 路径 MTU 发现(Path MTU Discovery)。换成大白话:从"卡车司机看隧道太低就自己把货拆了",改成"隧道口挂个牌子退回你,并告诉你限高多少,你自己回去重新装车"。
哪个更好?后者明显更好,理由是责任放在了唯一知道全局的人身上:发送方知道这批货一共有多少、怎么拆最合适;而路径上的路由器只看到眼前这一件,它拆得再对也是盲拆。而且发送方拆完之后每一片都是独立完整的包,丢了可以单独重传——不会出现"丢一片全废"的情况。
这也带来一条实践建议,和 §3.3 讲 UDP 时那条是一致的:应用层最好主动把数据切成不超过约 1400 字节的块,给各种隧道封装留出余量,从根上避免触发分片。
路由:一张表、一条规则、一个默认出口
前面那个快递分拣的类比已经把路由讲清了,这里补上具体形式。
路由表(Routing Table)就是一张对照表,每一行说的都是同一件事:"去往某一片网络,请把包交给某个下一跳"。
【一台普通电脑的路由表长什么样】
目标网络 子网掩码 下一跳(网关) 出口网卡
0.0.0.0/0 0.0.0.0 192.168.1.1 wlan0
↑ 默认路由:"所有我不认识的地址,一律交给 192.168.1.1"
这就是"小区大门"
192.168.1.0/24 255.255.255.0 直连(无需网关) wlan0
↑ "同一个小区的邻居,我直接找他,不用出门"
127.0.0.0/8 255.0.0.0 直连 lo
↑ "找我自己,压根不出网卡"
【转发决策的三步,每个包都走一遍】
① 看包上的目标地址
② 在表里找所有"匹配"的行
③ 从匹配的行里挑前缀最长(最具体)的那一行,
按它指定的下一跳发出去
【举例:目标是 8.8.8.8】
和 192.168.1.0/24 匹配吗? → 不匹配
和 127.0.0.0/8 匹配吗? → 不匹配
和 0.0.0.0/0 匹配吗? → 匹配(这一行匹配一切)
→ 交给 192.168.1.1(家里路由器)
【举例:目标是 192.168.1.20】
和 192.168.1.0/24 匹配吗? → 匹配!(前 24 位一致)
和 0.0.0.0/0 匹配吗? → 也匹配
→ 两个都匹配,选前缀更长的 /24
→ 直连发出,不经过路由器
★ 最长前缀匹配(Longest Prefix Match)
换成大白话:好比公司规章 ——
"研发部出差报销"和"全公司出差报销"两条都适用时,
按更具体的那条办。
越具体的规则优先级越高。
那条 0.0.0.0/0 值得多说一句,因为它是最优雅的一个设计。/0 意思是"零位需要匹配",也就是匹配所有地址。所以它永远是最后被选中的那一行——因为它的前缀最短、最不具体。
好比分拣表上最后那句"其他任何地方 → 总仓"。它一定成立,所以永远兜得住;但它也一定是最不具体的,所以只要有别的行对得上,就先用别的。这一行的存在意味着你家路由器压根不需要知道全世界的地址——不认识的一律往运营商那边推就行了。
路由表里的内容从哪来?分两类,理解这个分类能解释很多现象:
- 静态路由人手工写上去的。好比把分区表打印出来贴墙上——简单可控,但路况变了没人自动更新,得有人去改。家用路由器、小型网络基本靠这个。
- 动态路由路由器之间互相通报"我这边能到哪些网络",自动算出最优路径。好比各个分拣中心之间用对讲机互相通气:"我这条线路断了,你们别往我这送。"优点是链路一坏,几秒到几十秒内全网自动绕开;代价是复杂得多。互联网骨干之间用的是一套叫 BGP 的协议来做这件事,属于第 5 章的内容。
IPv6:从 32 个格子扩到 128 个格子
IPv4 的 43 亿个地址不够用,这件事在 1990 年代初就已经很清楚了。IPv6(规范是 RFC 8200,它在 2017 年成为互联网标准,取代了 1998 年的 RFC 2460)的核心改动只有一句:地址从 32 位扩到 128 位。
但这个"从 32 到 128"意味着什么?它不是多了四倍,是多了一个天文数字级别的量。
【128 位到底是多少?】
IPv4:2^32 ≈ 43 亿个
IPv6:2^128 ≈ 340 万亿亿亿亿个
(3.4 后面跟 38 个零)
【换算成能感知的量】
· IPv6 的地址数量,够给地球表面
每一平方毫米都分配上亿亿个地址
· 如果 IPv4 的地址总量相当于一粒沙,
IPv6 相当于……这个类比压根打不出来,
因为地球上的沙子总数远远不够。
★ 所以设计者的态度是:
这一次要多到"永远不用再考虑省着用"。
IPv4 时代那种"一个地址都不能浪费"的紧张
在 IPv6 里完全消失了 ——
一个普通家庭宽带通常会被分到
一整段(常见的分配粒度是 /64 或更大),
里面的地址数量比整个 IPv4 互联网还多。
★ 换成大白话:
从"七位数电话号码,全国都快分完了"
变成"号码长度加了一大截,
从此谁想要多少给多少,不用排队申请"。
IPv6 的写法和 IPv4 完全不同,需要单独学一下,不然看到那一串东西会懵:
【IPv6 地址的写法】
完整形式(八段,每段四个十六进制字符):
2001:0db8:0000:0000:0000:ff00:0042:8329
↑ 用冒号隔开,不是点
【简写规则一:每段前面的 0 可以省】
2001:db8:0:0:0:ff00:42:8329
【简写规则二:连续全是 0 的段可以用 :: 代替】
2001:db8::ff00:42:8329
↑ 这个 :: 代表"这里有若干段全零"
★ 但 :: 在一个地址里只能出现一次!
否则就无法确定每边各有几段零了。
好比填空题:"2001:__:__:5" ——
如果两处都用省略号,你没法算出总共八段该怎么分。
【几个要认识的 IPv6 地址】
::1 回环地址,相当于 IPv4 的 127.0.0.1
:: 全零,相当于 IPv4 的 0.0.0.0
fe80::/10 链路本地地址 —— ★ 你的每张网卡都会自动有一个,
只在本网段有效,跨路由器无效
ff00::/8 多播地址
2000::/3 目前主要分配给全球单播使用的范围
★ 注意:IPv6 里压根没有"广播地址"这个概念,
广播的功能全部由多播承担 ——
因为广播太吵,打扰所有人;
多播只打扰订阅了的那些人。
换成大白话:从"全楼大喇叭"
改成"只通知报了名的那几个班"。
除了地址变长,IPv6 还做了几处很值得知道的简化。这些改动的共同思路是:把 IPv4 头部里那些"路由器每一跳都要处理、但其实没必要"的东西全砍掉。
| 改动 | IPv4 的做法 | IPv6 的做法 | 为什么这么改 |
|---|---|---|---|
| 头部校验和 | 有,每一跳都要重算(因为 TTL 变了) | 直接删掉 | 链路层和传输层都已经在校验,重复劳动 |
| 分片 | 路由器可以切 | 路由器不许切,由发送方负责 | 只有发送方知道全局,路由器盲切代价大 |
| 头部长度 | 可变(20~60 字节,有可选项) | 固定 40 字节,扩展信息放在后面挂链 | 固定长度让硬件处理快得多 |
| TTL 的名字 | Time To Live(误导) | Hop Limit(跳数限制) | 正名而已,行为一直是数跳数 |
| 地址配置 | 靠 DHCP 分配 | 可以自动配置,也可以用 DHCPv6 | 设备太多,人工和集中分配都吃不消 |
| 广播 | 有广播地址 | 取消广播,全用多播 | 广播打扰所有人,浪费所有设备的处理能力 |
| ARP | 用 ARP 协议找邻居的物理地址 | 换成邻居发现协议(NDP,走 ICMPv6) | 整合进 ICMPv6,见 § 3.6 |
那"自动配置"是怎么回事?这是 IPv6 一个很实用的特性,叫 SLAAC(Stateless Address Autoconfiguration,无状态地址自动配置)。路由器定期在网络里广播(准确说是多播)一条消息:"这一片网络的前缀是某某。"设备听到之后,自己把这个前缀和自己的接口标识拼起来,就得到一个完整地址了——不需要任何服务器给它分配。
换成大白话:从"必须去人事领工位号"变成"墙上贴着『这是三楼西区』,你自己在名牌上写『三楼西区 + 我的名字』就行了"。好处是不需要一个中心服务器管分配,坏处是管理员对"谁拿到了什么地址"的掌控变弱了——所以企业环境里往往还是会用 DHCPv6。
那 IPv6 为什么普及得这么慢?这是一个非常经典的技术迁移难题,理由值得如实列出来:
- IPv4 和 IPv6 之间无法直接互通这是最根本的问题。只有 IPv6 地址的机器和只有 IPv4 地址的机器,压根没法直接说话——它们的地址格式不兼容,中间必须有翻译。好比两个人一个只会中文一个只会阿拉伯语,得请个翻译在中间。
- 所以只能"两套并行"过渡现实做法叫双栈(dual stack)——设备同时拥有 IPv4 和 IPv6 两套地址,两条路都能走。代价是所有设备、所有软件、所有配置都要维护两份,运维成本翻倍。
- NAT 太好用,把紧迫感消解掉了这是最讽刺的一点:NAT 本来是个临时的应急手段,结果它太成功了,让 IPv4 又多撑了二十多年——于是升级 IPv6 的动力一直不足。好比房子漏水,本来该翻修屋顶,但接水盆太好用了,于是接了二十年。
- 迁移的收益不归先动手的人你把自己的网络升级到 IPv6,但只要还有大量对端只有 IPv4,你就必须继续维护 IPv4。先动手的人成本全担、好处没多少——这和 §3.4 讲 DNSSEC 部署难时是同一个结构。
值得一提的是移动网络推动了 IPv6 的普及——手机数量太庞大,纯靠 NAT 撑不住,所以很多地区的移动网络实际上已经是 IPv6 为主。这也符合技术迁移的一般规律:新技术往往先在"旧方案实在扛不住"的那个角落里落地,而不是在存量最大的地方。
动手看看自己的 IP
前面讲的东西,你电脑上全都能查到。这几条命令值得记住,它们是排查任何网络问题的第一步。
# 【Windows】看本机所有地址、掩码、网关
> ipconfig /all
IPv4 地址 . . . . . . . . : 192.168.1.8 ← 你的门牌号
子网掩码 . . . . . . . . . : 255.255.255.0 ← /24,那把尺子
默认网关 . . . . . . . . . : 192.168.1.1 ← 小区大门
# 【Windows】看路由表
> route print
# 【Windows】看邻居的物理地址对照表(ARP 表,见 § 3.6)
> arp -a
# 【Linux / macOS】看地址
$ ip addr # 现代 Linux
$ ifconfig # 老写法,macOS 上仍常用
$ ip route # 看路由表
default via 192.168.1.1 dev wlan0
↑ 这一行就是 0.0.0.0/0,你的默认出口
192.168.1.0/24 dev wlan0 proto kernel scope link src 192.168.1.8
↑ 直连网段:这一片的邻居我直接找,不用出门
$ ip -6 addr # 只看 IPv6 地址
$ ip neigh # 看邻居表(相当于 arp -a)
# 【看自己的公网地址】
# 因为在 NAT 后面,本机看到的是私网地址,
# 要问外面的人"你看到我是谁"才知道公网地址。
$ curl ifconfig.me
$ curl ipinfo.io/ip
↑ 换成大白话:你在办公室里看不到公司大楼的门牌号,
得打电话问外面的人"你看我这封信是从哪寄出的"。
# 【判断某个地址是公网还是私网】速查
10.x.x.x → 私网
172.16.x.x ~ 172.31.x.x → 私网(★ 注意只有这 16 个)
192.168.x.x → 私网
127.x.x.x → 本机自己
169.254.x.x → ★ 没拿到地址,DHCP 失败了
100.64.x.x ~ 100.127.x.x → 运营商级 NAT 的内部地址
其他 → 一般是公网地址
再给一张常见故障对照表,把"你看到的地址"翻译成"大概是哪一环出了问题"。这张表非常实用,值得记住:
| 你看到的情况 | 说明什么 | 该往哪查 |
|---|---|---|
地址是 169.254.x.x | 没拿到地址,自己随便编了一个 | 路由器的 DHCP 服务;网线;WiFi 认证 |
| 能 ping 通网关,ping 不通外网 | 小区内部好的,出门那条路有问题 | 路由器的外网配置;宽带欠费;运营商线路 |
| 能 ping 通外网 IP,域名打不开 | 网络层没问题,是 DNS 的事 | 见 § 3.4 的排障表 |
| ping 不通同一网段的邻居 | 可能掩码配错了,两台机器"自认为"不在同一小区 | 核对两边的掩码是否一致 |
| 两台机器地址一样 | 地址冲突,两边都会时通时断 | 关掉手工配的那个,交给 DHCP 统一分配 |
| 大文件传输卡死,小文件正常 | 典型的 MTU / 分片问题 | 调小 MTU;检查隧道封装是否吃掉了余量 |
| 路由器上设了端口映射还是访问不到 | 可能上面还有一层运营商级 NAT | 看路由器的"公网地址"是不是 100.64 开头 |
倒数第三行那个"掩码配错"的情况很值得说一句,因为它的表现非常反直觉:两台机器地址明明看起来在一个网段,却互相 ping 不通。原因是它们对"哪条线是小区边界"的理解不一致——一台认为掩码是 /24(同一小区),另一台认为是 /25(不同小区,得出门)。好比两个人对"我们算不算一个片区"看法不一样:一个直接串门,另一个非要绕到大门口去登记——结果永远碰不上。
常见误解澄清
- 误解一:"IP 地址能定位到具体某个人的家门口"不能。IP 地址通常只能大致对应到一个城市或运营商片区,而且家用地址往往是动态分配、定期变化的,还可能有很多户共用一个(运营商级 NAT)。相当于只知道包裹是从某个分拣中心发出的,推不出是哪一户寄的。
- 误解二:"IP 地址是固定不变的"不一定。家用宽带的公网地址通常是动态的(重启光猫可能就换了);内网地址由 DHCP 分配,也有租期。只有你专门申请的固定地址才不变。
- 误解三:"192.168 开头的地址不安全 / 是假地址"不对。它是完全合法的私网地址,只是只在你自己的网络里有效。相当于内线号码——不是假号码,只是范围有限。
- 误解四:"NAT 就是防火墙"不是。NAT 的目的是省地址,"外面进不来"只是副作用。它不检查内容、不识别恶意流量、也不管你的设备主动往外连了什么。真正的防火墙是另一回事(第 8 章讲)。
- 误解五:"私网地址段是 10、172、192 这三个数字开头"说法太粗,容易出事。准确的是三段 CIDR:
10.0.0.0/8、172.16.0.0/12、192.168.0.0/16。尤其中间那段只覆盖 172.16 到 172.31,不是整个 172;而 192.168 是完整的 /16,不只是 192.168.1。 - 误解六:"IPv6 只是把地址变长了"不止。它还取消了广播、取消了路由器分片、删了头部校验和、把 ARP 换成了邻居发现、加了地址自动配置。这些改动都指向同一个目标:让路由器每一跳干的活更少。
- 误解七:"TTL 是时间"不是。它数的是还能被转发几次。IPv6 已经把它正名为 Hop Limit(跳数限制)。名字里带 Time,但它一天也不数秒。
- 误解八:"IP 保证数据能送到"完全不保证。IP 只承诺"尽力送",丢了不通知、乱了不管、重复了也不管。所有这些保证都是 TCP 加上去的(§ 3.2)。
最后把 IP 在整个协议栈里的位置定个位,方便你把这一章串起来:IP 在下面负责"送到哪台机器",TCP / UDP 在上面负责"送到哪个程序、以及保不保证送到",DNS 在旁边负责"把名字换成地址"。三者分工清清楚楚,任何一次上网都同时用到了它们。第 4 章会把这三样按时间顺序串成一条完整的访问流程。
一句话总结:IP 是门牌号加分拣规则——它只承诺"尽力往那个方向送",别的一概不管,而正是这份"不管"让它能撑起全球规模。
地址上记住三件事:
· IPv4 地址就是 32 个格子(RFC 791),每段最多 255 是因为 8 个格子最大就这么大;IPv6 扩到 128 个格子(RFC 8200)。
· 地址分两半:前半段是"哪个小区",后半段是"哪一户"。而子网掩码就是那把"划线尺",CIDR(RFC 4632)是这条线画在第几位的简写。往右挪 = 小区多、每个小区人少;往左挪 = 小区少、每个小区人多。
· 三段私网地址(RFC 1918)必须记准:10.0.0.0/8、172.16.0.0/12(只有 172.16 到 172.31)、192.168.0.0/16。
机制上记住三件事:
· 路由是逐跳接力,每台路由器只看目标地址、查表、扔给下一跳,谁都不知道全程;表上永远有一行默认路由 0.0.0.0/0 兜底;多行匹配时按最长前缀取胜。
· NAT(RFC 3022)用端口号换地址,把地址需求从"每台设备一个"降到"每户一个"。代价是外面无法主动连进来、破坏了端到端、且可能在运营商那里再套一层。
· TTL 数的是跳数不是秒数,它防环路,也让 traceroute 能画出整条路线。
下一节讲配角合集——ARP、ICMP、DHCP、SSH、FTP、SMTP。它们平时你注意不到,但你 ping 不通的时候、抓包看到一堆 ARP 的时候、连不上 WiFi 的时候,全是它们在说话。