使用pcap抓取双vlan流量

Using pcap to capture double vlan traffic

我正在尝试编写一个简单的数据包嗅探器,它只需要处理特定类型的流量。我正在用 C++ 编写代码并在 Centos 7 机器上使用 libpcap。它工作得相当好,但希望通过使用 pcap 库的过滤选项来提高性能,以便只显示我感兴趣的数据包类型进行处理。

我的代码示例:

struct bpf_program filter;
if (pcap_compile(pcap, &filter,
                 "(ip && (tcp || udp)) || (vlan && (ip && (tcp || udp)))",
                 1 /*OPTIMIZE*/, PCAP_NETMASK_UNKNOWN) == PCAP_ERROR) {
  std::cout << "Failed to compile filter: " << pcap_geterr(pcap);
} else {
  // Load filter into packet capture device
  if (pcap_setfilter(pcap, &filter) == PCAP_ERROR) {
    std::cout << "Failed to set filter: " << pcap_geterr(pcap);
  }
}

本质上,我想要包含 TCP 或 UDP 的 IP 数据包,并且还接受相同类型的带有 vlan 标记的数据包。我相信过滤器语法是正确的,但现在需要支持双 vlan 数据包 (802.1ad),并且不确定我应该如何重写过滤器字符串。我没有任何双 vlan 数据包可以测试,所以在我做对之前不能只是试验。有没有人对过滤器字符串应该如何寻找接受双 vlan 数据包(以及单 vlan 和无 vlan)有任何建议?

我还注意到,当我 运行 直播时,pcap_compile 函数失败并出现错误 no VLAN support for data link type 113。奇怪的是,当我将相同的过滤器代码放入 wireshark 时,它并没有抱怨。知道这里的问题是什么吗?

更新 1:

我设法在网上找到了一些双vlan包来测试。使用 wireshark,过滤器 ieee8021ad 工作正常,但在用作 pcap_compile

的参数时会产生语法错误

我找到了允许带有 802.1ad 标记的数据包通过的正确过滤器字符串。这是更新后的代码:

if (pcap_compile(pcap, &filter,
                   "(ip && (tcp || udp)) ||"
                   "(vlan && (ip && (tcp || udp))) ||"
                   "((ether[12:2] == 34984) && (vlan && (ip && (tcp || udp))))"
                   "|| vlan",
                   1 /*OPTIMIZE*/, PCAP_NETMASK_UNKNOWN) == PCAP_ERROR) {
    LOG(ERROR) << "Failed to compile filter: " << pcap_geterr(pcap);
  } else {
    // Load filter into packet capture device
    if (pcap_setfilter(pcap, &filter) == PCAP_ERROR) {
      LOG(ERROR) << "Failed to set filter: " << pcap_geterr(pcap);
    }
  }

基本上,它允许tcp/udp(IP),tcp/udp(IP) in VLAN,tcp/udp(IP) in double VLAN,然后如果有3个或更多级别VLAN,一切都允许进入。据我所知,当你想指定其他选项时,没有允许所有嵌套 VLAN 的通配符选项,所以现在,这就可以了。

问题的第二部分是由于使用 cooked captured('any' 接口),并非所有过滤器都受支持,例如vlan、eth addr 等。我们可以通过在每个接口(自己的线程)上打开和捕获来解决这个问题,这样我们就有了正确的 link 类型,这允许我们有更多的过滤器选项。