【网络】使用 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 不是"可选",而是"必需"的,以保证流量路径的对称性和连接的完整性。

相关推荐
IMPYLH21 小时前
Linux 的 numfmt 命令
linux·运维·服务器·bash
领尚21 小时前
openclaw 极简安装(Ubuntu 24.04 server)
linux·运维·ubuntu
Gofarlic_OMS1 天前
Windchill的license合规使用报告自动化生成与审计追踪系统
大数据·运维·人工智能·云原生·自动化·云计算
SPC的存折1 天前
3、主从复制实现同步数据过滤
linux·运维·服务器
SPC的存折1 天前
openEuler 24.03 MariaDB Galera 集群部署指南(cz)
linux·运维·服务器·数据库·mysql
xcbrand1 天前
文旅行业品牌策划公司找哪家
大数据·运维·人工智能·python
芯智工坊1 天前
第19章 Mosquitto完整项目实战
网络·人工智能·mqtt·开源
SPC的存折1 天前
MySQL 8.0 分库分表
linux·运维·服务器·数据库·mysql
cyber_两只龙宝1 天前
【Oracle】Oracle之DQL中WHERE限制条件查询
linux·运维·数据库·云原生·oracle
斌味代码1 天前
Shell 性能监控:指标采集、告警规则与可视化大盘设计
运维