设置

设置

我使用ip6tablesnat 将包发送到不同接口 (localhost) 上的 IP,但发送到那里的所有数据包都丢失了。我iptables对 IPv4 有相同的规则,一切正常。

设置

主机是 debian 11 VM,客户端是运行的 docker 容器debian:stable-slim

/etc/docker/daemon.json

{
   "ipv6": true,
   "fixed-cidr-v6": "2d00::/8",
   "ip6tables": true,
   "experimental": true
}

主机具有分别用于 IPv6 和 IPv4 的docker0接口 IP2d00::1172.17.0.2。我分别设置了以下 ip(6)tables 规则以针对 IPv4 和 IPv6 进行 NAT:

ip6tables -t nat -A PREROUTING -d 2d00::1 -p tcp -m tcp --dport 8081 -j DNAT --to-destination [::1]:9999
iptables -t nat -A PREROUTING -d 172.17.0.2 -p tcp -m tcp --dport 8081 -j DNAT --to-destination 127.0.0.1:9999

我还将以下规则附加到我的/etc/sysctl.conf

net.ipv4.ip_forward = 1
net.ipv4.conf.all.route_localnet = 1
net.ipv6.conf.all.use_tempaddr = 0
net.ipv6.conf.all.forwarding = 1

最小的非工作示例

在主机上设置一个 HTTP 服务器,监听[::1]:9999

python3 -m http.server --bind ::1 9999

并尝试从客户端容器连接它:

docker run --rm -it --name client debian:stable-slim /bin/bash
apt update
apt install -y curl
curl http://[2d00::1]:8081

结果是 curl 挂了一段时间并不断尝试建立连接,但我从未得到响应。

我尝试过和观察到的事情

我已经对上述不起作用的示例进行了相同的测试

  • 带 nat 的 IPv4
  • 无需NAT的IPv6
  • IPv6 带有 nat 到与原始目标 IP 位于同一接口上的 IP(即,仅更改端口,或 NAT 到接口的链路本地地址)

和他们全部成功。因此,唯一不起作用的情况是带有 NAT 的 IPv6,其中 NAT 想要路由到不同的接口。

我还向各种 ip(6)tables 链添加了日志输出,我可以看到在成功的情况下,我可以观察到到达表链filter的数据包INPUT以及nat表的PREROUTING链。一旦我尝试将 IPv6 流量 NAT 到不同的接口,我就再也收不到到达表中任何链的数据包了filter

我也曾经tcpdump在主机上跟踪数据包,并观察到在成功的情况下,我在veth*docker 创建的虚拟接口以及docker0接口上都可以看到数据包。当对 IPv6 上的其他接口进行 NAT 时,数据包不再出现在接口上docker0,但我仍然可以在veth*接口上看到它们。

答案1

经过进一步挖掘,我发现问题不是跨接口路由,而是路由到::1,这这是另一个主题的答案根据 RFC 4291 第 2.5.3 节的规定,IPv6 中不允许这样做。

相关内容