网络嗅探器设计(一)

功能

@网络数据包的截取
扫描主机上的网络接口,使用Libcap 库截取数据报文
@主机端口扫描
指定要扫描的主机,以及要扫描的端口范围,构造TCP 数据报文,扫描目标主机端
@返回端口状态,端口服务类型
网络层数据报文分析
@分析数据报文,处理IP,ARP,RARP 数据报文
将IP 数据报文交给下一层再做进一步分析
@传输层数据报文分析
分析TCP,UDP,ICMP,IGMP 数据报文,将分析结果记录在日志文件中。
@查找网关
查找本地地址的网关,返回路由表,网关

模块分解:
程序入口main.c
嗅探程序sniffer.c
处理以太网层数据包ethernet.c
处理tcp 数据包tcp.c
处理udp 数据包udp.c
处理icmp 数据包icmp.c
处理arp 数据包arp.c
处理端口扫描port.c
处理查找网关gateway.c
工具common.c

准备工作:
1>了解libpcap库:

***libpcap的抓包框架:***
pcap_lookupdev():函数用来查找网络设备,返回可被pcap_open_live()函数调用的网络设备名指针。
pcap_lookupnet():函数获得指定网络设备的网络号和掩码。
pcap_open_live():函数用于打开设备,并且返回用于捕获网络数据包的数据包捕获描述字。对于此网络设备的操作都要基于此网络设备描述字。
pcap_compile():函数用于将用户制定的过滤策略编译到过滤程序中
pcap_setfilter():函数用于设置过滤器
pcap_loop():与pcap_next()和pcap_next_ex()两个函数一样用来捕获数据包
pcap_close():函数用于关闭网络设备,释放资源

///////////////////////////////////////
***libpcap使用步骤***

打开网络设备==>设置过滤规则==>捕获数据==>关闭网络设备

2>libpcap细节

@获取网络设备接口:

char *pcap_lookupdev(char * errbuf);
功能:自动获取可用的网络设备名指针
参数:errbuf,存放出错信息字符串
成功返回设备名指针(第一个合适的网络接口的字符串指针),失败则返回NULL,同时,errbuf存放出错信息字符串

////////////////////////////////////////////

@获取网络号(ip地址)和掩码:

int pcap_lookupnet(char* device,bpf_u_int32 *netp,bpf_u_int32 *maskp,char *errbuf);
功能:获取指定网卡的ip地址,子网掩码
device:网络设备名,为第一步获取的网络接口字符串,也可以人为指定,如“eth0”
netp  :存放ip地址的指针,buf_u_int32为32位无符号整型
maskp :存放子网掩码的指针
errbuf:存放出错信息
返回值 :成功返回0,失败返回1

///////////////////////////////////////////

@打开网络接口:

pcap_t *pcap_open_live(const char * device,int snaplen,int promisc,int to_ms,char *errbuf);
功能:打开一个用于捕获数据的网络端口
device:网络接口的名字,为第一步获取的网络接口字符串,也可以人为指定
snaplen:捕获数据包的长度,不能大于65535个字节
promise:”1“代表混杂模式,其他值代表非混杂模式
to_ms  :等待毫秒数,超时间,获得数据包的函数会立即返回,0表示一直等待
errbuf :存储错误信息
返回值:返回pcap_t类型指针,后面的所有操作都要使用这个指针。

///////////////////////////////////////////////

@获取数据包:

**方法一**:
const u_char *pcap_next(pcap_t *p,struct pcap_pkthdr *h);
功能:捕获一个网络数据包,收到一个数据包立即返回
p:pcap_open_live()返回的pcap_t类型的指针        h:数据包头
 struct pcap_pkthdr  
 {  
     struct timeval ts; // 抓到包的时间  
     bpf_u_int32 caplen; // 表示抓到的数据长度  
     bpf_u_int32 len; // 表示数据包的实际长度  
 }
len和caplen的区别:因为在某些情况下不能保证捕获的包是完整的,例如一个包长1480,但是你捕获到1000的时候,可能因为某些原因就终止捕获了,所以caplen是记录实际捕获的包长,也就是1000,而len就是1480
返回值:成功则返回捕获数据包的地址,失败返回NULL

**方法二**
int pcap_loop(pcap_t *p,int cnt,pcap_handler callback,u_char *user);
功能:循环捕获网络数据包,直到遇到错误或者满足退出条件,每次捕获一个数据包就会调用callback指定的回调函数,所以,可以在回调函数中进行数据包的处理操作。

p:pcap_open_live()返回的pcap_t类型的指针
cnt:指定捕获数据包的个数,一旦抓到cnt个数据包,pcap_loop立即返回,如果是-1,就会一直捕获直到出错
callback:回调函数,名字任意,根据需要自行取名
user:向回调函数中传递的参数

callback回调函数的定义:
void callback(u_char *userarg,const struct pcap_pkthdr *pkthdr,const u_char *packet)
userarg:pcap_loop()的最后一个参数,当收到足够数量的包后pcap_loop会调用callback回调函数,同时将pcap_loop()的user参数传递给它
pkthdr:是收到数据包的pcap_pkthdr类型的指针,和pcap_next()第二个参数是一样的
packet:收到的数据包数据
返回值:成功返回0,失败返回负数

**方法三**

int pcap_dispatch(pcap_t *p,int cnt,pcap_handler callback,u_char *user);
这个函数和pcap_loop()非常类似,只是在超过to_ms毫秒后就会返回(to_ms是pcap_open_live()的第四个参数)

////////////////////////////////////////////

***释放网络接口***
void pcap_close(pcap_t *p);
功能:关闭pcap_open_live()打开的网络接口,并释放相关资源
参数:p:需要关闭的网络接口,pcap_open_live()的返回值

/////////////////////////////////////////////

@过滤数据包:

int pcap_setfilter(pcap_t *p,struct bpf_program *fp);
功能:应用BPF过滤规则
p :pcap_open_live()返回的pcap_t类型的指针
fp:pcap_compile()的第二个参数
返回值:成功返回0,失败返回-1

猜你喜欢

转载自blog.csdn.net/m18706819671/article/details/80463906