我对 tun 接口和内核处理 IPv6 有疑问。
我正在尝试通过纯 IPv4 网络向网络的最终用户提供 IPv6。总结一下(只是隧道背景理论)所有 IPv6 数据包都放入 IPv4 数据包中并通过隧道发送,当出去时,此 IPv4 标头将被删除并传递到系统。
我模拟这一切的场景如下:
- 我只有一台机器,有两个 IPv4 虚拟接口,用于在两者之间发送隧道流量。我们称它们为“if4a”和“if4b”。这些接口是管理接口的子接口。
- 该机器还有两个 IPv6 tun 接口,用于屏蔽最终用户的 IPv6 地址。我们称它们为“if6a”和“if6b”。每个 tun 接口都附加了一个手工程序,用于在将数据包写入隧道或从隧道读取数据包之前放置/删除我需要的标头(GTP)(带有 fd00:fea:2001::1 地址的 if4a 和带有 fd00:fea:2002 地址的 if4b: :1 地址)。
- 我有两个未在任何地方定义的 IPv6 地址,实际上是最终用户地址(fd00:cafe:2001::1 代表 if6a 的用户,fd00:cafe:2002::1 代表 if6b 网络的用户)。
- 路由表配置为将最终用户流量发送到“if6a”或“if6b”(tun 接口)。
- 有一个 NAT 配置,它通过“cafe”地址更改“fea”IPv6 地址,以避免数据包直接传递到目标 if6x 接口,并强制 IPv6 流量通过 tun 接口,因此我的 GTP 处理程序。
问题是:
- 我通过 if6a 从 fd00:fea:2001::1 向 fd00:cafe:2002::1 发送 ICMPv6。
- NAT 后路由链通过 fd00:cafe:2001::1 更改源地址
- 监听 if6a 的程序读取 ICMPv6,添加 GTP 标头并将其发送到 if4b(使用 IPv4)
- 封装到 GTP 中的 IPv6 数据包具有以下地址:从 fd00:cafe:2001::1 到 fd00:cafe:2002::1
- 服务器接收数据包,删除 GTP 标头并将其(IPv6 数据包)注入到 if6b 接口上。
- 这是 tshark 嗅探数据包并打印跟踪的地方
- NAT 预路由链通过 fd00:fea:2002::1 更改目标地址并向上访问堆栈 IP。
- 该数据包被丢弃,因为它进入的是 IPv4 堆栈而不是 IPv6 堆栈。
一些痕迹:
- 沙克:
[root@vm062 ~]# tshark -i if6b`
Running as user "root" and group "root". This could be dangerous
Capturing on 'if6b'
1 0.000000 fd00:cafe:2001::1 -> fd00:cafe:2002::1 ICMPv6 104 Echo
(ping) request id=0x7383, seq=1, hop limit=0
1 2 0.785373 fd00:cafe:2001::1 -> fd00:cafe:2002::1 ICMPv6 104
Echo (ping) request id=0x7383, seq=2, hop limit=0
2 3 1.782000 fd00:cafe:2001::1 -> fd00:cafe:2002::1 ICMPv6 104
Echo (ping) request id=0x7383, seq=3, hop limit=0
3 4 2.781968 fd00:cafe:2001::1 -> fd00:cafe:2002::1 ICMPv6 104
Echo (ping) request id=0x7383, seq=4, hop limit=0...
- 丢弃的数据包,如 dropwatch 显示:
[ipv6test@vm062 ssh]$ echo start | dropwatch -l kas
Initalizing kallsyms db
dropwatch> start
Enabling monitoring...
Kernel monitoring activated.
Issue Ctrl-C to stop monitoring
1 drops at ip_rcv+c0 (0xffffffff81536450)
2 drops at ip_rcv+c0 (0xffffffff81536450)
1 drops at ip_rcv+c0 (0xffffffff81536450)
2 drops at ip_rcv+c0 (0xffffffff81536450)
2 drops at ip_rcv+c0 (0xffffffff81536450)
2 drops at ip_rcv+c0 (0xffffffff81536450)
2 drops at ip_rcv+c0 (0xffffffff81536450)
...
如果我停止 ping6,则 ping6 也会停止。
我一直在研究ip_rcv 函数并且仅适用于 IPv4 数据包,因此我认为我的 IPv6 数据包是通过 IPv4 堆栈而不是 IPv6 堆栈进入的。内核为什么要这样做?
有一个类似的问题这里。