看似不明显的原因iptables -t nat -A PREROUTING -d 192.168.12.87 -p tcp --dport 80 -j DNAT --to-destination 192.168.12.77
是返回数据包将如何路由。
您可以设置规则,使发送到192.168.12.87的数据包被简单地NAT到192.168.12.77,但是192.168.12.77然后会将回复直接发送回客户端。这些答复不会通过您的iptables规则进行NAT的主机,因此,一个方向的数据包将被转换,而另一个方向的数据包则不会。
有三种方法可以解决此问题。
- 在第一台主机上,不仅要进行DNAT,还要进行SNAT,这样返回流量将通过第一台主机发回。该规则可能看起来像
iptables -t NAT -A POSTROUTING -d 192.168.12.77 -p tcp --dport 80 -j SNAT --to-source 192.168.12.87
- 从DSR负载平衡和DNAT数据包中获取灵感,这些数据包是在以太网层而不是IP层。通过将数据包的目标MAC替换为192.168.12.77的MAC,并在以太网上发送而不接触IP层,则192.168.12.77可以在虚拟接口上配置192.168.12.87,从而能够终止TCP连接客户端知道的服务器IP。
- 在第一台主机上使用幼稚(但不起作用)的解决方案。然后通过对返回流量进行SNAT处理第二个主机上的返回数据包。规则看起来像
iptables -t nat -A OUTPUT -p tcp --sport 80 -j SNAT --to-source 192.168.12.87
这三个解决方案中的每一个都有缺点,因此,如果确实需要执行此特定转发,则需要仔细考虑。
- 使用SNAT将丢失客户端IP,因此2号主机将认为所有连接都来自192.168.12.87。此外,您将使用主机号1的带宽用于所有答复数据包,这将与其他方法相比采用更直接的路由。
- DSR方法将破坏两个节点之间的所有其他通信。DSR方法实际上仅在服务器地址不是任何主机的主IP时才适用。每个主机都需要有一个主IP,而不是DSR IP。
- 在一个主机上使用连接跟踪在一个方向上进行转换,而在另一主机上使用连接跟踪在另一个方向上进行转换,这很丑陋,并且有多种方式可以破坏它。例如,如果任一主机上的端口号都被NAT修改,则无法重建端口号。同样不明确的是,如果连接跟踪看到的第一个数据包是SYN-ACK而不是ACK,则它将正确运行。
我认为这三种方法中的第一种是最可能有效的一种。因此,如果您不需要知道客户端IP地址,那就是我推荐的地址。
您也可以选择完全忽略NAT,而不尝试解决MAC或IP层上的问题。您可以一直进行到HTTP层并在那里寻找解决方案。在这种情况下,您将找到一个HTTP代理解决方案。如果您在192.168.12.87上安装HTTP代理并进行了适当配置,则可以让它将请求转发到192.168.12.77并转发回答案。另外,它可以插入保留原始客户端IP的X-Forwarded-For标头。然后,需要将192.168.12.77上的服务器配置为信任来自192.168.12.87的X-Forwarded-For标头。