我想写一个无线流量的实时分析工具。
有谁知道如何从 C 中的混杂(或嗅探)设备中读取数据?
我知道您需要具有 root 访问权限才能执行此操作。我想知道是否有人知道执行此操作需要哪些功能。普通套接字在这里似乎没有意义。
我想写一个无线流量的实时分析工具。
有谁知道如何从 C 中的混杂(或嗅探)设备中读取数据?
我知道您需要具有 root 访问权限才能执行此操作。我想知道是否有人知道执行此操作需要哪些功能。普通套接字在这里似乎没有意义。
在 Linux 上,您使用 PF_PACKET 套接字从原始设备读取数据,例如在混杂模式下运行的以太网接口:
s = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))
这会将收到的每个数据包的副本发送到您的套接字。不过,您很可能并不真正想要每个数据包。内核可以使用 BPF(伯克利包过滤器)执行第一级过滤。BPF 本质上是一个基于堆栈的虚拟机:它处理一小组指令,例如:
ldh = load halfword (from packet)
jeq = jump if equal
ret = return with exit code
BPF 的退出代码告诉内核是否将数据包复制到套接字。可以使用 setsockopt(s, SOL_SOCKET, SO_ATTACH_FILTER, ) 直接编写相对较小的 BPF 程序。(警告:内核采用 struct sock_fprog,而不是 struct bpf_program,不要混淆它们,否则您的程序将无法在某些平台上运行)。
对于任何相当复杂的东西,你真的想使用 libpcap。BPF 的功能受到限制,特别是每个数据包可以执行的指令数量。libpcap将负责将复杂的过滤器分成两部分,内核执行第一级过滤,而功能更强大的用户空间代码会丢弃它实际上不想看到的数据包。
libpcap 还从您的应用程序代码中抽象出内核接口。Linux 和 BSD 使用类似的 API,但 Solaris 需要 DLPI,而 Windows 使用其他东西。
我曾经不得不收听原始以太网帧并最终为此创建了一个包装器。通过使用设备名称调用函数,例如,eth0
我得到了一个处于混杂模式的套接字。您需要做的是创建一个原始套接字,然后将其置于混杂模式。这是我的做法。
int raw_init (const char *device)
{
struct ifreq ifr;
int raw_socket;
memset (&ifr, 0, sizeof (struct ifreq));
/* Open A Raw Socket */
if ((raw_socket = socket (PF_PACKET, SOCK_RAW, htons (ETH_P_ALL))) < 1)
{
printf ("ERROR: Could not open socket, Got #?\n");
exit (1);
}
/* Set the device to use */
strcpy (ifr.ifr_name, device);
/* Get the current flags that the device might have */
if (ioctl (raw_socket, SIOCGIFFLAGS, &ifr) == -1)
{
perror ("Error: Could not retrive the flags from the device.\n");
exit (1);
}
/* Set the old flags plus the IFF_PROMISC flag */
ifr.ifr_flags |= IFF_PROMISC;
if (ioctl (raw_socket, SIOCSIFFLAGS, &ifr) == -1)
{
perror ("Error: Could not set flag IFF_PROMISC");
exit (1);
}
printf ("Entering promiscuous mode\n");
/* Configure the device */
if (ioctl (raw_socket, SIOCGIFINDEX, &ifr) < 0)
{
perror ("Error: Error getting the device index.\n");
exit (1);
}
return raw_socket;
}
然后,当您拥有套接字时,您可以使用 select 在数据包到达时对其进行处理。
您可以使用tcpdump 和 Wireshark 也使用的 pcap 库(参见http://www.tcpdump.org/pcap.htm )。
你为什么不使用像WireShark这样的东西?
它是开源的,所以如果你不想仅仅使用它,至少你可以从中学到一些东西。
Linux 上的 WireShark 具有捕获 PLCP(物理层汇聚协议)头信息的能力。