§ 3.5 · Section

IP

Internet Protocol

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好比全国的快递公司、卡车品牌、包装规格千差万别,但"收件地址怎么写"全国统一——正因为这一条统一了,其他的才能各干各的。

Analogy · 快递分拣中心:路由的全部真相

如果你只记住这一节的一个类比,请记住这个。它能同时解释路由表、网络号、子网掩码和默认路由这四样东西。

想象一个快递分拣中心。传送带上一件件包裹过来,分拣员站在旁边,墙上贴着一张表:

发往「北京市 海淀区 ...」 → 扔进 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 地址不是一个整体,它是两半拼起来的:

为什么非要分成两半?因为这直接决定了路由器要不要费劲。回到快递分拣的画面:分拣员看"北京海淀"这几个字就能决定往哪个笼子扔,他压根不需要看"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 开头。
Analogy · 快递分区表上的那把尺子

子网掩码之所以让人头疼,是因为它总被当成"一个要背的数字"。其实它就是一句话:"地址前面几个字,我拿来当地区看。"

回到分拣中心。假设包裹地址统一写成十二位数字,比如 110108003502。分拣员墙上贴着一句话:

"前六位是片区,后六位是具体门牌。"

于是他看到 110108|003502,只关心前面的 110108——这就是他要匹配的东西。那句"前六位是片区"就是子网掩码,写成 CIDR 就是 /6(这里只是打比方,真实 IP 是按二进制位算的)。

现在关键的一步来了:这条线可以移动,而且移动它会同时改变两件事。

线往右移(网络位变多,比如从 /24 移到 /26)片区划得更细了 → 片区数量变多,但每个片区里能装的门牌变少。好比本来"整个海淀区"算一个片区,现在细分成"海淀北部、海淀中部、海淀南部、海淀西部"——片区多了四倍,每个片区管的户数少了四分之三。

线往左移(网络位变少,比如从 /24 移到 /22)片区划得更粗 → 片区数量变少,但每个片区能装的门牌变多。好比把海淀、朝阳、东城、西城合成一个大片区——片区少了,但一个片区里的户数翻了几倍。

这就是子网划分的全部内容,一句话你在 32 个格子上挪那条竖线,往右挪就是"多分小区、每个小区少装人",往左挪就是"少分小区、每个小区多装人"。总人数是固定的,你只是在决定怎么分组。

为什么要分?三个非常实在的理由:① 隔开——财务部和访客 WiFi 分在不同小区,串门要经过门卫,好管好防;② 减少吵闹——同一个小区里的"喊话"(广播)所有人都听得到,小区太大就吵得没法工作;③ 好规划——每个部门一个小区,看地址就知道是谁,排查问题快得多。

再给一张最实用的对照表。这张表建议直接记住常用的那几行,因为它是网络配置里天天用到的:

CIDR子网掩码地址总数可用主机数说白了就是
/8255.0.0.01677721616777214一个超级大区,能装一千六百多万台
/16255.255.0.06553665534一个大区,六万多台——大企业整个园区的量级
/22255.255.252.010241022一千台出头,中型办公楼
/24255.255.255.0256254最常见的一档,家用路由器默认就是这个
/25255.255.255.128128126把一个 /24 对半劈开
/26255.255.255.1926462一个 /24 切成四份,一个部门一份
/28255.255.255.2401614十几台,一个小机柜
/30255.255.255.25242只够两台——专门用来连两台路由器之间的那根线
/31255.255.255.25422(特例,见 RFC 3021)点对点链路的省地址写法
/32255.255.255.25511就指定这一个地址,常用于路由和防火墙规则

为什么"可用主机数"总是比"地址总数"少 2 个?这是最常被问的问题。因为每一段网络里有两个地址被征用了,不能分给机器:

/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/810.0.0.0 ~ 10.255.255.255约 1677 万个一个 A 类大企业、云服务商内网、大规模数据中心
172.16.0.0/12172.16.0.0 ~ 172.31.255.255约 104 万个16 个连续的 B 类中型企业;Docker 默认网段常在这个范围
192.168.0.0/16192.168.0.0 ~ 192.168.255.25565536 个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.x172.32.x.x 都是公网地址,不属于私网。这个边界记错会导致很实际的配置事故。

Analogy · 内线号码:为什么每家公司都有 8001

私网地址这件事,用办公室内线来理解一秒就通。

你在一家公司上班,前台内线是 8001。你朋友在另一家公司,前台内线也是 8001这两个 8001 之间完全没有冲突,因为它们只在各自那栋楼里有意义。

你在自己公司拨 8001,接的是自己公司前台;你朋友拨 8001,接的是他公司前台。两个人都用同一个号码,但谁也不会串线——因为这个号码出了这栋楼就不存在

那怎么打给外面的人?你得先拨一个 0(或者 9,各公司规矩不同)转外线。这个"拨 0 转外线"的动作,就是把内部号码换成"公司总机 + 外拨"的过程——这正是 NAT 做的事。

反过来,外面的人怎么找到你?他不能直接拨 8001——那个号码在外面不存在。他只能拨公司总机,然后跟前台说"我找财务部的小李",前台再帮他转到 8001。这解释了私网最重要的一个后果:外面的人无法主动找到你,除非有人在前台替你留了转接规则。

为什么要这么设计?因为电话号码不够用了——如果全国每一个内线都要一个独立的正式号码,号码资源早就耗尽了。"内部随便编号 + 出门统一换成总机号"这一招,让号码需求从"每个人一个"降到"每家公司一个"。

顺带的好处也很实在:外面的人默认打不进来。这不是刻意设计的安全机制,但它事实上挡掉了绝大多数来自外部的主动扫描和攻击尝试。很多人把这当成"路由器自带防火墙",其实那只是私网加 NAT 的副作用。

除了这三段私网,IPv4 里还有几段有特殊用途的地址,遇到它们时能一眼认出来会很有用:

地址段叫法说白了就是你什么时候会见到
127.0.0.0/8回环地址(Loopback)"我自己"——发给它的包压根不出网卡127.0.0.1localhost,本地开发天天用
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 意思是"零位需要匹配",也就是匹配所有地址。所以它永远是最后被选中的那一行——因为它的前缀最短、最不具体。

好比分拣表上最后那句"其他任何地方 → 总仓"。它一定成立,所以永远兜得住;但它也一定是最不具体的,所以只要有别的行对得上,就先用别的。这一行的存在意味着你家路由器压根不需要知道全世界的地址——不认识的一律往运营商那边推就行了。

路由表里的内容从哪来?分两类,理解这个分类能解释很多现象:

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 为什么普及得这么慢?这是一个非常经典的技术迁移难题,理由值得如实列出来:

值得一提的是移动网络推动了 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 在下面负责"送到哪台机器",TCP / UDP 在上面负责"送到哪个程序、以及保不保证送到",DNS 在旁边负责"把名字换成地址"。三者分工清清楚楚,任何一次上网都同时用到了它们。第 4 章会把这三样按时间顺序串成一条完整的访问流程。

Recap · 收束

一句话总结:IP 是门牌号加分拣规则——它只承诺"尽力往那个方向送",别的一概不管,而正是这份"不管"让它能撑起全球规模。

地址上记住三件事
· IPv4 地址就是 32 个格子(RFC 791),每段最多 255 是因为 8 个格子最大就这么大;IPv6 扩到 128 个格子(RFC 8200)。
· 地址分两半:前半段是"哪个小区",后半段是"哪一户"。而子网掩码就是那把"划线尺",CIDR(RFC 4632)是这条线画在第几位的简写。往右挪 = 小区多、每个小区人少;往左挪 = 小区少、每个小区人多。
· 三段私网地址(RFC 1918)必须记准10.0.0.0/8172.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 的时候,全是它们在说话。

☰ 主页
Xue Hai Wu Ya · Network · § 3.5 · IP