【网络】使用 DNAT 进行负载均衡时,若未配置配套的 SNAT,回包失败

【网络】iptables 1 概念
【网络】iptables 2 查看规则
【网络】使用 DNAT 进行负载均衡时,若未配置配套的 SNAT,回包失败
【网络】回包路由原理

使用 DNAT 进行负载均衡时,若未配置配套的 SNAT,后端服务器将直接回包给客户端,导致客户端因收到源 IP 不匹配的响应而丢弃数据包,最终连接失败。

场景设定

  • 客户端 (Client): IP_C

  • 负载均衡器 (Load Balancer): IP_VIP (虚拟服务 IP), IP_LB (LB 的内部接口 IP)

  • 后端真实服务器 (Real Server): IP_RS1, IP_RS2

  • 网络拓扑:

    • 客户端 IP_C 可以访问 IP_VIP

    • 负载均衡器 IP_LB 可以访问后端服务器 IP_RS1/RS2

    • 后端服务器 IP_RS1/RS2 知道如何到达 IP_C(例如,IP_CIP_RS 在同一个二层网络,或者 IP_RS 的默认网关指向了能到达 IP_C 的路由器)。


流量路径分析

1. 请求 (Request) 路径:IP_C -> IP_VIP
  1. 客户端发送: IP_C 发送一个请求包到 IP_VIP

  2. 到达负载均衡器: 包到达负载均衡器。此时包的源/目的为:src=IP_C, dst=IP_VIP

  3. iptables DNAT 执行:

    • 负载均衡器上的 iptables 规则(通常在 PREROUTING 链的 nat 表)匹配到该包。

    • 执行 DNAT,将目的 IP 从 IP_VIP 修改为某个后端服务器的 IP,例如 IP_RS1

    • 关键: 源 IP (IP_C) 保持不变。

    • 包变为:src=IP_C, dst=IP_RS1

  4. 负载均衡器转发: 负载均衡器根据路由表,将修改后的包转发给 IP_RS1

2. 响应 (Response) 路径:IP_RS1 -> IP_C (问题发生!)
  1. 后端服务器处理: IP_RS1 收到一个来自 IP_C 的请求包(src=IP_C, dst=IP_RS1)。它认为这是一个直接的、正常的连接。

  2. 后端服务器直接回包:

    • IP_RS1 准备响应包。

    • 它查询自己的路由表,发现有到达 IP_C 的路由(直连或通过网关)。

    • 因此,它直接将响应包发送给 IP_C

    • 响应包的源/目的为:src=IP_RS1, dst=IP_C

  3. 响应包绕过负载均衡器: 这个响应包直接从 IP_RS1 发往 IP_C,完全绕过了负载均衡器。


产生的问题

  1. 客户端收到"错误"的响应:

    • 客户端 IP_C 发起的是到 IP_VIP 的连接。

    • 它期望收到的响应包的源 IP 是 IP_VIP

    • 但它实际收到的响应包的源 IP 是 IP_RS1

    • 客户端的 TCP/IP 协议栈会认为这是一个不属于任何已知连接的、无效的包(因为五元组 src=IP_RS1, dst=IP_C 与它发起的 src=IP_C, dst=IP_VIP 不匹配)。

    • 结果: 客户端通常会丢弃这个包,并可能发送一个 RST (复位) 包给 IP_RS1,导致连接中断。

  2. 连接状态不完整:

    • 负载均衡器只看到了请求包(并执行了 DNAT),但从未看到响应包。

    • 它无法维护一个完整的连接状态(conntrack)。如果后续有同一个连接的包到达,负载均衡器可能会再次进行 DNAT 决策,导致行为不一致。

  3. 非对称路由 (Asymmetric Routing):

    • 请求路径: IP_C -> LB -> IP_RS1

    • 响应路径: IP_RS1 -> IP_C (绕过 LB)

    • 这种进出路径不一致的情况就是非对称路由,在安全设备、状态防火墙等场景下会引发问题。


为什么需要 SNAT/MASQUERADE?

为了解决上述问题,必须确保响应包也经过负载均衡器。这就是 SNAT 或 MASQUERADE 的作用。

  • 在 DNAT 的同时配置 SNAT:

    • 当负载均衡器执行 DNAT (dst=IP_VIP -> dst=IP_RS1) 时,同时执行 SNAT,将源 IP 从 IP_C 修改为负载均衡器自己的 IP (IP_LB)。

    • 发送给后端服务器的包变为:src=IP_LB, dst=IP_RS1

  • 后端服务器回包:

    • IP_RS1 收到 src=IP_LB, dst=IP_RS1 的包。

    • 它认为连接是 IP_LB 发起的,所以会回复 IP_LBsrc=IP_RS1, dst=IP_LB

    • 这个包必须经过负载均衡器(因为 IP_LB 是它的直接邻居或默认网关)。

  • 负载均衡器处理回包:

    • 负载均衡器收到 src=IP_RS1, dst=IP_LB 的包。

    • 它查询连接跟踪表 (conntrack),找到原始连接记录(orig=IP_C->IP_VIP, reply=IP_RS1->IP_LB)。

    • 执行逆向转换:

      • 将目的 IP 从 IP_LB 改回 IP_C (逆向 SNAT)。

      • 将源 IP 从 IP_RS1 改回 IP_VIP (逆向 DNAT)。

    • 最终发给客户端的包为:src=IP_VIP, dst=IP_C,客户端完全满意。


总结

iptables DNAT 负载均衡中,如果不配置 SNAT/MASQUERADE:

  1. 后端服务器会直接回包给客户端,绕过负载均衡器。

  2. 客户端收到源 IP 错误的响应包(是 IP_RS 而不是 IP_VIP)。

  3. 客户端丢弃响应包,导致连接失败。

因此,在标准的 DNAT 负载均衡场景中,SNAT/MASQUERADE 不是"可选",而是"必需"的,以保证流量路径的对称性和连接的完整性。

相关推荐
寻星探路5 小时前
【深度长文】万字攻克网络原理:从 HTTP 报文解构到 HTTPS 终极加密逻辑
java·开发语言·网络·python·http·ai·https
七夜zippoe8 小时前
CANN Runtime任务描述序列化与持久化源码深度解码
大数据·运维·服务器·cann
盟接之桥8 小时前
盟接之桥说制造:引流品 × 利润品,全球电商平台高效产品组合策略(供讨论)
大数据·linux·服务器·网络·人工智能·制造
会员源码网8 小时前
理财源码开发:单语言深耕还是多语言融合?看完这篇不踩坑
网络·个人开发
米羊1219 小时前
已有安全措施确认(上)
大数据·网络
Fcy6489 小时前
Linux下 进程(一)(冯诺依曼体系、操作系统、进程基本概念与基本操作)
linux·运维·服务器·进程
袁袁袁袁满9 小时前
Linux怎么查看最新下载的文件
linux·运维·服务器
代码游侠10 小时前
学习笔记——设备树基础
linux·运维·开发语言·单片机·算法
主机哥哥10 小时前
阿里云OpenClaw部署全攻略,五种方案助你快速部署!
服务器·阿里云·负载均衡
Harvey90310 小时前
通过 Helm 部署 Nginx 应用的完整标准化步骤
linux·运维·nginx·k8s