![iptables SNAT 不适用于 GRE 数据包](https://linux22.com/image/707230/iptables%20SNAT%20%E4%B8%8D%E9%80%82%E7%94%A8%E4%BA%8E%20GRE%20%E6%95%B0%E6%8D%AE%E5%8C%85.png)
我正在尝试将 SNAT 应用于 PPTP 客户端。TCP/1723 数据包已正确进行 SNAT,但 GRE 数据包未正确进行 SNAT。有人能发现问题所在吗?
我有以下 iptables 配置:
$ sudo iptables -t nat -L POSTROUTING -v -n
Chain POSTROUTING (policy ACCEPT 616 packets, 37030 bytes)
pkts bytes target prot opt in out source destination
0 0 SNAT 47 -- * * $internal_ip 0.0.0.0/0 to:$external_ip
当使用 tcpdump 检查出口接口上的传出流量时,我看到以下内容:
<timestamp> IP $internal_ip > $target_ip: GREv1, call 31607, seq 1, length 36: LCP, Conf-Request (0x01), id 1, length 22
... 与预期不同,$external_ip >
所以显然SNAT
翻译不起作用(从中可以清楚地看出0 pkts 0 bytes
)。
我已经加载了以下模块(其中包括):
nf_nat_proto_gre
nf_conntrack_proto_gre
nf_conntrack_pptp
nf_nat_pptp
以防万一这是相关的,这里有几点说明:
- 路由使用第三方防火墙在上游进行(因此传出的数据包已经在正确的出口接口上)。
- 防火墙实际上在虚拟机中运行(上面的
iptables
列表来自其虚拟机管理程序),并桥接至出口接口。 - TCP/1723 数据包被防火墙 SNAT 处理(但 GRE 数据包没有);我实际上正在尝试使用 IPTables 作为解决防火墙缺陷的变通方法。想必 IPTables 并不关心数据包是如何到达那里的?
- 出口接口/网桥具有不同于
$external_ip
(尽管在同一子网中)的静态 IP
这是运行3.13.0-123-generic
答案1
首先,您的 iptables 命令缺少-t nat
部分。但这应该会产生错误,因为默认情况下,过滤表中不存在 POSTROUTING 表。请确保将其添加到正确的表中。这与这个问题非常相似:Linux 路由器上的 NAT GRE(IP 协议 47)
接下来,确保您指定了正确的 $internal_ip,并且该值与您在 tcpdump 上看到的值相匹配。有时一个简单的拼写错误就会被忽略,并使事情看起来很复杂。
另外,检查您的 iptables 规则中没有任何在 SNAT 规则之前触发的前置规则。Netfilter 只会在那种情况下触发第一个匹配。您注意到 TCP/1723 已进行 NAT,这实际上意味着您在那里有其他规则。
如果这没有帮助,请确保使用iptables -t nat -L -v -n
和类似的东西检查并发布您的详细配置ip rule ls && ip route ls
。使用-v
带有 iptables 的交换机,您实际上可以看到每个规则触发了多少数据包。
您正在虚拟机内部运行。请检查主机节点的 iptables 规则!您的规则可能有效,但主机节点防火墙已将来自虚拟机的打包源 IP 覆盖回内部 IP。似乎您正在其他地方检查数据包,即不直接在您的虚拟机上。