场景: 当服务 A 和服务 B 都部署在同一个内网环境中,服务 A 试图通过服务 B 的公共 IP 地址进行请求。这种情况下,由于 NAT 环回的限制,可能会导致请求无法成功到达服务 B。
原理
NAT 设备通常维护两个个转换表,用于跟踪内网设备与公共 IP 地址之间的映射关系。分别是SNAT和DNAT,
SNAT(源地址转换)
- 作用:
- SNAT 主要处理出站流量,将内部 IP 转换为公共 IP。
- 过程:
- 例如,内部设备
192.168.1.10
向外部请求时,NAT 将源 IP 地址转换为公共 IP 地址203.0.113.1
。因此,当外部服务器看到的请求源是203.0.113.1
。
- 例如,内部设备
- 响应:
- 外部服务器的响应会返回到
203.0.113.1
,NAT 会根据其转换表将响应路由回192.168.1.10
。
- 外部服务器的响应会返回到
DNAT(目的地址转换)
- 作用:
- DNAT 处理入站流量,将公共 IP 转换为内部 IP。
- 过程:
- 当外部服务器向
203.0.113.1
发送响应时,NAT 会将目标 IP 地址从203.0.113.1
转换为内部设备的 IP 地址,比如192.168.1.10
。
- 当外部服务器向
- 结果:
- 响应最终会到达内部设备,而外部服务器只知道请求来自
203.0.113.1
。
- 响应最终会到达内部设备,而外部服务器只知道请求来自
正常的请求流程
假设当前服务A的本地IP为192.168.0.1,公网IP为203.0.113.1,要访问的服务B本地IP为192.168.0.1,公网的IP地址是203.0.223.2,那么会经过一下几个步骤:
(x,y)表示(请求IP,目的IP)
- 服务A发送消息到网关,再到路由器
- 本地路由器将本地IP192.168.0.1转换为公网IP203.0.113.1,并在SNAT中记录 (203.0.113.1,203.0.223.2)
- 消息通过网络中的路由器不断路由,找到目的网络路由器
- 目的路由器通过DNAT表转换目的IP为192.168.0.1 (203.0.113.1,192.168.0.1)
- 服务B接收到请求,并发出响应消息到网关 (192.168.0.1,203.0.113.1)
- 目的路由器转换IP为公网IP203.0.223.2 (203.0.223.2,203.0.113.1)
- 本地路由器接收到消息,并且期待响应IP(203.0.223.2)= 实际响应IP(203.0.223.2)
- 完成请求
环回的请求流程则
假设当前服务A的本地IP为192.168.0.1,公网IP为203.0.113.1,要访问的服务B本地IP为192.168.0.2,公网的IP地址是203.0.113.1,那么会经过一下几个步骤:
- 服务A发送消息到网关,再到路由器
- 本地路由器将本地IP192.168.0.1转换为公网IP203.0.113.1,并在SNAT中记录 (203.0.113.1,203.0.113.1)
- 消息通过网络中的路由器不断路由,回到当前路由器
- 路由器通过DNAT表转换目的IP为192.168.0.2 (203.0.113.1,192.168.0.2)
- 服务B接收到请求,并发出响应消息到网关 (192.168.0.2,203.0.113.1)
- 由于响应的目标地址与路由器的公共 IP 相同,路由器会尝试查找 DNAT 表,查找IP192.168.0.2的映射
- 当路由器不支持环回时,即DNAT表中没有此映射,则会丢弃消息,因为期待响应IP(203.0.113.1)!= 实际响应IP(192.168.0.2)
解决方案
- 使用支持环回的 NAT 路由器:
- 如果路由器支持 NAT 环回,内部设备可以使用公共 IP 地址与自己通信。这种配置允许服务 A 通过公共 IP 地址成功请求服务 B。
- 即在DNAT中,加入映射
- 使用内网地址访问:
- 最简单和最常见的解决方案是直接使用服务 B 的私有 IP 地址进行访问。这样可以避免 NAT 环回的问题,并确保请求在内部网络中正常路由。