【计算机网络】第 13 篇:NAT 和端口映射是什么?为什么本地服务外网访问不了?

系列: 从 0 开始学习计算机网络

适合读者: 计算机专业学生、Java 后端学习者、需要部署本地服务的开发者

本文关键词: NAT、NAPT、私有 IPv4 地址、端口映射、CGNAT、Spring Boot

一、引言:服务明明启动了,为什么外网还是访问不了?

假设你在电脑上启动了一个 Spring Boot 项目,服务监听 8080 端口。在本机访问 http://localhost:8080 没问题,同一 Wi-Fi 下的手机也可能通过电脑的局域网 IP 访问。

但当你把电脑的公网 IP 和端口发给校外朋友,对方却访问失败。

这不一定是 Java 代码写错了。请求从互联网到达内网服务,途中可能遇到多个问题:

  • 内网设备使用的地址不是互联网可直接路由的公网地址;
  • 路由器只为内网主动发起的连接维护了地址转换状态,没有配置外部入站转发;
  • 主机防火墙或路由器防火墙阻止了请求;
  • 运营商使用了运营商级 NAT(CGNAT),你并没有可直接控制的公网 IPv4 入口;
  • 服务只监听在 127.0.0.1,没有监听局域网接口。

本文专门解释 NAT 为什么能让内网设备访问互联网、端口映射如何让外部请求进入内网,以及外网访问失败时如何判断问题在哪一层。不重复前面已经讲过的子网掩码计算、路由基础和通用网络排查命令。

二、先区分公网 IP、私有 IP 和端口

2.1 私有 IPv4 地址是什么?

很多家庭或公司局域网使用私有 IPv4 地址。根据 RFC 1918,常见的私有地址范围有三段:

私有地址范围 CIDR 表示 常见例子
10.0.0.0 至 10.255.255.255 10.0.0.0/8 10.1.2.3
172.16.0.0 至 172.31.255.255 172.16.0.0/12 172.20.1.5
192.168.0.0 至 192.168.255.255 192.168.0.0/16 192.168.1.20

这些地址可以在不同组织的内部网络中重复使用。它们没有全球唯一的公网路由意义,互联网中的路由器不会把它们当作普通公网目的地址直接转发。

因此,内网电脑的 192.168.1.20 并不能直接充当一个全球可达的服务器地址。

2.2 公网 IP 是什么?

公网 IPv4 地址通常由运营商或云服务商分配,并在公共互联网路由体系中具有全球唯一的可路由意义。这里的"公网"不等于"所有人都一定能访问":防火墙、路由策略、服务监听和运营商限制仍然可能阻止连接。

本文图中的 198.51.100.10、203.0.113.50 是专门用于文档示例的地址,不代表真实服务器。

2.3 IP 地址和端口分别负责什么?

可以先这样理解:

  • IP 地址:帮助网络把数据送到目标主机或网络接口。
  • 端口:在 TCP/UDP 等传输层协议中,帮助数据到达目标主机上的相应服务端点。

例如:

text 复制代码
192.168.1.20:8080

表示地址为 192.168.1.20 的主机上,TCP 或 UDP 的某个端口 8080。在 Web 开发场景中,我们通常说 Spring Boot 的 HTTP 服务监听 TCP 8080 端口。

要特别注意:端口号本身不决定协议。TCP 8080 和 UDP 8080 是不同的传输层端点;设置端口转发时,必须选择正确的协议。

三、NAT 是什么?内网设备如何访问互联网?

NAT 的全称是 Network Address Translation,即网络地址转换。它由路由器或其他网络设备修改数据包中的地址信息,使不同地址空间之间能够通信。

在家庭网络中,最常见的做法是让多台内网设备共享路由器的一个公网 IPv4 地址。实际部署中通常还会转换 TCP/UDP 端口,这种做法常称为 NAPT(Network Address and Port Translation),也经常被叫作 PAT 或 NAT Overload。不同厂商对这些术语的使用可能略有差异。

3.1 通过一个例子理解出站 NAT

假设:

  • 内网电脑:192.168.1.20
  • 路由器公网侧地址:198.51.100.10
  • 目标服务器:203.0.113.50:443

电脑发起连接时,可能使用一个临时源端口,例如 52341。路由器把出站流量的源地址和源端口转换为公网侧的地址与端口,例如 198.51.100.10:40001,并记录这条映射。

外部服务器返回数据时,响应报文到达路由器公网侧。路由器根据映射把目标地址和端口还原为内网电脑对应的地址与端口,再转发给原来的连接。

这就是为什么多台内网设备可以共享一个公网 IPv4 地址访问外部服务。

上面的端口 40001 只是用于说明的示例值,不是所有路由器固定使用的端口,也不是运行测试的结果。

3.2 NAT 不等于防火墙

NAT 的核心工作是地址或端口转换;防火墙的核心工作是根据安全规则允许或拒绝流量。许多家用路由器把 NAT、状态跟踪和防火墙功能集成在同一设备上,所以使用者容易把它们当成一回事。

但是两者不能完全画等号:

  • 有地址转换,不代表所有流量都一定被安全策略允许;
  • 有防火墙规则,也不代表路由器已经知道应该把外部请求转发给哪台内网主机;
  • NAT 不是完整的安全方案,服务本身仍然需要认证、授权、补丁和访问控制。

四、为什么外部请求通常不能直接进入内网?

当内网电脑主动访问外部服务器时,路由器能够在连接建立过程中创建或维护相应的 NAT 映射。返回流量可以按照映射回到内网设备。

但如果外部用户突然向路由器公网地址的某个端口发送新请求,路由器未必知道应该把请求转发给哪台内网主机。

例如,家中有三台设备:

  • 192.168.1.20:运行 Java Web 服务;
  • 192.168.1.21:运行数据库;
  • 192.168.1.22:运行其他应用。

外部用户访问路由器的 198.51.100.10:18080 时,路由器需要明确知道该请求应该送往哪里。端口映射就是配置这条静态转发规则的一种常见方式。

五、端口映射是什么?如何把外部端口转到内网服务?

端口映射(Port Forwarding)通常指在网关或路由器上设置一条规则:当符合条件的外部流量到达指定公网地址和端口时,将其转发到指定的内网地址和端口。这类规则通常涉及目的地址转换(DNAT)或相应的端口转发实现。

5.1 端口映射规则示例

假设你的 Spring Boot 服务在内网电脑 192.168.1.20 上监听 TCP 8080。你希望外部用户访问路由器的 TCP 18080 端口时,请求能够进入这个服务。

路由器上可以按设备实际界面配置类似规则:

配置项 示例值
规则名称 spring-demo
外部端口 18080
内网目标 IP 192.168.1.20
内网目标端口 8080
协议 TCP
启用状态 开启

外部客户端访问的地址形式是:

text 复制代码
http://<路由器公网IPv4地址>:18080/

尖括号中的内容需要替换为真实的公网 IPv4 地址。不要直接把本文的文档示例地址复制成实际访问地址。

5.2 为什么内网目标 IP 最好固定?

假设端口转发规则指向 192.168.1.20:8080,但电脑重新连接网络后,DHCP 给它分配了 192.168.1.35。路由器仍把流量转发到旧地址,外部访问就可能失败。

常见做法是:

  • 在设备上合理配置固定地址;或
  • 在路由器上为该设备设置 DHCP 地址保留。

对大多数家庭网络来说,DHCP 地址保留通常更方便,也可以减少手工配置地址时发生冲突的风险。

5.3 外部端口与内网端口可以不同吗?

可以。例如:

text 复制代码
公网地址:18080  →  192.168.1.20:8080

外部客户端访问 TCP 18080,路由器把请求转发到内网 TCP 8080。它们是两个不同网络位置上的端口,映射规则负责建立关联。

不过,改变外部端口只是改变访问入口,不是可靠的安全防护措施。不能因为外部端口比较偏,就认为服务不会被扫描或攻击。

六、Java / Spring Boot 服务还需要检查什么?

配置好路由器并不意味着 Java 服务一定能访问。网络请求最终仍需要到达正确的进程。

6.1 确认服务监听的端口

Spring Boot 常见的 HTTP 端口是 8080,也可以在配置文件中指定:

yaml 复制代码
server:
  port: 8080

server.port 配置的是应用 HTTP 服务的端口,不会自动为路由器创建端口映射,也不会自动修改操作系统防火墙规则。

6.2 注意服务绑定的地址

如果服务只绑定在 127.0.0.1,通常只能通过本机回环接口访问,局域网中的其他设备无法直接通过电脑的局域网 IP 访问它。

Spring Boot 可以通过 server.address 配置服务器绑定的网络地址,例如在确认确实需要监听所有 IPv4 网络接口时:

yaml 复制代码
server:
  address: 0.0.0.0
  port: 8080

0.0.0.0 是 IPv4 的通配监听地址,不是让其他用户访问时填写的目标 IP。具体监听行为还与服务器实现、操作系统和网络栈有关。

安全提醒: 监听所有接口不等于应该把服务暴露到公网。开发阶段的接口、调试端点和包含敏感数据的服务,不应在没有认证、访问控制和安全配置的情况下直接开放到互联网。

6.3 主机防火墙也可能拦截请求

即使 Java 进程已经监听 TCP 8080,操作系统防火墙仍可能阻止来自局域网或外部网络的连接。排查时应检查是否存在允许对应协议、端口和来源范围的规则,而不是为了测试就长期关闭整个防火墙。

在 Windows 上,可以查看本机监听状态:

powershell 复制代码
netstat -ano | findstr :8080

这条命令用于辅助判断是否存在占用该端口的监听项。它不能单独证明路由器端口映射正确,也不能证明外部互联网一定能访问。

七、配置了端口映射,外网仍然访问不了:重点检查 CGNAT

这是最容易被忽略的一种情况。

家用路由器的 WAN 地址不一定是真正可从互联网直接访问的公网 IPv4 地址。某些运营商会在用户路由器之外再做一层地址转换,这种技术常称为运营商级 NAT(Carrier-Grade NAT,CGNAT)。

在这种情况下,网络路径可能类似:

text 复制代码
内网电脑
  ↓
家用路由器 NAT
  ↓
运营商 CGNAT
  ↓
互联网

你只能管理自己的家用路由器,无法直接配置运营商设备上的入站映射。于是,即使家用路由器的端口转发规则没有问题,外部请求也可能无法到达它。

7.1 如何初步判断是否存在上游 NAT?

可以先查看路由器管理页面里的 WAN / Internet 地址,再与外部网站显示的出口 IPv4 地址进行比较。

以下情况值得重点关注:

  • 路由器 WAN 地址属于 10.0.0.0/8;
  • WAN 地址属于 172.16.0.0/12;
  • WAN 地址属于 192.168.0.0/16;
  • WAN 地址属于 100.64.0.0/10,这是 RFC 6598 为共享地址空间定义的范围;
  • 路由器 WAN 地址与外部网站观察到的出口 IPv4 地址不同。

这些现象可能说明存在上游 NAT、双重 NAT、VPN 或其他网络路径差异,但不能仅凭其中一个现象就断定一定是 CGNAT。例如,VPN 可能改变外部网站看到的出口地址,家庭网络也可能有自己管理的上级路由器。

7.2 如果确认有 CGNAT,应该怎么办?

常见选择包括:

  1. 向运营商咨询公网 IPv4: 询问是否可以提供可入站访问的公网地址,以及是否存在入站端口限制。
  2. 使用有公网入口的云服务器: 将服务部署到云服务器,并按需配置安全组和主机防火墙。
  3. 使用 VPN 或反向隧道: 让内网设备主动建立到可达节点的连接,再通过受控通道访问服务。
  4. 使用托管平台或反向代理方案: 根据项目需求选择能提供外部访问入口的服务。

这些方案各有成本和安全要求。若只是为了演示项目,通常优先考虑部署到受控的测试服务器,或者使用经过认证与访问控制保护的隧道,而不是把个人电脑上的所有端口开放到公网。

八、家庭路由器端口映射和云服务器端口开放有什么区别?

在云服务器场景中,通常不需要用户自己配置家庭路由器的 NAT 端口映射,但仍然可能有多层访问控制。

场景 需要重点检查的项目
家庭网络内网服务 服务监听、电脑防火墙、路由器端口映射、WAN 是否有可用公网入口
云服务器上的 Java 服务 服务监听、云平台安全组、系统防火墙、应用与反向代理配置
经过负载均衡器的服务 负载均衡监听端口、后端目标、健康检查和访问控制
运营商 CGNAT 后的内网服务 是否能获得公网入口,或改用 VPN、反向隧道等方案

云平台的安全组通常是云网络中的虚拟防火墙规则,而不是端口映射本身。即使安全组允许 TCP 8080,应用没有监听该端口,或者主机防火墙仍然拒绝连接,服务也无法正常访问。

不要把"开放端口"理解成"把服务自动部署到了公网"。地址可达、转发规则、访问控制和应用监听必须同时匹配。

九、常见误区

误区 1:NAT 就是防火墙

不准确。NAT 负责地址或端口转换;防火墙负责按规则过滤流量。家用设备可能集成两者,但概念和作用并不相同。

误区 2:配置端口映射后,所有外网用户都一定能访问

不一定。还需要路由器有可达的公网入口、服务监听正确、防火墙放行,且运营商没有阻止相关入站流量。

误区 3:换一个高位端口就安全了

错误。改变外部端口只能改变访问入口,不能代替身份认证、授权、加密、漏洞修复和访问控制。

误区 4:本机能访问 localhost,就代表局域网能访问

错误。localhost 通常解析到本机回环地址。服务若只监听回环接口,其他设备不能通过电脑的局域网地址访问它。

误区 5:云服务器开放安全组端口,就一定能访问应用

错误。还需要检查操作系统防火墙、服务监听地址和端口、反向代理、健康检查等实际配置。

十、本篇总结

这篇文章的核心结论有五个:

  1. 私有 IPv4 地址可在内部网络重复使用,但不能直接作为全球公网路由地址。
  2. NAT / NAPT 让内网设备能够共享公网 IPv4 地址访问外部网络。
  3. 端口映射为符合条件的外部入站流量指定内网目标,但它不能代替防火墙和应用安全配置。
  4. 如果家用路由器处于 CGNAT 或其他上游 NAT 后面,仅修改本地路由器规则通常无法实现公网入站访问。
  5. Java 服务外网访问失败时,应从服务监听、局域网可达、路由器 WAN 地址、端口转发和防火墙逐层确认。

一句话总结:NAT 解决地址转换,端口映射指定内网目标;要让外网真正访问成功,还必须有可达的公网入口、正确的监听和允许流量通过的安全规则。

我是程序员大海,我们下期不见不散.

参考资料

  1. RFC 1918:Address Allocation for Private Internets ------ 私有 IPv4 地址范围。
  2. RFC 3022:Traditional IP Network Address Translator (Traditional NAT) ------ NAT、NAPT 和地址/端口转换机制。
  3. RFC 6598:IANA-Reserved IPv4 Prefix for Shared Address Space ------ 运营商级 NAT 常用共享地址空间 100.64.0.0/10。
  4. Spring Boot 官方文档:Common Application Properties ------ server.port 和 server.address 配置说明。

本文中的 IP 地址、端口和转发规则均为教学示例,不代表某个真实网络的运行结果。实际路由器界面、运营商策略和云平台配置可能不同,请结合自己的环境验证。

相关推荐
Linux运维技术栈6 小时前
WAF部署在防火墙后面,获取不到真实IP怎么办?
服务器·网络·tcp/ip·安全·防火墙·waf
学到老活到老6 小时前
第 22 集:Filter、Interceptor、AOP 都能拦截,为什么不能互换?
java·后端·spring
sun03226 小时前
【JDK 动态代理】 和 【CGLIB 代理】对比
java·数据库·sql
文丑颜不良啊6 小时前
LeetCode1261~1280题目解析
java·leetcode
郭小李6 小时前
spring 中的 @EnableWebMvc注解和WebMvcConfigurer接口
java·后端·spring
低慢小uav7 小时前
(已解决)Zynq芯片lwip协议栈,使用tcp作为服务器Service,接收大量数据时,长度接收正常,接收对数据校验,校验和异常分析
网络协议·tcp/ip·fpga开发
垆边人似月.7 小时前
RDMA项目踩坑(一):为什么最后一块数据必须使用实际长度?
网络·c/c++·rdma·高性能io·tcp与rdma
YH_Analytics7 小时前
2026 高压 E-House 市场深度分析报告市场格局
网络·数据库
zl_dfq7 小时前
Windows 下 UDP 套接字编程指南
网络·windows·udp