我正在努力解决 iptables 和数据包标记问题。我已经建立了一个有 3 个接口的系统
eno1:192.168.0.100 gre1:10.0.0.2 gre2:10.0.0.6
并且有一个本地守护进程在 eno1 端口 1111 上运行(nc -l -p 1111 -s 192.168.0.100)。来自 gre1 和 gre2 的传入流量应转发到 eno1:1111,响应应返回到相应的 gre 接口。我只找到了一种将流量发送回一个接口的解决方案:
iptables -t nat -A PREROUTING -i gre1 --destination X.X.X.X -p tcp --dport 80 -j DNAT --to 192.168.35.100:1111
ip route add 0.0.0.0/1 via 10.0.0.1 dev gre1 table GRE
iptables -A OUTPUT -o eno1 -t mangle -p tcp --sport 1111 -j MARK --set-mark 1
ip rule add fwmark 1 table GRE
我尝试使用 CONNMARK 在某些线程中使用不同的解决方案,但均未成功。有人知道如何让它在两个接口上都工作吗?
编辑:2023-12-08 澄清我想要实现的目标(以及我目前的解决方案为一条隧道实现的目标)是,包含在 GRE 数据包中的数据包由我的本地守护进程应答,就好像它是请求的服务器一样。举个例子:来自 gre1 的 GRE 数据包中包含的数据包具有目标 ip xxxx 和源 ip yyyy 此数据包被转发到我的本地守护进程,回复数据包具有源 ip xxxx 和目标 ip yyyy 并且此数据包将使用它来自的 gre 隧道。
答案1
为什么要使用 gre 隧道进行 DNAT 和 mangle?
GRE 隧道的作用是穿过防火墙,以便您可以使用标准路由。
您对 10.0.0.6 和 10.0.0.2 使用了哪个子网?
我假设它们是 /30 地址,所以 10.0.0.2 的远程端是 10.0.0.1,而 10.0.0.6 的远程端是 10.0.0.5?
假设 .2 隧道末端的远程子网是 192.168.2.0/24,而 .6 隧道末端的远程子网是 192.168.6.0/24。
然后添加以下路线:
ip route add 192.168.2.0/24 dev gre1
ip route add 192.168.6.0/24 dev gre2
启用转发
sysctl net.ipv4.conf.gre1.forwarding=1
sysctl net.ipv4.conf.gre2.forwarding=1
无需在机器上本地进行任何 na 路由。
如果您想将其限制为仅 1111 端口,那么简单的入站规则就可以起作用。
iptables -I INPUT -i gre+ -j DROP
iptables -I INPUT -i gre+ -p tcp --sport 1111 -j ACCEPT
我使用 -I 来添加规则,将它们添加到规则的顶部,这就是为什么 DROP 排在第一位,而 allow 排在第二位。确保这不会阻止您当前的连接。
如果您希望远程端的其他端点能够到达本地守护程序,则将路由添加到 192.168.0.0/24 以到达具有 gre 接口的服务器。在该服务器的本地网络接口上启用转发。
全部完成,无需 NAT,GRE 隧道的存在消除了对 NAT 的需求。否则,您可以只使用站点的外部 IP 地址,并将端口 1111 转发到本地服务器,然后以这种方式使用 NAT。对于大型公司来说,他们通常需要一个端口来访问众多端点,这就是使用 gre 的地方。
根据额外的信息,问题是你不知道源 IP 或它们来自的子网,并且你需要它返回与它来自的路径相同的路径?在这种情况下,你是否将 nginx 视为代理?如果你想使用 iptables,那么你将需要类似的东西:
iptables -t nat -A PREROUTING -i gre+ -p tcp --dport 80 -j DNAT --to 192.168.35.100:1111 *to change the detination to the endpoint you want.
iptables -t nat -A POSTROUTING -o eno1 -d 192.168.35.100 -p tcp --dport 1111 -j MASQUERADE
让 iptables 在后台发挥其魔力并跟踪会话和数据包的返回路径。
由于我们没有修改PREROUTING表中的源IP地址,因此MASQUERADE将把源替换为服务器IP,并在返回时执行相反的操作。
或者,如果您可以访问 gre 隧道源处的服务器,则可以在那里执行 NAT,因此您知道如果源是 10.0.0.1,它将转到 gre1;如果源是 10.0.0.5,它将转到 gre2,然后遵循规则。简单 SNAT 和路由将处理返回路径。
答案2
您可能能够标记来自 GRE 隧道的数据包以标记其来源。例如:
iptables -t mangle -A PREROUTING -j CONNMARK --restore-mark
iptables -t mangle -A PREROUTING -i gre0 -j MARK --mark 0x1
iptables -t mangle -A PREROUTING -i gre1 -j MARK --mark 0x2
iptables -t mangle -A POSTROUTING -j CONNMARK --save-mark
第一条规则将连接跟踪的标记恢复到 IP 数据包。
第二条和第三条规则对来自gre0
/ 的数据包gre1
使用不同的标记。
第三条规则将数据包标记保存为连接标记。
有了这些规则,与单个流相关的所有数据包都应该有一个标记,表明该流与哪个接口相关联。
答案3
mangle 和 connmark 是解决方案:
iptables -t mangle -A PREROUTING -i gre1 -m conntrack --ctstate NEW -j MARK --set-mark 1
iptables -t mangle -A PREROUTING -m mark --mark 1 -j CONNMARK --save-mark
iptables -t mangle -A OUTPUT -j CONNMARK --restore-mark