如何使用带有 C 示例代码的 Libpcap 执行数据包嗅探
【摘要】 本文提供了 libpcap 库的基本概述,它构成了许多网络监控工具(包括 wireshark、tcpdump、snort 等)的数据包嗅探的基础。
像wireshark、tcpdump 等网络工具在数据包嗅探方面相当流行。本文提供了 libpcap 库的基本概述,它构成了许多网络监控工具(包括 wireshark、tcpdump、snort 等)的数据包嗅探的基础。
什么是数据包嗅探及其工作原理?
数据包嗅探是一种可以轻松监控进出计算机的网络数据的技术。数据以数据包的形式在网络上传播,数据包嗅探工具可以轻松捕获这些数据包。大多数数据包嗅探器由网络管理员和开发网络工具的开发人员使用。但是,整体数据包嗅探器对于调试网络相关问题非常方便,任何拥有所需权限的人都可以使用。
数据包嗅探器通过嗅探 eth0 等接口设备来工作。可以通过ifconfig命令获取接口列表。一旦选择了接口,可以有一些选项,通过这些选项可以根据协议、源端口、目标端口等过滤掉数据包。选择过滤选项不是必需的。然后开始数据包捕获。
libpcap 库
Libpcap 是许多流行的网络监控工具用于数据包嗅探的底层库。要了解这个库的使用,需要对 C 编程语言有基本的了解。
这是 libpcap 的工作原理:
- 选择要在其上进行数据包嗅探的网络接口设备。例如 Linux 上的 'eth0' 、 'wlan0' 等。
- 选择设备后,使用该设备初始化 pcap 库。
- 接下来,我们可以为以下情况应用过滤器选项:如果我们只想嗅探 TCP/IP 数据包,或者如果我们想指定仅从特定源或目标端口嗅探数据包等。这个过滤器被编译然后使用一组libpcap 库函数。
- 接下来,pcap 库进入其数据包捕获循环,在该循环中它捕获程序设置的数据包数量。
- 捕获数据包后,将调用回调函数,其中整个数据包可用于打印其详细信息或以任何其他方式使用它
上面提到的四个步骤是通过 libpcap 开始抓包的基本步骤。
一个例子
下面的代码使用 libpcap 函数来实现基本的数据包捕获。捕获数据包后,在回调函数中,每个数据包的长度都会打印在标准输出上。
#include <pcap.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netinet/if_ether.h>
#include <netinet/tcp.h>
#include <netinet/ip.h>
#include <string.h>
void callback(u_char *useless,const struct pcap_pkthdr* pkthdr,const u_char*
packet)
{
static int count = 1;
printf("\nPacket number [%d], length of this packet is: %d\n", count++, pkthdr->len);
}
int main(int argc,char **argv)
{
char *dev;
char errbuf[PCAP_ERRBUF_SIZE];
pcap_t* descr;
struct bpf_program fp; /* to hold compiled program */
bpf_u_int32 pMask; /* subnet mask */
bpf_u_int32 pNet; /* ip address*/
pcap_if_t *alldevs, *d;
char dev_buff[64] = {0};
int i =0;
// Check if sufficient arguments were supplied
if(argc != 3)
{
printf("\nUsage: %s [protocol][number-of-packets]\n",argv[0]);
return 0;
}
// Prepare a list of all the devices
if (pcap_findalldevs(&alldevs, errbuf) == -1)
{
fprintf(stderr,"Error in pcap_findalldevs: %s\n", errbuf);
exit(1);
}
// Print the list to user
// so that a choice can be
// made
printf("\nHere is a list of available devices on your system:\n\n");
for(d=alldevs; d; d=d->next)
{
printf("%d. %s", ++i, d->name);
if (d->description)
printf(" (%s)\n", d->description);
else
printf(" (Sorry, No description available for this device)\n");
}
// Ask user to provide the interface name
printf("\nEnter the interface name on which you want to run the packet sniffer : ");
fgets(dev_buff, sizeof(dev_buff)-1, stdin);
// Clear off the trailing newline that
// fgets sets
dev_buff[strlen(dev_buff)-1] = '';
// Check if something was provided
// by user
if(strlen(dev_buff))
{
dev = dev_buff;
printf("\n ---You opted for device [%s] to capture [%d] packets---\n\n Starting capture...",dev, (atoi)(argv[2]));
}
// If something was not provided
// return error.
if(dev == NULL)
{
printf("\n[%s]\n", errbuf);
return -1;
}
// fetch the network address and network mask
pcap_lookupnet(dev, &pNet, &pMask, errbuf);
// Now, open device for sniffing
descr = pcap_open_live(dev, BUFSIZ, 0,-1, errbuf);
if(descr == NULL)
{
printf("pcap_open_live() failed due to [%s]\n", errbuf);
return -1;
}
// Compile the filter expression
if(pcap_compile(descr, &fp, argv[1], 0, pNet) == -1)
{
printf("\npcap_compile() failed\n");
return -1;
}
// Set the filter compiled above
if(pcap_setfilter(descr, &fp) == -1)
{
printf("\npcap_setfilter() failed\n");
exit(1);
}
// For every packet received, call the callback function
// For now, maximum limit on number of packets is specified
// by user.
pcap_loop(descr,atoi(argv[2]), callback, NULL);
printf("\nDone with packet sniffing!\n");
return 0;
}
在上面的代码中:
- 函数 pcap_findalldevs() 用于获取所有可用接口设备的列表。该列表可以显示给用户,以便可以选择预期的接口来嗅探数据包。请注意,这些存在一个函数 pcap_lookupdev(),它也返回一个接口设备,但这个函数的问题是它返回第一个可用的非环回设备。因此,如果我使用无线网络连接并且连接的接口设备是“wlan0”,但 pcap_lookupdev() 函数首先遇到此接口时仍会返回“eth0”。因此,使用 pcap_findalldevs() 是一个更好的选择,因为它会生成一个可供选择的接口设备列表。
- 函数 pcap_findalldevs() 返回的列表提供给用户,用户的输入来自标准输入。
- 然后函数 pcap_lookupnet() 用于获取 IP 地址和网络掩码。
- 通过函数 pcap_open_live() 初始化 pcap 库并选择接口设备。
- 通过 pcap_compile() 函数,我们可以编译用户设置的协议等任何过滤器。
- 通过 pcap_setfilter(),应用此过滤器。
- 最后,通过函数 pcap_loop(),库在应用了过滤器的选定设备上开始数据包捕获,并且在捕获每个相关数据包后,调用回调函数。
这是上述程序的输出:
$ sudo ./pcap tcp 10
[sudo] password for himanshu:
Here is a list of available devices on your system:
1. eth0 (Sorry, No description available for this device)
2. wlan0 (Sorry, No description available for this device)
3. usbmon1 (USB bus number 1)
4. usbmon2 (USB bus number 2)
5. usbmon3 (USB bus number 3)
6. usbmon4 (USB bus number 4)
7. usbmon5 (USB bus number 5)
8. usbmon6 (USB bus number 6)
9. usbmon7 (USB bus number 7)
10. any (Pseudo-device that captures on all interfaces)
11. lo (Sorry, No description available for this device)
Enter the interface name on which you want to run the packet sniffer : wlan0
---You opted for device [wlan0] to capture [10] packets---
Starting capture...
Packet number [1], length of this packet is: 496
Packet number [2], length of this packet is: 66
Packet number [3], length of this packet is: 357
Packet number [4], length of this packet is: 66
Packet number [5], length of this packet is: 238
Packet number [6], length of this packet is: 66
Packet number [7], length of this packet is: 403
Packet number [8], length of this packet is: 66
Packet number [9], length of this packet is: 121
Packet number [10], length of this packet is: 66
Done with packet sniffing!
如果您不是以 root 身份执行上述程序,则应使用 sudo 运行该程序,因为 libpcap 库所做的操作需要超级用户权限。
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)