ARP协议DPI深度解析
项目需要采用DPI对ARP报文进行解析(也可以借鉴open dpi?),整理ARP报文结构如下:
结构ether_header定义了以太网帧首部;结构arphdr定义了其后的5个字段,其信息用于在任何类型的介质上传送ARP请求和回答;ether_arp结构除了包含arphdr结构外,还包含源主机和目的主机的地址。
定义以太网首部:
typedef struct ehhdr
{
unsigned char eh_dst[6]; /* destination ethernet addrress */
unsigned char eh_src[6]; /* source ethernet addresss */
unsigned short eh_type; /* ethernet pachet type */
}EHHDR, *PEHHDR;
定义以太网arp字段:
typedef struct arphdr
{
/* arp 头 */
unsigned short arp_hrd; /* format of hardware address */
unsigned short arp_pro; /* format of protocol address */
unsigned char arp_hln; /* length of hardware address */
unsigned char arp_pln; /* length of protocol address */
unsigned short arp_op; /* ARP/RARP operation */
/* 发送端信息(mac + ip) */
unsigned char arp_sha[6]; /* sender hardware address */
unsigned long arp_spa; /* sender protocol address */
/* 目的端信息(mac + ip) */
unsigned char arp_tha[6]; /* target hardware address */
unsigned long arp_tpa; /* target protocol address */
}ARPHDR, *PARPHDR;
ARP应答报文会将自己的 mac + ip 填在发送端信息中;将请求端的 mac + ip 填在目的端信息中;即对调ARP请求报文中的信息。
根据以上结构可以定义整个arp报文包,总长度42字节:
typedef struct arpPacket
{
EHHDR ehhdr;
ARPHDR arphdr;
} ARPPACKET, *PARPPACKET;
根据定义,头6个字节是以太网目的地址 ff ff ff ff ff ff 这是一个广播地址,全网下的所有终端都能接收到,紧跟着的6个字节是以太网源地址,即发送者的MAC地址( 00 0c f1 d4 d9 60 是我的MAC地址)。帧类型0806占两个字节,到这里以太网帧头就结束了。0806指的是后面的数据是属于arp包的。
接着分析ARP包头。头两个字节是硬件类型 00 01,接着两个字节是协议类型,即ARP使用的是IP协议代号08 00。硬件地址长度和协议地址长度分别是6和4。这与ARP报文格式是对应的。后面的2个字节OP指示当前包是请求包还是应答包,对应的值分别是0x0001和0x0002。原始数据里是00 01所以这是一个请求包,然后6个字节又是发送者MAC地址00 0c f1 d4 d9 60 ,后面4个字节是发送者IP地址c0 a8 01 0f ,转换成点分十进制格式即192.168.1.15,这是我的IP,接下来的6个字节留空,00 00 00 00 00 00 在arp请求包里也可以是其他数据,因为稍后IP地址为c0 a8 01 02 (192.168.1.2)会把自己的MAC地址填充进这6个字节中。
填充完后,arp包里的发送者硬件地址|目标硬件地址和以太网首部的以太网目的地址|以太网源地址正好对调。最后把这个封装好的ARP包发送出去,这样一个来回就可以让两台终端互相知道对方的IP和MAC。利用wireShark抓包如下:
Linux 定义ARP协议报文结构如下:
下一篇: python time模块用法实例详解