【计算机网络】| 从ping 不通出发:NAT 与 DHCP 在做什么

👋 关于作者

你好,这里是一条 泥憨鱼 | 专注于 后端开发 、AI 前沿技术与计算机基础 。

🏠 个人主页 :一条泥憨鱼

通过技术博客记录技术成长,分享学习心得与经验。期待与您共同交流!

📚精选技术专栏:

|-------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------|
| ❄️后端开发 | ❄️Redis| 黑马点评 |
| ❄️从0开始学习计算机网络 | ❄️数据结构与算法 |
| ❄️苍穹外卖 | ❄️探秘AI与agent |

把笔记本插上网线就能上网,而家里那台服务器从公司却怎么也连不进去。这两个现象背后是两套机制:DHCP 负责把地址发下来,NAT 负责把内网流量送出去。

为什么需要 NAT

IPv4 地址是 32 位,理论上约 43 亿个。这个数字在 1990 年代就被认为不够用了,原因不只是设备多,还在于地址分配本身是分块的:早期按 A/B/C 类划分,一个 B 类就吃掉 65536 个地址,很多组织拿到的地址段实际只用了一小部分。IPv6 是最终解法,但迁移成本高、周期长,中间必须有个过渡方案,这就是 NAT。

NAT(Network Address Translation,网络地址转换) 要解决的核心矛盾很具体:内网有一大批设备需要访问公网,但公网只给这个组织分配了少量甚至一个公网地址。

它给出的办法是在内网和公网之间放一个转换点(通常是路由器或防火墙)。内网设备用私有地址(10.0.0.0/8、172.16.0.0/12、192.168.0.0/16 这三段,RFC 1918 规定),这些地址不会出现在公网上。数据包经过转换点时,源地址被改写成公网地址;回来的包再改回内网地址。

代价随之而来。NAT 是有状态的:它必须记住"这个内网地址对应哪个公网地址",才能把回包还原。这意味着外部主机无法主动发起连接------转换表里没有对应条目,包到了就被丢弃。这也是为什么家庭宽带默认无法从外面直接访问内网服务,需要端口映射或内网穿透。另一个副作用是破坏端到端透明性:应用层如果把自己的 IP 写进载荷(比如 SIP、FTP 主动模式),NAT 不知道要改,就会出现连不通的怪问题。

NAT 的三种形态

按映射粒度,NAT 分成三类。理解它们的关键是问一句:内网地址和公网地址之间是几对几的关系?

静态 NAT 是一对一固定映射。管理员手工配好 192.168.1.10 与 203.0.113.5 的对应关系,之后这个内网地址出去永远用这个公网地址。因为映射固定,外部也能通过这个公网地址主动访问进来,常用于把内网服务器发布到公网。缺点是每个内网地址都独占一个公网地址,省不下来。

动态 NAT是一对一轮询。准备一个公网地址池,内网设备要出网时从池里借一个,用完还回去。它比静态 NAT 灵活,但映射粒度仍是一对一,池子里有多少地址就最多支持多少台设备同时出网。设备一多就排队。

NAPT(Network Address Port Translation),也叫 PAT、端口复用,是真正让 IPv4 撑到今天的方案。它把映射粒度降到端口级:多个内网地址可以共用一个公网地址,靠不同的源端口区分。一台家用路由器只有一个公网 IP,却能让手机、电脑、电视同时上网,靠的就是它。

| 类型 | 映射粒度 | 公网地址需求 | 外部能否主动访问 |

| 静态 NAT | 一对一固定 | 每个内网地址一个 | 能 |

| 动态 NAT | 一对一轮询 | 池大小决定并发 | 不能(映射不固定) |

| NAPT/PAT | 多对一,按端口区分 | 可仅一个 | 不能(除非配端口映射) |

主流是 NAPT,原因很直接:在地址最紧张的场景下,它把"地址"这个稀缺资源换成了"端口"这个相对充裕的资源。一个公网 IP 有 65535 个端口可用,理论上能支撑数万个并发会话。

NAPT 内部如何运转

NAPT 的核心是一张转换表,出站时建表,入站时查表。整条链路分两个方向。

出站方向,内网主机发出一个包,源地址是 192.168.1.10:50000,目标是公网某服务器 198.51.100.20:80。转换节点收到后做三件事:

  1. 给这个会话分配一个公网源端口,比如 40001;

  2. 记录一条表项:内网 192.168.1.10:50000 与公网 203.0.113.5:40001 的对应关系,对端 198.51.100.20:80;

  3. 改写报文头,源地址变成 203.0.113.5:40001,转发出去。

报文改写前后的对比大致是这样:

复制代码
出站前:192.168.1.10:50000  ->  198.51.100.20:80

出站后:203.0.113.5:40001   ->  198.51.100.20:80

入站前:198.51.100.20:80    ->  203.0.113.5:40001

入站后:198.51.100.20:80    ->  192.168.1.10:50000

入站方向反过来。服务器回包,目标地址是 203.0.113.5:40001。转换节点拿目的端口 40001 去查表,找到对应内网地址 192.168.1.10:50000,把目的地址改写回去,再转发给内网主机。

这里有个容易忽略的细节:查表不只看端口,还要看协议和对端地址。 因为 TCP 和 UDP 的端口空间是独立的,同一个端口号 40001 可以同时被 TCP 和 UDP 占用;对端地址用来区分不同会话,避免误匹配。

所以 NAT 的本质是连接状态。表项存在,回包能还原;表项不存在,包直接被丢。这也解释了前面那个现象:外部主动连进来时,表里没有对应条目,包无处可去。表项还有生存时间,TCP 会话结束后会保留一段时间(常见几十秒到几分钟),UDP 因为没有明确的结束信号,超时通常更短。会话空闲太久,表项被清理,再来的回包就会被丢弃------这是长连接应用在 NAT 环境下偶发断连的原因之一,通常需要靠心跳保活。

DHCP 四步握手

**DHCP(Dynamic Host Configuration Protocol)**解决的问题正好相反:设备刚接入网络时,既没有 IP,也不知道网关和 DNS 是谁,怎么把地址发到它手上?

答案是四步握手,名词很好记:Discover、Offer、Request、ACK。

Discover:客户端以广播方式发出,源地址 0.0.0.0,目的地址 255.255.255.255,意思是"谁是 DHCP 服务器,我需要地址"。因为客户端此时没有任何地址,只能用广播。

Offer:服务器收到后,从地址池里挑一个可用地址,回一个 Offer,里面带上 IP、子网掩码、网关、DNS、租约时长。如果网络里有多个 DHCP 服务器,客户端可能收到多个 Offer。

Request:客户端从收到的 Offer 里选一个,广播发出 Request,告诉所有服务器"我要用这个地址"。这一步是关键------因为它是广播,其他服务器看到后会收回自己刚才的 Offer,把地址放回池子。如果没有这一步,多个服务器都以为自己分配成功,就会出现地址冲突。

ACK:被选中的服务器确认,客户端正式获得地址,可以开始通信。

地址不是永久给的,而是租约。租约到期前,客户端会尝试续租:先单播给原服务器发 Request,服务器回 ACK 续期。如果原服务器没响应,租约过半后会向整个网段广播续租请求。租约彻底过期还没续上,客户端就得重新走一遍 Discover 流程。租约机制的好处是地址可以回收再利用------设备拔走之后,地址不会永远占着。

为什么 DHCP 基于 UDP

这里有个鸡生蛋的问题:客户端还没有 IP,怎么通信?

TCP 要求先建立连接,而建立连接需要双方都能收发报文,意味着双方都得有地址。客户端此刻连自己的地址都没有,TCP 根本不成立。UDP 是无连接的,发出去就不管,不需要预先握手,正好适配这个场景。

具体到地址使用,DHCP 有几个边界细节:

  • 客户端发 Discover 和 Request 时,源地址是 0.0.0.0,目的地址是 255.255.255.255。0.0.0.0 表示"我还没有地址",广播表示"我不知道服务器在哪,全网喊一声"。

  • 服务器回 Offer 和 ACK 时,如果客户端还不能接收单播(有些系统要求先完成配置才能收单播),服务器会用广播;否则用单播。

  • 端口固定:服务器监听 67,客户端监听 68。

还有一个常被忽略的设计:DHCP 报文可以带一个 giaddr(网关 IP 地址)字段,用来支持跨网段分配。因为广播不能穿过路由器,如果 DHCP 服务器和客户端不在同一个网段,就需要中继代理(DHCP Relay)把广播转成单播发给服务器,并在 giaddr 里填上自己的地址,服务器据此判断该从哪个地址池分配。企业网络里一台 DHCP 服务器管多个 VLAN,靠的就是这个。

收束

回到开头那两个现象:能上网说明 NAT 和 DHCP 都在正常工作,从外面连不进来说明 NAT 表里没有对应条目。这两件事的机理可以概括成一句话:NAT 靠状态,DHCP 靠广播。

排查内网访问问题时,先分清是地址分配层还是地址转换层。设备拿不到 IP、拿到的是 169.254.x.x,问题在 DHCP------检查地址池是否耗尽、中继是否配好、服务器是否可达。设备有正常 IP 但访问不了外网、或者外部连不进来,问题在 NAT------看转换表有没有对应条目、端口映射是否配置、会话是否已超时被清理。

相关推荐
下辈子不要当码农1 小时前
Linux驱动(2)
linux·运维·单片机
m0_587383001 小时前
碰碰好评卡功能落地实战 从需求梳理到上线部署全流程实操指南
java·linux·服务器·前端·javascript·vue.js·人工智能
壹玖玖肆1 小时前
openGauss 7.0 Docker 部署 + 跨版本迁移全流程(aarch64)
运维·docker·容器
筑梦之路1 小时前
Alibaba Cloud Linux 4 制作 Ansible RPM包实践(离线可复用)——筑梦之路
linux·运维·ansible
ITxiaobing20231 小时前
自研 IP 库与 AppsFlyer 地理位置判定不一致,该如何排查?
网络·数据库·tcp/ip
承渊政道1 小时前
Linux网络学习【应用层自定义协议与序列化实战:从手写序列化与反序列化到深入理解进程间关系与守护进程】
linux·网络·学习·ubuntu·json·序列化与反序列化
玩AI的奶茶1 小时前
什么情况适合租算力?一张场景对照表,加三个自测问题
大数据·linux·服务器·数据库·人工智能·python
IT利刃出鞘1 小时前
Linux权限--adduser和useradd的区别
linux·运维·服务器
天意__1 小时前
Android手机上部署Linux服务器 在Termux里安装Ubuntu
android·linux·服务器