网络抓包工具wireshark and tcpdump 及其实现基于的libpcap

简介:

最近无意中看到博客园中一篇介绍wireshark的文章,写得不错,它简单清楚介绍了wireshark的使用

简介

wireshark以前叫做Ethereal, 在大学时候的网络课程中就常看到它,它是世界上最流行的网络抓包分析工具(world's most popular network protocol analyzer),它是基于图形界面的,官网有介绍wireshark是1998年的一个项目衍生出来的,它有比较强大的特性,可以用来分析数百种网络协议。wireshark是在GNU General Public Lisence下发布的。

以下是我自己使用wireshark的一个截图, 照着上面的博客中去抓取和查看一次http请求前的tcp三次握手,下面详细显示的那行及其上下行就是我从本机浏览器访问自己博客园博客的时候产生的tcp三次握手,可以看到是先握手成功才传输的http报文

可以看到wireshark提供了一个非常友好和详细的界面,可以看到一个包从链路层ethernet,网络层ip,传输层tcp的包信息。详细的使用参加上面提到的博客

tcpdump其实和wireshark很像,区别只是tcpdump是命令行界面的,wireshark和tcpdump都共同使用 libpcap作为其底层抓包的库,  tcpdump最早是由 Van Jacobson于1987年开发的,后来在1999年http://www.tcpdump.org/创立,这上面有关于tcpdump和pcap详细的文档。

 

tcpdump的输出

tcpdump的输出格式是和协议相关的,在协议栈的同一层会有不同的协议,比如在Transport Layer会有TCP,UDP协议。下图摘自wikipedia

对于tcpdump,-e表示输出link level header,以下是一个例子   tcpdump -i eth2 -e -n 

要以看到用了-e打印出了网卡MAC地址,链路层的协议(ethertype), 网络层的协议(IPv4), 第一个length是表示链路层包的长度。然后打出的是里面的tcp packet的信息,发送端和接收端的ip地址,tcp中的Flags等,可以看到后三个包都是广播的包。最后一个是一个ARP查询的包

用tcpdump来看一下三次握手

用这样的命令形式,sudo tcpdump -i eth2 -n '(tcp[13] & 2 == 2 or tcp[13] & 16 ==16)'  , 注意tcpdump是需要superviser的权限的, 输出很多,从中提了一个三次握手

上面的 -n 表示输出结果全用数字表示而不用域名和端口代表的服务名,而后面那个是传递给tcpdump中的libpcap模块的过滤expression, 关于这个过滤expression的语法,在man pcap-filter中有详细的说明,上面这个表达式的意思是 , tcp[13]是包中的tcp子包的第13个字节的值,字节数是从第0个字节开始的。而这个字节正好是Flags这个字节。 而上面Flags的字段中 S表示SYN,   .(一个点)表示ACK

上图是TCP的结构,从图中可以看出,对于Flags这个字节,2表示只有SYN这一位为1, 16则是只有ACK那一位为1, 而上面的tcp[13] & 2 == 2表示SYN这一位为1, 其他位不管。在tcp协议中,只有建立连接的两个端口发的第一个包才会设置SYN位,表示起始的sequence number。从上面可以看到起始的seq num是一个随机值。

 

libpcap , 以及基于libpcap实现一个简单的抓包程序

安装

libpcap是一个c库,用于网络抓包和过滤,源于tcpdump项目,是从最开始tcpdump中剥离出来的一个库, tcpdump中抓包,过滤,capture file的读写的代码被提取出来成了libpcap。现在也是由tcpdump项目的开发者维护。

从tcpdump的官网上下载下来后,包里面有一个INSTALL.txt文件,也就是三步的内容,./configure;   make;   make install;在这个过程中我安装了flex(一个lexical analyzer generator)和yacc才成功了

写的一个简单程序

pcap实际上是从链路层抓包的,所以可以从中提出取出从链路层开始的包信息,官网里(这里)有详细的基于pcap的编程文档。这个文档中有提到基于libpcap编程的基本步骤, 如何应用过滤条件,如何拿到一个包后回调,以及在回调函数中(下面的call_back)怎样提取包的详细信息,因为是得到这个链路层包的实际内容的(以字串的形式),所以是可以提取出从链路层开始,网络程ip, 传输层如tcp的所有信息的,  基本上不同的基于libpcap的软件也就是这里不同了,怎样提取和展示包的信息。基于这个文档我写了一个简单的程序

复制代码
复制代码
1 #include<stdio.h>
 2 #include<pcap.h>
 3 #include<string>
 4 
 5 using namespace std;
 6 
 7 static const unsigned int ETHER_ADDR_LEN = 6;    
 8 void call_back(u_char * args, const struct pcap_pkthdr * header, const u_char * packet);
 9 string generate_mac_address(char macChars[ETHER_ADDR_LEN]);
10 
11 int main(){
12     pcap_t * handle; // Sesion handle
13     char dev[] = "eth2";  //device to sniff on
14     char errbuf[PCAP_ERRBUF_SIZE]; // error string
15     char filter_exp[] = "";  //filter expression
16     bpf_u_int32 mask;  //The netmask of our sniffing device
17     bpf_u_int32 net;   //The IP of our sniffing device
18 
19     struct bpf_program fp;  //the compiled filter expression
20     
21     //查询device的mask和ip    
22     if (pcap_lookupnet(dev, &net, &mask, errbuf) == -1){
23         fprintf(stderr, "Can't get netmask for device %s\n", dev);
24         net = 0;
25         mask = 0;
26     }
27 
28     //obtaining packet capture descriptor
29     handle = pcap_open_live(dev, BUFSIZ, 1, 1000, errbuf);
30     if(handle == NULL){
31         fprintf(stderr, "Can't open device %s\n", dev);
32         return 2;
33     }
34     
35     // before apply filter exp, compile it 
36     if(pcap_compile(handle, &fp, filter_exp, 0, net) == -1){
37         fprintf(stderr, "can't parse filter %s: %s\n", filter_exp, pcap_geterr(handle));
38         return 2;
39     }    
40     //apply filter to this session
41     if(pcap_setfilter(handle, &fp) == -1){
42         fprintf(stderr, "can't install filter %s: %s\n", filter_exp, pcap_geterr(handle));
43         return 2;
44     }
45 
46     // now the device is prepared to sniff under the filter condition
47     struct pcap_pkthdr header; // packet header struct
48     const u_char * packet;  // actual packet
49     
50     //5表示积累5个包pcap_loop才返回,但每个包都会调一次call_back
51     while(!pcap_loop(handle, 5, call_back, NULL)){
52         printf("-------\n");  //每8行才会输出一次这个
53     }
54     pcap_close(handle);
55 }
56 
57 struct sniff_ethernet {
58         char ether_dhost[ETHER_ADDR_LEN]; /* Destination host address */
59         char ether_shost[ETHER_ADDR_LEN]; /* Source host address */
60         u_short ether_type; /* IP? ARP? RARP? etc */
61 };
62 
63 // call_back function的统一原型
64 void call_back(u_char * args, const struct pcap_pkthdr * header, const u_char * packet){
65     static int count = 0;
66     struct sniff_ethernet * ethernet;  //ethernet header
67     ethernet = (struct sniff_ethernet*)(packet);
68     
69     //把6字节的字符串转换成mac地址的表示形式
70     std::string source_mac_address = generate_mac_address(ethernet->ether_shost);
71     std::string dst_mac_address = generate_mac_address(ethernet->ether_dhost);
72 
73     printf("wy: call_back called %d,  %s->%s,   packet length:%d\n", count++, source_mac_address.c_str(), dst_mac_address.c_str(),  header->len);
74 }
75 
76 //由字节为单位字符串生成mac地址,16进制数的字串
77 string generate_mac_address(char macChars[ETHER_ADDR_LEN]){
78     string macAddr;
79     char temp[2];
80     for(int i = 0; i < ETHER_ADDR_LEN; i++){
81         //把一个字节转化成16进制表示形式
82         sprintf(temp, "%x", macChars[i]);
83         if(i != 0){
84             macAddr.append(":");
85         }
86         macAddr.append(temp, 2);
87     }
88     return macAddr;
89 }
复制代码
复制代码

 

这个程序上面有比较详细的注释,就是把通用的基于libpcap编程的流程走了一遍,最后打印出每个包链路层from和to的MAC地址,以及每个包的长度.

对于call_back的第二个参数 struct pcap_pkthdr, 这是pcap.h中定义的一个结构体,包含了这个包的一些信息,捕获时间,包长度, 可以看到程序中的包长度就是从中提取的,定义如下

1 struct pcap_pkthdr {
2         struct timeval ts; /* time stamp */
3         bpf_u_int32 caplen; /* length of portion present */
4         bpf_u_int32 len; /* length this packet (off wire) */
5     };

 

上面的参数char * packet实际上是整个包在内存在的地址,为了从这当中提取出信息,必须要自己定义相应的数据结构从这个纯字符串中去提, 可以看到我照着文档中去定义了一个 struct  sniff_ethernet,这个是需要自己定义的,pcap.h中是没有的,然后可以看到我如何写了一个函数 generate_mac_address把这个6字节的字符串转换成mac地址标准的表达形式。以下是程序运行输出

比较奇怪的是,我本机网卡 eth2的MAC地址是  bc:30:5b:a4:40:40, 但是程序的输出是 ff:30:5b:ff:40:40

本来想选择就用c来写这个程序,但是写到字串转换那里,对字符串的操作用c确实比较麻烦和难看,所以我还是用的c++, 我想到了陈皓的一篇文章,他感慨c的编译器gcc已经开始用c++来实现了,他列举出了c++比c优雅的地方,就我的感觉是很赞同的。

一个链接错误

很奇怪的是我编译程序遇到了一个错误, g++ -o test_pcap test_pcap.cpp -L/usr/local/lib -lpcap

错误提示是 

/usr/local/lib/libpcap.so: undefined reference to `pcap_parse'
collect2: ld returned 1 exit status

google了一下,发现这个问题很普遍却都没给出一个明确的原因解释,有篇文章提到把libpcap重装也一遍,也就是cd到下载下来的包目录,make clean ; ./configure; make ; make install ;  我这样试了之后竟然好了,没有明白是为什么,网上也没有找到,在这里做一个记录吧

目录
相关文章
|
22天前
|
网络协议 Unix Linux
深入解析:Linux网络配置工具ifconfig与ip命令的全面对比
虽然 `ifconfig`作为一个经典的网络配置工具,简单易用,但其功能已经不能满足现代网络配置的需求。相比之下,`ip`命令不仅功能全面,而且提供了一致且简洁的语法,适用于各种网络配置场景。因此,在实际使用中,推荐逐步过渡到 `ip`命令,以更好地适应现代网络管理需求。
34 11
|
25天前
|
Linux 网络性能优化 网络安全
Linux(openwrt)下iptables+tc工具实现网络流量限速控制(QoS)
通过以上步骤,您可以在Linux(OpenWrt)系统中使用iptables和tc工具实现网络流量限速控制(QoS)。这种方法灵活且功能强大,可以帮助管理员有效管理网络带宽,确保关键业务的网络性能。希望本文能够为您提供有价值的参考。
79 28
|
1月前
|
网络协议 安全 测试技术
Nping工具详解:网络工程师的瑞士军刀
### Nping工具详解:网络工程师的瑞士军刀 Nping是Nmap项目的一部分,支持TCP、UDP、ICMP和ARP等多种协议,用于生成和分析网络数据包。它提供灵活的命令行界面,适用于网络探测、安全测试和故障排除。本文介绍Nping的基础与高级用法,包括发送不同类型的网络请求、自定义TCP标志位、路由跟踪等,并通过实战案例展示其应用。掌握Nping有助于更好地理解和管理网络环境。 (239字符)
83 9
|
1月前
|
数据采集 人工智能 自然语言处理
FireCrawl:开源 AI 网络爬虫工具,自动爬取网站及子页面内容,预处理为结构化数据
FireCrawl 是一款开源的 AI 网络爬虫工具,专为处理动态网页内容、自动爬取网站及子页面而设计,支持多种数据提取和输出格式。
305 19
FireCrawl:开源 AI 网络爬虫工具,自动爬取网站及子页面内容,预处理为结构化数据
|
2月前
|
存储 安全 物联网
浅析Kismet:无线网络监测与分析工具
Kismet是一款开源的无线网络监测和入侵检测系统(IDS),支持Wi-Fi、Bluetooth、ZigBee等协议,具备被动监听、实时数据分析、地理定位等功能。广泛应用于安全审计、网络优化和频谱管理。本文介绍其安装配置、基本操作及高级应用技巧,帮助用户掌握这一强大的无线网络安全工具。
97 9
浅析Kismet:无线网络监测与分析工具
|
3月前
|
安全 网络安全 数据安全/隐私保护
访问控制列表(ACL)是网络安全管理的重要工具,用于定义和管理网络资源的访问权限。
访问控制列表(ACL)是网络安全管理的重要工具,用于定义和管理网络资源的访问权限。ACL 可应用于路由器、防火墙等设备,通过设定规则控制访问。其类型包括标准、扩展、基于时间和基于用户的ACL,广泛用于企业网络和互联网安全中,以增强安全性、实现精细管理和灵活调整。然而,ACL 也存在管理复杂和可能影响性能的局限性。未来,ACL 将趋向智能化和自动化,与其他安全技术结合,提供更全面的安全保障。
200 4
|
3月前
|
安全 Windows
【Azure Cloud Service】在Windows系统中抓取网络包 ( 不需要另外安全抓包工具)
通常,在生产环境中,为了保证系统环境的安全和纯粹,是不建议安装其它软件或排查工具(如果可以安装,也是需要走审批流程)。 本文将介绍一种,不用安装Wireshark / tcpdump 等工具,使用Windows系统自带的 netsh trace 命令来获取网络包的步骤
104 32
|
2月前
|
SQL 安全 网络安全
网络安全与信息安全:知识分享####
【10月更文挑战第21天】 随着数字化时代的快速发展,网络安全和信息安全已成为个人和企业不可忽视的关键问题。本文将探讨网络安全漏洞、加密技术以及安全意识的重要性,并提供一些实用的建议,帮助读者提高自身的网络安全防护能力。 ####
86 17
|
2月前
|
存储 SQL 安全
网络安全与信息安全:关于网络安全漏洞、加密技术、安全意识等方面的知识分享
随着互联网的普及,网络安全问题日益突出。本文将介绍网络安全的重要性,分析常见的网络安全漏洞及其危害,探讨加密技术在保障网络安全中的作用,并强调提高安全意识的必要性。通过本文的学习,读者将了解网络安全的基本概念和应对策略,提升个人和组织的网络安全防护能力。
|
2月前
|
安全 网络安全 数据安全/隐私保护
网络安全与信息安全:关于网络安全漏洞、加密技术、安全意识等方面的知识分享
在数字化时代,网络安全和信息安全已成为我们日常生活中不可或缺的一部分。本文将深入探讨网络安全漏洞、加密技术和安全意识等方面的问题,并提供一些实用的建议和解决方案。我们将通过分析网络攻击的常见形式,揭示网络安全的脆弱性,并介绍如何利用加密技术来保护数据。此外,我们还将强调提高个人和企业的安全意识的重要性,以应对日益复杂的网络威胁。无论你是普通用户还是IT专业人士,这篇文章都将为你提供有价值的见解和指导。

热门文章

最新文章