Print

做了公网端口映射后,内网主机反而访问不了?——NAT 回流(NAT hairpin)原理与解决案例

组网及说明

问题描述

某单位在出口路由器上做了端口映射(虚拟服务器),把公网地址 123.123.123.123 的 TCP 8080 映射到内网服务器 192.168.1.100 的 TCP 80,并用域名 oa.example.com 解析到该公网地址。

  • 外网用户:访问 http://oa.example.com:8080 一切正常;
  • 内网用户:访问同一个网址(即通过公网 IP 访问),页面打不开或一直转圈超时;
  • 内网用户直接访问服务器私网地址 http://192.168.1.100(80 端口)又是正常的。

很多人第一反应是"映射没配好",但外网能访问已经说明映射本身是好的。这是一个非常典型的 NAT 回流(NAT hairpin ) 问题。

过程分析

故障原理:为什么"外网通、内网不通"?

报文交互过程(关键)

内网 PC(192.168.1.50)访问公网地址 123.123.123.123:8080 时:

  1. PC → 路由器:目的地址是公网 IP,不在本网段,PC 把报文交给网关。 报文:源 192.168.1.50 → 目的 123.123.123.123:8080
  2. 路由器做目的地址转换(DNAT):命中端口映射规则,把目的地址和端口改成服务器私网地址后从 LAN 口转发给服务器。 报文:源 192.168.1.50 → 目的 192.168.1.100:80 ⚠️ 注意:此时源地址没有被转换,仍然是 PC 的私网地址。
  3. 服务器回包"抄近路":服务器看到请求来自 192.168.1.50——和自己同一网段,于是回包不发给网关,直接二层送达 PC。 报文:源 192.168.1.100:80 → 目的 192.168.1.50
  4. PC 拒收:PC 发出的 SYN 目的是 123.123.123.123:8080,等来的 SYN+ACK 源地址/端口却是 192.168.1.100:80,四元组对不上,PC 认为这不是自己那条连接的回包,直接丢弃(或回 RST)。

 

三次握手永远建立不起来,表现就是"一直转圈、连接超时"。整个过程形成了一个不对称的"三角形"路径:去程绕网关、回程走直连。

注意:即使 PC 与服务器不在同一网段(中间隔着三层核心交换机),只要服务器回包由核心直接路由回 PC、未经过出口路由器,问题完全相同

 

解决方法

方案一:开启 NAT 回流 / 双向端口映射生效(需出口路由器支持)

原理:在做 DNAT 的同时,把内网访问者的源地址也转换成路由器 LAN 口地址,即再做一次 SNAT。这样服务器看到的请求来自网关 192.168.1.1,回包必然交给网关,由网关沿原路返回,四元组恢复一致。

转换后的报文路径:

 

配置方法(以 Web 管理界面为例):

  1. 进入「网络管理→NAT配置→端口映射」;
  2. 启用NAT hairping功能,设置当前NAT hairping生效接口;

命令行设备(MSR 等 Comware 网关)可在内网接口上同时配置 nat outbound + nat server,即同一接口上既做源转换又做服务器映射,达到相同效果。

若路由器不支持端口回流,可考虑以下方案实现

 

方案二:内网 DNS 分离解析

原理:不让内网流量绕出去再绕回来,而是让内网用户解析域名时直接得到服务器的私网地址。

  1. 在内网 DNS 服务器(或路由器自带的 DNS)上添加静态记录: oa.example.com → 192.168.1.100;
  2. 内网终端 DNS 指向内网 DNS 服务器;
  3. 外网用户仍通过公网 DNS 解析到 123.123.123.123,互不影响。