iptables:使用 fwmark 和路由表进行内部端口转发

iptables:使用 fwmark 和路由表进行内部端口转发

我有 2 台服务器,需要转发到内部端口。

为了解释,我使用具有 2 个接口(内部/外部)的服务器作为服务器 A,将内部服务器作为服务器 B。

在服务器 A 中我使用

iptables -A PREROUTING -t nat -i $extif -p tcp --dport $extif_port -j DNAT --to-destination $dst_ip:$dst_port"
iptables -A FORWARD -t filter -d $dst_ip -j ACCEPT"
iptables -A POSTROUTING -t nat -p tcp -s $dst_ip --sport $dst_port -j SNAT --to-source $extif_ip"

在服务器 BI 中使用 fwmark,并使用 fwmark 和 iproute2 路由到服务器 A:

ip rule  $command  fwmark 1 lookup 1
ip route $command  default via $rt_ip table 1

--

iptables -A PREROUTING -t mangle -p tcp -i $intif ! -s $intif_net --dport $port -j MARK --set-mark 1
iptables -A PREROUTING -t mangle -p tcp -i $intif -s $intif_ip --sport $port -j MARK --set-mark 1
iptables -A POSTROUTING -t mangle -p tcp -o $intif -s $intif_ip --sport $port -j MARK --set-mark 1

在服务器 B 上执行上述三条规则时,连接仅停留在 SYN_RECV 状态,并且在日志中没有在连接中发送 ACK,在某些部分数据包在内部丢失,但我不知道原因。

欢迎任何帮助,祝您有美好的一天。

答案1

我使用 B 服务器中的 CONNMARK 解决了这个问题。

使用伪装后它可以快速工作,但是因为它是一个 Web 服务器,所以我需要原始 IP 地址并且伪装会将源 IP 更改为我的 A 服务器的 $intif_ip,所以我无法使用伪装。

因为我没有使用 iptables 设置防火墙,所以我丢弃了 FOWRARD 链规则,因此在 A 服务器中我只有 DNAT 和 SNAT 规则。

iptables -A PREROUTING -t nat -i $extif -p tcp --dport $extif_port -d $extif_ip -j DNAT --to-destination $dst_ip:$dst_port"
iptables -A POSTROUTING -t nat -s $dst_ip -p tcp --sport $dst_port -j SNAT --to-source $extif_ip:$extif_port"

然后在 B 服务器中我遇到了问题,因为它没有路由数据包,我尝试了 1001 种方法来强制使用服务器 A 的 $intif_ip 作为网关,但最终我找到了它!

理论是将 MARK 应用于数据包并且他的流进入为 fwmark 裁定的网关的 ip,但是它在路由决策中丢失了 mar,所以我开始使用 CONNMARK 来保存这个 fwmark。

当使用 CONNMARK 时,它无论如何都不起作用,直到你记录所有链。由于我读过有关 CONNMARK 的文章,示例恢复了 mangle 的 POSTROUTING 链中的规则,但遍历的第一个链是 mangle 的 OUTPUT。因此,我将 CONNMARK 更改为 mangle 的 OUTPUT 链,并且运行良好。

这是服务器 B 的规则集。

iptables -A PREROUTING -t mangle ! -s $int_net -p tcp -i $int_if --dport $int_port -j MARK --set-mark 1
iptables -A PREROUTING -t mangle -m mark --mark 0x1 -j CONNMARK --save-mark
iptables -A OUTPUT -t mangle -j CONNMARK --restore-mark

以及 iproute2 命令(服务器 B)

ip route flush table 1
ip rule add fwmark 1 lookup 1
ip route add default via $intif_ip_serverA table 1
ip route flush cache

希望这能帮助您解决这个奇怪的问题。祝您有美好的一天。

答案2

我看到一些答案错误地使用了 CONNMARK 目标。在 mangle 链中使用 MARK 目标应该可以正常工作。

相关内容