为啥 Linux TAP 设备不处理 ARP 或 ICMPv6 数据包

Posted

技术标签:

【中文标题】为啥 Linux TAP 设备不处理 ARP 或 ICMPv6 数据包【英文标题】:Why aren't ARP or ICMPv6 packets processed by a Linux TAP device为什么 Linux TAP 设备不处理 ARP 或 ICMPv6 数据包 【发布时间】:2011-12-27 00:45:40 【问题描述】:

我正在使用打开一个 TAP 设备

p->fd = open("/dev/net/tun", O_RDWR);

// skipping error handling code

ifr.ifr_flags = IFF_TAP | IFF_ONE_QUEUE | IFF_NO_PI;
strncpy(ifr.ifr_name, p->name, IFNAMSIZ-1);
result = ioctl(p->fd, TUNSETIFF, &ifr);

// skipping error handling and setting ipv4 address & netmask code

ifr.ifr_flags = (IFF_UP | IFF_RUNNING);
result = ioctl(dummySock, SIOCSIFFLAGS, &ifr);

我面临的问题是,当应用程序(例如 mozilla)想要通过 tap 设备发送数据包时,它需要获取 dst mac 地址。所以内核发出一个ARP请求。我正在编写的应用程序转发 arp 请求(通过物理 eth 设备上的原始套接字)并获得 arp 回复。这个 arp 回复被转发回 tap 设备,但内核拒绝接受。如果我手动添加一个arp条目,则不会生成arp请求并且有两种方式的ip数据包交换(mozilla很高兴)。

Wireshark 能够接收数据包并且没有发现错误。 ICMPv6 数据包(邻居请求和广告)也是如此。在设备上侦听的任何应用程序都会完整地获取数据包。但是内核不会为 ARP/ICMP 处理它。

我的问题是,为什么内核不接受 arp 回复/ICMPv6 msgs?我们需要调用一些 ioctl 调用吗?

编辑:

这是在 tap 设备“ethgress”捕获的数据包的详细信息(tshark 输出)

  9  16.548328    fc00:1::2 -> ff02::1:ff00:1 ICMPv6 86 Neighbor Solicitation
 10  17.243247  fc00:1::100 -> fc00:1::2    ICMPv6 86 Neighbor Advertisement
 11  17.548652    fc00:1::2 -> ff02::1:ff00:1 ICMPv6 86 Neighbor Solicitation
 12  17.668736  fc00:1::100 -> fc00:1::2    ICMPv6 86 Neighbor Advertisement

这是“ethgress”的 ifconfig 输出

ethgress  Link encap:Ethernet  HWaddr 00:01:02:03:04:05
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:83 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:10000
          RX bytes:0 (0.0 b)  TX bytes:7062 (6.8 KiB)

可以看出,内核拒绝接受收到的 ICMPv6 数据包。但是 tx 数据包是递增的。

tap 设备“ethgress”配置了 IPv6 地址 fc00:1::2,应用程序想要与 fc00:1::1 通信。 fc00:1::1 与 fc00:1:100 位于同一接口,后者使用正确的 MAC 地址响应邻居广告(该数据包中的目标 IP 是 fc00:1::1)。 Tcpdump 能够捕获它,而 wireshark/tshark 能够在没有它的情况下对其进行解码,并说它是一个格式正确的数据包。但内核不会增加 Rx 计数器,也不会更新其 arp 缓存。 ARP 数据包也是如此。

编辑 2:

网络看起来像这样。有两个外部盒子被配置为冗余。其中只有一个会处于活动状态。它们每个都通过一个物理网卡连接到一台电脑。我正在编写的应用程序在这台电脑上运行,并在每个 NIC 上打开一个原始套接字。它还会打开一个 TAP 设备。 NIC 未配置 IP 地址。 TAP 设备配置了 IPv4 和 IPv6 地址。一个标准应用程序,比如 mozilla,通过 tap 设备打开一个套接字并希望连接到活动框。为此,内核会在 Tap 设备上生成 ARP 请求/邻居请求消息。应用程序读取此消息并将其转发到两个 NIC。活动框使用 ARP 回复响应 ARP 请求,应用程序读取该回复并将其写入 TAP 设备。 tcpdump 会捕获此 arp 回复数据包,但内核不会更新其 arp 缓存。网卡和TAP设备的mac地址相同。

要求的其他参数。

cat /proc/sys/net/ipv4/conf/all/log_martians
0
cat /proc/sys/net/ipv4/conf/all/rp_filter
1
cat /proc/sys/net/ipv4/conf/all/arp_filter
0

【问题讨论】:

如果您发布了相关的 Wireshark 捕获,将会有所帮助。 如果 ARP 请求是通过 物理 设备发送的,那么回复应该如何到达 TAP 设备?对我来说,这听起来更像是一个高级别的网络配置问题...... 我已经在 Tap 设备上用 tshark 输出更新了这个问题。我正在编写的应用程序在两个 eth 接口与分接头设备之间进行多路复用。 Tap设备上的应用程序自动生成一个arp请求,我将它转发到两个eth接口,但只有一个会回复(不知道哪个)。应用程序根据 arp 回复维护哪个是活动的 eth 接口。它不会修改任何数据包,并在 tap 设备和活动 eth 接口(基于 arp 回复)之间透明地转发数据包。 @Damien_The_Unbeliever 已修复。 log_martiansrp_filterarp_filter 的设置是什么?您的网络是什么样的? 【参考方案1】:

这个问题现在很老了。

(你也有TUN和TAP设备的区别https://security.stackexchange.com/questions/46442/open***-tap-vs-tun-mode)

如果您的设备确实是包含 ARP、硬件寻址等的 TAP 设备: 您的流量转储不包括以太网帧。这些 ARP 和 ICMPv6 数据包的两个重要细节是硬件 dst 和 src 地址。 RP 过滤器是其中的一部分,但可能不允许所有可能的组合通过。

对于 TUN 设备:应该不需要 ARP 等,该设备是“盲”IP 设备

【讨论】:

以上是关于为啥 Linux TAP 设备不处理 ARP 或 ICMPv6 数据包的主要内容,如果未能解决你的问题,请参考以下文章

如何判断交换机是不是受到ARP攻击以及处理方式

LVS负载均衡中arp_ignore和arp_annonuce参数配置的含义

[Linux用户空间编程-4]:Linux虚拟网络设备TUN/TAP的工作原理与代码示例

arp 和icmp

硬货 | 利用 Linux tap/tun 虚拟设备写一个 ICMP echo 程序

TUN/TAP设备浅析(一) -- 原理浅析