![当应用于本地目的地流量时,DNAT 和 REDIRECT 是否等效?](https://linux22.com/image/587782/%E5%BD%93%E5%BA%94%E7%94%A8%E4%BA%8E%E6%9C%AC%E5%9C%B0%E7%9B%AE%E7%9A%84%E5%9C%B0%E6%B5%81%E9%87%8F%E6%97%B6%EF%BC%8CDNAT%20%E5%92%8C%20REDIRECT%20%E6%98%AF%E5%90%A6%E7%AD%89%E6%95%88%EF%BC%9F.png)
在设置我们的 OpenStack 环境时,我遇到了一个问题,即阻止实例联系主机上运行的服务器。元数据服务(公开 HTTP API)在主机上的端口 8775 上运行,OpenStack 网络代码添加了以下 DNAT 规则以通过端口 80 上的特殊地址授予访问权限:
-A PREROUTING -d 169.254.169.254/32
-p tcp -m tcp --dport 80 -j DNAT --to-destination 127.0.0.1:8775
实例通过本地桥接设备连接到主机,并169.254.169.254
分配给lo
。
虽然此规则成功匹配了尝试访问的客户实例的数据包http://169.254.168.254/
,但它们从未到达监听服务。
用基本等效的 REDIRECT 替换此 DNAT 规则可使一切正常工作:
-A PREROUTING -d 169.254.169.254/32
-p tcp -m tcp --dport 80 -j REDIRECT --to-ports 8775
我试图理解为什么 REDIRECT 有效而 DNAT 失败。从 iptables 文档中无法明确该DNAT
规则是否适用于本地目的地流量。我希望这里有人可以提供权威的答案,最好有文档支持,或者可以指出我的配置中可能存在哪些问题,导致 DNAT 规则无法按预期工作。
答案1
你想做的是明确被内核拒绝。
您不能将数据包从非 127/8 地址发送到 127/8。内核会过滤掉这些数据包并将其丢弃,因为它认为它们是“火星人”。
这可能是因为rp_filter
默认为开启。禁用它可能会改变此行为(尽管这会禁用一些可能至关重要的安全保护)。
使用 REDIRECT 不会更改 IP,这就是它有效的原因。换句话说,如果您要使用 DNAT,您可以将其发送到任何外部127.0.0.0/8。
答案2
目标 NAT 有一个特殊的情况,称为重定向:它是一种简单的便利,完全相当于对传入接口的地址执行 DNAT。
它稍微智能一点,因为它选择 DNAT 目标地址作为接收数据包的设备的地址。在您的例子中,它会将数据包 DNAT 到桥接设备上的地址,而不是 127.0.0.1。