我正在使用 UDP over ipv6 作为通信堆栈。
我在辅助虚拟接口 tap0 上运行网络客户端。它为应该在相同接口但不同链路范围 ipv6 地址上运行的服务器生成消息。我可以在 wireshark 上看到客户端生成的正确消息。
目前我还没有准备好服务器代码,但我正在使用 netcat 代替服务器来测试接收消息,我已完成如下操作:
nc -l -6 -vvv -u fe80::d4b2:dcff:fe59:6d2%tap0 61616
fe80::d4b2:dcff:fe59:6d2 是服务器端链路范围 ipv6 地址。tap0 上的 Wireshark 跟踪清楚地显示生成的数据包是针对上述 ipv6 地址和端口的,但 netcat 无法接收任何数据包。ifconfig
显示我已将上述 IP 分配给 tap0。此外,如果我执行以下命令,我就能够在 netcat(服务器)上接收数据包。
nc -6 -vvv -u fe80::d4b2:dcff:fe59:6d2%tap0 61616 < raw_message_file
奇怪的是,上面的 netcat “raw_message_file” 的发送没有被运行在 tap0 上的 wireshark 捕获。下面的 ping 也没有被 wireshark 捕获。
ping6 -I tap0 fe80::d4b2:dcff:fe59:6d2
即使明确指定了 netcat 和 ping 的接口,数据包也不会在该接口上接收/发送,这怎么可能呢?
PS1:虚拟接口 tap0 由客户端代码打开。一段时间后,它会将消息发送到服务器,服务器应该使用不同但固定的 IPv6 监听该接口。PS2
:我觉得我的描述有点令人困惑;如果您有任何问题,请提问?
编辑:localhost 上的 tcpdump 显示 netcat 和 ping 正在通过 localhost 接口。我的问题是,为什么?
答案1
看起来您可能对 IPv6 的工作方式有点困惑。
首先我们来澄清几件事:你没有运行客户端或服务器”在“网络接口,当你谈论 tun 或 tap 设备时,这尤其令人困惑,因为它们违反了我们的一些惯例。此外,你不会”打开“一个 tap 设备(除非你正在编写一个 tun/tap 助手,但这里似乎不是这种情况),相反,你绑定地址到插座操作系统随后将确定如何将传出的数据包路由到网络接口,以及如何将传入的数据包从网络接口传送到本地进程。请记住,这是操作系统在执行的操作,而不是您的程序。
当您的进程将套接字绑定到链路本地 IPv6 地址时,它只是告诉操作系统数据包将从哪个地址发送,以及来自网络的数据包将被捕获并中继到您的进程。...%tap0
链路本地地址的后缀是地址的一部分,它只是对操作系统的一个提示,因为所有链路本地地址在所有网络上共享一个全局地址空间,这并不意味着该进程以任何方式绑定或锁定到该特定设备。
如果您要向自己的计算机发送数据包,那么它肯定不会通过 tap 接口。也许这就是您的答案:唯一应该通过 tap 接口的数据包是那些发往隧道另一侧的数据包,将发往自己计算机的数据包发送到那里是没有意义的。这些数据包是通过接口传送的lo
。将 wireshark 连接到接口lo
,您应该会看到丢失的数据包。
当您将地址分配给接口时,操作系统知道该地址现在属于您的计算机,并且发送到该地址的任何内容(包括本地进程本身发送的任何内容)都应路由到此计算机。从物理或逻辑接口发出的任何内容,例如eth0
或tap0
实际上正在从您的计算机发送出去的内容,如果某些内容必须留在系统中,则必须在接口上掉头,lo
以便数据包返回堆栈底部并到达接收进程。
操作系统在哪里跟踪这些信息?在路由表中。试试这个:
ip -6 route list table all root fe80::/10
您应该会看到一条或多条通往 fe80::/64 的路由,其中一条路由对应于系统中每个启用 IPv6 的物理或逻辑网络接口,另外还有一些本地链路本地地址对应于每个分配的 IPv6 地址。您会注意到本地地址设置为使用dev lo
,这就是操作系统知道不会发送任何发往这些地址的内容的方式。