我正在学习 L3 负载均衡器,现在正在研究 keepalived NAT 模式。数据包流应为客户端 ------> L3(lvs DNAT)------> 真实服务器,返回流应与请求流完全相反。但 lvs DNAT 仅更改目标 NAT,意味着仅更改了数据包的目标 IP,即)[源=客户端 ip,目标=真实服务器 ip]。因此,在真实服务器处理请求后,它会将其转发到默认网关而不是 L3 服务器,并且数据包会被丢弃。我不想将 L3 服务器设置为真实服务器的默认网关,相反,我需要一个 IP 表相关的解决方案来将流量从真实服务器转发到 L3 服务器(当涉及到端口 8443 和 8080 时)。
IP 表提供了在通过 PREROUTING 处理数据包之前转发流量的方法,但我想要的是服务器处理请求后将流量转发到 L3。我尝试使用 OUTPUT 链,但仍然没有成功sudo iptables -t nat -A OUTPUT -p tcp --match multiport --sports 8443,8080 -j DNAT --to 172.24.248.201
172.24.248.201
是L3服务器的IP。
提前致谢
答案1
这是一个路由问题。iptables不路由,但路由可能会受到它可以改变的地址的影响,这就是为什么iptables经常被误认为是进行路由。因此iptables不可能这解决方案来解决问题(但有时可以是此类解决方案的一部分)。
此外,任何试图改变回复使用 Netfilter/iptables 的 NAT 的数据包将被忽略:纳特表仅针对流的第一个数据包触发:不针对回复触发:iptables -t nat -A OUTPUT -p tcp --match multiport --sports 8443,8080 -j DNAT --to 172.24.248.201
永远不会匹配。即使可以匹配,这也行不通,因为回复的目的地必须是真实服务器看到的初始查询的来源:实际的远程客户端 IP 地址,而不是 L3 LB。
以下是在真实服务器上正确执行此操作的简单方法:使用策略路由。
在这个具体的问题和答案中,我假设Linux 内核 >= 4.17对于“扩展 fib 规则匹配支持以包括 sport、dport 和 ip proto 匹配”,这避免了复杂的使用iptables标记数据包(但仍然需要策略路由)。
必须确保真实服务器的专用端口不能与真实服务器的动态端口范围重叠(当服务器是客户端时使用,例如用于 DNS 查询或系统升级):
# sysctl net.ipv4.ip_local_port_range
net.ipv4.ip_local_port_range = 32768 60999
确保较低的端口高于真实服务器用于服务的最高端口。这里:32768 > 8443 就足够了。
为打算使用 L3 LB 作为网关的特定流量添加路由表。表 248201 是任意选择的值。我假设真实服务器的接口名为eth0,请调整:
ip route add default via 172.24.248.201 dev eth0 table 248201
添加选择器:每个端口范围一个。它可以是一个单一的宽范围(只要不与动态端口交互,就没关系)或 X 个不同端口的 X 条规则。对于单个范围:
ip rule add iif lo ipproto tcp sport 8000-8443 lookup 248201
其中iif lo
是本地发起的传出流量的特殊语法,并不是真正关于洛界面。
现在,所有预期的返回流量都将使用 L3 LB 作为网关进行路由。如果需要,任何其他流量都将使用通常的默认网关。
我不认为安全防御框架协议如果启用,除非服务器的常用默认网关使用其他接口,否则应该会存在问题。如果这是一个问题,可以设置为松散模式反而。
只有当没有它就行不通时才这样做(即使这样,eth0可能就足够了,而不是全部以下):
sysctl -w net.ipv4.conf.all.rp_filter=2