首页 > 解决方案 > 使用 tcpdump 检查内部基因包

问题描述

我想在由geneve封装的内部数据包上放置过滤器。

如果我放一个过滤器

tcpdump -vnn udp -i eth0

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

如何过滤geneve内部proto字段设置为udp的数据包?

标签: udptcpdump

解决方案


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

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

注意:我不确定我是否应该删除我原来的答案?现在,我将把它留在下面......


我不熟悉这个Geneve 协议,也没有任何要测试的捕获文件,但是如果您知道包含所需值的字段的偏移量,您应该能够使用切片运算符(即[]),表明内部协议是UDP。

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

"udp[10:2] = 17" 

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

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


推荐阅读