使用tcpdump检查内部日内瓦包

问题描述

我想对由geneve封装的内部数据包进行过滤。

如果我放一个类似的过滤器

tcpdump -vnn udp -i eth0

它过滤所有Geneve数据包,因为Geneve上方的标头是udp。

如何过滤将原型字段设置为udp的属内数据包?

解决方法

我设法找到了一个包含Geneve流量的在线示例捕获文件。这是Cloudshark上的geneve.pcap文件。

我下载了此文件并修改了其中一个数据包,因此内部封装的协议是UDP而不是ICMP。然后,我可以提出一个捕获过滤器,以便在使用tcpdump进行测试时隔离该数据包。这是我用来测试的带有捕获过滤器的命令:

tcpdump -r geneve_udp.pcap "(udp port 6081) and (udp[10:2] = 0x6558) and (udp[(8 + (4 * (2 + (udp[8:1] & 0x3f))) + 12):2] = 0x0800) and (udp[8 + (4 * (2 + (udp[8:1] & 0x3f))) + 14 + 9:1] = 17)"

捕获过滤器的说明:

  • udp port 6081:这部分仅过滤UDP端口号标识的Geneve数据包。
  • udp[10:2] = 0x6558:这部分过滤具有协议类型为“透明以太网桥接”的Geneve数据包。
  • udp[(8 + (4 * (2 + (udp[8:1] & 0x3f))) + 12):2] = 0x0800:这个有点复杂的部分用于过滤以太类型为0x0800(IPv4)的封装以太网帧。它通过以下方式做到这一点:
    • 跳过UDP标头本身的8个字节。
    • 跳过Geneve标头,它是8个字节加上Opt Len的4倍,我们必须与该字节隔离,因为此字段仅包含在低6位之内。
    • 跳到封装的以太网头的Ethertype字段。
    • 最后将在那里找到的2字节值与IPv4分配的以太类型0x0800进行比较。
  • udp[8 + (4 * (2 + (udp[8:1] & 0x3f))) + 14 + 9:1] = 17:这个有点复杂的部分用于过滤协议字段为17(UDP)的封装IPv4标头。它通过以下方式做到这一点:
    • 跳过UDP标头本身的8个字节。
    • 跳过Geneve标头,它是8个字节加上Opt Len的4倍,我们必须与该字节隔离,因为此字段仅包含在低6位之内。
    • 跳过封装的以太网报头的14个字节。
    • 跳过封装的IP标头的前9个字节,以获取IPv4协议字段的适当偏移量。
    • 最后,将该字段的值与UDP分配的协议值17进行比较。

如果Geneve协议将UDP封装在IPv6而不是IPv4内,那么您将必须相应地修改捕获过滤器。

注意:我不确定是否应该删除原始答案?现在,我将其保留在下面...


我对Geneve protocol并不熟悉,也没有任何可用于测试的捕获文件,但是您应该能够使用 slice 运算符(即{{1 }}),如果您知道包含期望值的字段的偏移量,则表明内部协议是UDP。

出于说明目的,我假设如果Geneve Header的 Protocol Type 字段包含值17,则表示封装的UDP数据包。假设这是正确的,那么如下所示的过滤器可能会有所帮助:

[]

此过滤器将UDP数据的偏移量10处的2个字节与值17(据我所知)进行比较,该值是Geneve标头的协议类型字段的位置。如果此假设或我对协议的理解不正确,显然您将需要调整偏移量。

有关捕获过滤器语法的更多帮助,请参见pcap-filter手册页。