初探数据包分析程序设计


转载的一篇对于libpcap很有用的帖子


初探数据包分析程序设计
Author :maigan
From : 第八军团-信息安全小组(www.cnhacking.com www.juntuan.org)
Mail : maigan@maigan.com
Warnong: 转载本文请注明作者及出处


整天在网上转,也看到许多不错的文章,但我发现大多文章要么只停留在理论上,要么就

是太高深。对问题详细分析介绍的很少。今天,我就想以数据包分析程序为主题和大家讨论一

下网络编程的的相关问题,我也是新手,有不到之处,还望大家不吝指正。
通过对数据包的分析,我们可以判断通信双方的操作系统、网络信息流量、经过的路由、

数据包的大小,以及数据包的内容等等。对于喜欢网络安全的人来说,掌握这方面的知识是相

当重要的。现在的网络通信中,大部分数据都没有加密,我们可以轻易地从数据包中提取账号

、密码之类我们关心的数据.大家在看本文时如有困难,可先读一读计算机网络及C程序设计还

有协议分析方面的书。下面我将分TCP/IP族协议结构、程序部分函数及数据结构说明、案例程

序剖析三个部分与大家共同学习数据包分析程序的设计方法

一、TCP/IP族协议结构
在说TCP/IP之前,先让我们来认识一下以太网,因为我们现在接触最多的就是以太网,

并且研究数据包又是离不开以太网的帧的。在以太网中,数据是以被称为帧的数据结构本为单

位进行交换的。以太网中常用的协议是CSMA/CD(carrier sense multiple access with

collision detection)即载波监听多点接入/碰撞检测,在这里,我们关注的是帧的格式。常

用的以太网帧的格式有两种标准,一种是DIX Ethernet V2标准,另一种是IEEE的802.3标准。

现在最常用的MAC帧是V2格式,这也是我们所要研究的格式,至于802.3帧我们不再讨论。以太

网V2帧的格式如下:
(插入8字节)目的地址(6字节)->源地址(6字节)->类型(2字节)->数据(46-1500)->FCS(4字

节)
以太网的地址由48位的二进制来表示,也就是我们常说的MAC地址及硬件地址。在MAC帧前还有8

字节的前同步码和帧的开始定界符,之后才是地址等报头信息。接收端和发送端的地址之后是

2字节的类型字段,存放帧中传送数据的上层协议类型,RFC1700号文档规定了这些,如下:
ETHER TYPES(十六进制) PROTOCOlS
800 IP
806 ARP
8035 Revese ARP
809B Apple Talk
8137/8138 Novel
814c SNMP
帧的数据部分长度为46-1500字节,当小于46时,会在后面加入一个整数字节的填充字段。

FCS(Frame Check Sequence)在以太网常用循环冗佘校检(CRC:cyclic redandancy check)。
IP协议为网络层协议,网络层的数据结构体被称为IP数据报。IP地址及域名这两个概念

我们就不说了,下面我们来看一看IP数据报的结构:
成员名 字节数 说明
version 1/2 IP的版本,现在为IPV4
IHL(报送长度) 1/2 最常用为20,取5-15之前的值,最

大60字节
Type Of Service 1 优先和可靠性服务要求的数值
Total Lenth 2 IP数据报的全长
Identification 2 识别IP数据报的编号
Flags 3/8 1位为0表示有碎块,2位为0表示是

最后的碎块,为1表示接收中。
Fragment Offset 13/8 分片在原分组中的位置
TTL 1 数据报寿命,建议值为32秒
Protocol 1 上层协议
Headerchecksum 2 报头检验码
Source Address 4 发送端IP地址
Destination Address 4 接收端IP地址
Options And Padding 4 选项及填充位
其中协议字段的值对我们分析数据包是很重要的,下面列出来给大家看看:
值 协议 意义
1 ICMP Internet Control Message

Protocol
6 TCP Tranfer Control Protocol
8 EGP Exterior Gateway Protocol
9 IGP Interior Gateway Protocol
17 UDP User Datagram Protocol
下面这些协议的值在后面的程序中我们可以见到,请大家留心记一下。接着我们介绍地址解析

协议(ARP/RARP):
成员名 字节数 说明
Hardware address 2 硬件类型,以太网为1
Protocol address 2 上层协议类型,IP为800
Byte length of each hardware 1 查询物理地址的字节长度,

以太网为6
Byte length of each protocol address 1 查询上层协议的字节长度,

IPv4时为4
Opcode 2 1为ARP请求,2为响应;3为

RARP请求,4为响应
Hardware address of sender of this packet 6 发送端硬件地址
protocol address of sender of this packet 4 发送端IP地址
Hardware address of target of this packet 6 查询对象硬件地址
Protocol address of target of this packet 4 查询对象IP地址
ARP/RARP协议用来查询IP对应的硬件地址或反过来查询IP地址,这在我们分析数据包时也会见

到。下面介绍ICMP协议。我们常用的PING命令就是用的这个协议,这个协议比较简单,由类型

(1字节)、代码(1字节)、检验和(2字节)、还有四个字节的与类型相关的可变部分及数据构成


数据包在运输层还有两个重要的协议,即TCP/UDP,TCP/UDP中使用端口的概念,以区别

计算机上不同的程序。下面我们先来看看TCP数据报的首部构成:
成员名 字节数 说明
Source Port 2 发送端端口号
Destination Port 2 接收端端口号
Sequence NO 4 本报文段所发送的

第一个字节的序号
ACk Number 4 期望收到的下一个

报文段的序号
DAta Offset 1/2 首部的长度
Reserved 3/4 保留今后用
Contol Bits 3/4 控制位
Window 2 滑动窗口的大小
Checksum 2 检验和
Urgent Pointer 2 紧急指针
Options And Padding 4 可选,真充项
Tcp被使用在跨越路由器进行网络服务的网络应用程序中,如WWW、电子邮件、新闻、FTP等。

UDP则是在IP的基础上加入了端口的概念,其结构很简单,只有八个字节首部如下:
源端口(2字节)->目的端口(2字节)->长度(2字节)->检验和(2字节)

二、程序部分函数及数据结构说明
在此部分我们将介绍后面程序中用到的部分函数及数据结构。在程序中我们使用了PCAP

程序库,大家可以从
ftp://ftp.ee.lbl.gov/libpcap.tar.z下载。?..颐侵饕赗edhat Linux下测试程序,这里简单

介绍一下程序库的安装方法,其它环境请大家自行解决。我的目的是给大家编写数据包分析程

序提供思路,至于实用程序的实现这里不做介绍,第三部分给出的程序也不具实用性,为了演

示,程序中实现的功能较多而有些地方又不够详细,编写实用程序时请适当取舍并加入你所需

要的功能实现部分。PCAP程序库的安装方法如下:
1、解压文件
2、进入文件目录执行./configure 及make
3、使用Make命令,设定手册和Include文件(要有Root权限),执行以下命令:
make install -man
make install -incl
4、如出现不存在Include及Include/net目录,则建立此目录并重新执行 make

install -incl
5、检查/usr/include/netinet/目录是否存在Protocols.h文件,不存在则拷贝过去。

至此程序库安装完毕。
下面介绍程序中出现的部分函数及数据结构:
1、PCAP_t *pd;
此型数据结构称为数据包捕捉描述符。
2、Pcap_Open_Live(argv[1],DEFAUT_SNALEN,1,1000,ebuf)
此函数对Pcap程序库进行初始化并返回指向Pcap_t型数据的指针,其参数列表如下


char * 指定网络接口
int 取得数据的最大字节数
int 指定网络接口卡,一般用1
int 读出暂停时间
char * 错误消息用缓冲区
3、Pcap_loop(pd,-1,packet_proce,NUll)
此函数程序的核心,反复执行,利用Pcap取得数据包,返回的是读入数据包的个数

,错误时返回-1,其参数列表如下:
Pcap_t * 指定取得数据包的数据包捕捉描述符
int 取得数据包的个数,-1为无限
返回指向函数的指针 指定数据包处理的函数
U_char * 指向赋给数据包处理函数字符串的指针
4、struct ether_header * eth
此结构体存储以太网报头信息,其成员如下:
ether_dhost[6] 接收端的MAC地址
ether_shost[6] 发送端的MAC地址
ether_type 上层协议的种类
5、fflush(stdout)
此函数完成的是强制输出,参数Stdout,强制进行标准输出。
6、noths(((struct ether_header *P)->ether_type))
此函数将短整型网络字节顺序转换成主机字节顺序。此类函数还有:
ntohl 长整型 功能同上
htons 短整型 将主机字节顺序转换成网络字节顺序
htons 长整型 同上
7、struct IP *iph
ip型结构体在IPh文件中定义,其成员和第一部分讲到的IP数据报结构对应,如下


成员名 类型 说明
ip_hl 4位无符号整数 报头长度
ip_v 同上 版本,现为4
ip_tos 8位无符号整数 Type of service
ip_len 16位无符号整数 数据报长度
ip_id 同上 标识
ip_off 同上 数据块偏移和标志
ip_ttl 8位无符号整数 TTL值
ip_p 同上 上层协议
ip_sum 16位无符号整数 检验和
ip_src in_addr结构体 发送端IP
ip_dst 同上 接收端IP
8、struct ether_arp *arph
ether_arp型结构体成员如下:
成员名 类型 说明
ea_hdr arphdr型结构体 报头中地址以外的部分
arp_sha 8位无符号整数数组 发送端MAC地址
arp_spa 同上 发送端IP地址
arp_tha 同上 目标MAC地址
arp_tpa 同上 目标IP地址
9、struct icmphdr * icmp
icmphdr型结构体中包含共用体根据数据报类型的不同而表现不同性质,这里不再列

出,只列能通用的三个成员
成员名 说明
type 类型字段
code 代码
checksum 检验和

三、案例程序剖析

QUOTE
//example.c
//使用方法:example〈网络接口名〉 > 〈输出文件名〉
//例如:example etho > temp.txe
//结束方法:ctrl+c
//程序开始,读入头文件
#include
#include
#include
#include
#include
#include
#include
#include //pcap程序库
#include //DNS检索使用
#define MAXSTRINGSIZE 256 //字符串长度
#define MAXSIZE 1024 //主机高速缓存中的最大记录条数
#fefine DEFAULT_SNAPLEN 68 /数据包数据的长度
typedef struct
{
unsigned long int ipaddr; //IP地址
char hostname[MAXSTRINGSIZE]; //主机名
}dnstable; //高速缓存数据结构
typedef struct
{
dnstable table[MAXSIZE];
int front;
int rear;
}sequeue;
sequeue *sq; //定义缓存队列
sq->rear=sq->front=0; //初始化队列
//输出MAC地址函数
void print_hwadd(u_char * hwadd)
{
for(int i=0,i<5;++i)
printf("%2x:",hwadd);
printf("%2x",hwadd);
}
//输出IP地址的函数
void print_ipadd(u_char *ipadd)
{
for(int i=0;i<3;++i)
printf("%d.",ipadd);
printf("%d",ipadd);
}
//查询端口函数
void getportname(int portno,char portna[],char* proto)
{
if(getservbyport(htons(portno),proto)!=NULL)
{
strcpy(portna,getservbyport(htons(portno),proto)->s_name);
}
else
sprintf(portna,"%d",portno);
}
//将IP转化为DNS名
void iptohost(unsigned long int ipad,char* hostn)
{
struct hostent * shostname;
int m,n,i;
m=sq->rear;
n=sq->front;
for(i=n%MAXSIZE;i=m%MAXSIZE;i=(++n)%MAXSIZE)
{
//检查IP是否第一次出现
if(sq->table.ipaddr==ipad)
{
strcpy(hostn,sq->table.hostname);
break;
}
}
if(i=m%MAXSIZE)
{//不存在则从域名服务器查询并把结果放入高速缓存
if((sq->rear+1)%MAXSIZE=sq->front) //判队满
sq->front=(sq->front+1)%MAXSIZE; //出队列
sq->table.ipaddr=ipad;
shostname=gethostbyaddr((char*)&ipad,sizeof(ipad),AF_INET);
if(shostname!=NULL)
strcpy(sq->table.hostname,shostname->h_name);
else
strcpy(sq->table.hostname,"");
sq->rear=(sq->rear+1)%MAXSIZE;
}
}
void print_hostname(u_char* ipadd)
{
unsigned long int ipad;
char hostn[MAXSTRINTSIZE];
ipad=*((unsigned long int *)ipadd);
iptohost(ipad,hostn)
if(strlen(hostn)>0)
printf("%s",hostn);
else
print_ipadd(ipadd);
}
//处理数据包的函数
void packet_proce(u_char* packets,const struct pcap_pkthdr * header,const u_char

*pp)
{
struct ether_header * eth; //以太网帧报头指针
struct ether_arp * arth; //ARP报头
struct ip * iph; //IP报头
struct tcphdr * tcph;
struct udphdr * udph;
u_short srcport,dstport; //端口号
char protocol[MAXSTRINGSIZE]; //协议类型名
char srcp[MAXSTRINGSIZE],dstp[MAXSTRINGSIZE]; //端口名
unsigned int ptype; //协议类型变量
u_char * data; //数据包数据指针
u_char tcpudpdata[MAXSTRINGSIZE]; //数据包数据
int i;
eth=(struct ether_header *)pp;
ptype=ntohs(((struct ether_header *)pp)->ether_type);
if((ptype==ETHERTYPE_ARP)||(ptype==ETHERTYPE_RARP))
{
arph=(struct ether_arp *)(pp+sizeof(struct ether_header));
if(ptype==ETHERTYPE_ARP)
printf("arp ");
else
printf("rarp "); //输出协议类型
print_hwadd((u_char *)&(arph->arp_sha));
printf("(");
print_hostname((u_char *)&(arph->arp_spa));
printf(")->");
print_hwadd((u_char *)&(arph->arp_tha));
printf("(");
print_hostname((u_char *)&(arph->arp_tpa));
printf(")tpacketlen:%d",header->len);
}
else if(ptype==ETHERTYPE_IP) //IP数据报
{
iph=(struct ip *)(pp+sizeof(struct ether_header));
if(iph->ip_p==1) //ICMP报文
{
strcpy(protocol,"icmp");
srcport=dstport=0;
}
else if(iph->ip_p==6) //TCP报文
{
strcpy(protocol,"tcp");
tcph=(struct tcphdr *)(pp+sizeof(struct ether_header)

+4*iph->ip_hl);
srcport=ntohs(tcph->source);
dstport=ntohs(tcph->dest);
data=(u_char *)(pp+sizeof(struct ether_header)+4*iph-

>ip_hl+4*tcph->doff);
for(i=0;i<maxstringsize-1;++i)
{
if(i>=header->len-sizeof(struct ether_header)-

4*iph->ip_hl-4*tcph->doff);
break;
else
tcpudpdata=data;
}
} //TCP数据处理完毕
else if(iph->ip_p=17) //UDP报文
{
strcpy(protocol,"udp");
udph=(struct udphdr *)(pp+sizeof(struct ether_header)

+4*iph->ip_hl);
srcport=ntohs(udph->source);
dstport=ntohs(udph->dest);
data=(u_char *)(pp+sizeof(struct ether_header)+4*iph-

>ip_hl+8);
for(i=0;i<maxstringsize-1;++i)
{
if(i>=header->len-sizeof(struct ether_header)-

4*iph->ip_hl-8);
break;
else
tcpudpdata=data;
}
}
tcpudpdata='\0';
getportname(srcport,srcp,protocol);
getportname(dstport,dstp,protocol);
printf("ip ");
print_hwadd(eth->ether_shost);
printf("(");
print_hostname((u_char *)&(iph->ip_src));
printf(")[%s:%s]->",protocol,srcp);
print_hwadd(eth->ether_dhost);
printf("(");
print_hostname((u_char *)&(iph->ip_dst));
printf(")[%s:%s]",protocol,dstp);
printf("tttl:%d packetlen:%d,iph->ttl,header->len);
printf("n");
printf("%s",tcpudpdata);
printf("==endpacket==");
}
printf("n");
}
//Main函数取数据包并初始化程序环境
int main(int argc,char ** argv)
{
char ebuf[pcap_ERRBUF_SIZE];
pcap * pd;
if(argc<=1) //参数检查
{
printf("usage:%sn",argv[0]);
exit(0);
}
//设置PCAP程序库
if((pd=pcap_open_live(argv[1],DEFAULT_SNAPLEN,1,1000,ebuf))=NULL)
{
(void)fprintf(stderr,"%s",ebuf);
exit(1);
}
//循环取数据包
//改变参数-1为其它值,可确定取数据包的个数,这里为无限个
if(pcap_loop(pd,-1,packet_proce,NULL)<0)
{
(void)fprintf(stderr,"pcap_loop:%sn",pcap_geterr(pd));
exit(1);
}
pcap_colse(pd);
exit(0);
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
iptables 是一种在 Linux 操作系统上广泛使用的防火墙工具。它能够通过过滤、修改和重定向网络数据包来加强服务器的安全性。 首先,iptables 可以根据源和目标 IP 地址、端口号和协议类型等条件对网络数据包进行过滤。例如,我们可以配置 iptables 来阻止特定 IP 地址或端口的流量进入服务器,从而避免潜在的安全威胁。此外,我们还可以通过 iptables 的用户定义链来进行更复杂的过滤操作。 其次,iptables 还可以修改数据包的头部信息。通过修改数据包的源或目标 IP 地址等信息,我们可以实现网络地址转换(NAT)功能,将私有 IP 地址映射为公共 IP 地址以实现 Internet 访问。此外,还可以通过修改数据包的源或目标端口号来实现端口转发等功能。 最后,iptables 还可以根据一系列规则来重定向数据包。例如,我们可以配置 iptables 将特定端口号的流量重定向到不同的服务器,以实现负载均衡或高可用性。同时,iptables 还支持连接跟踪,可以跟踪连接状态,并根据连接状态来处理数据包,从而提供更高级的安全防护。 在实际应用中,我们可以使用 iptables 命令来创建、修改和删除规则。同时,为了简化配置过程,还可以使用一些图形界面的工具,如 firewalld 和 UFW,来管理iptables。需要注意的是,正确地配置 iptables 规则非常重要,因为不当配置可能会导致网络连接问题或安全漏洞。 总的来说,通过 iptables 的应用,我们能够灵活地设置与管理服务器的防火墙规则,从而保护服务器免受各种网络攻击和恶意流量的侵害。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值