
探究Linux下C语言与ARP协议的实现
随着计算机网络的迅猛发展,网络通信协议也越来越成熟和复杂,ARP(Address Resolution Protocol)协议是用于将IP地址转换为物理地址的一种网络协议。在Linux系统下,ARP协议的实现是由C语言编写的。本文将探究Linux下C语言与ARP协议的实现。
一、ARP协议的概述
ARP协议是指Address Resolution Protocol,即地址解析协议,它在互联网协议(IP)中被用来将IPv4地址转换成物理硬件地址,例如MAC地址。通俗的理解,ARP协议实现了IP地址到MAC地址的映射,当我们想要与其他设备通信时,首先需要知道目标设备的MAC地址,而ARP协议就是用来完成这个任务的。
当一个网络设备(网卡、路由器、交换机等)需要发送网络数据包时,它会尝试去获取目标IP地址对应的MAC地址,步骤如下:
1. 在ARP缓存中查找对应的IP地址的MAC地址,如果存在,则直接发送数据包到目标设备的MAC地址。
2. 如果ARP缓存中不存在对应的MAC地址,则网卡需要发送一个ARP请求数据包广播到整个网络中,请求目标设备回应自己的MAC地址。广播的数据包的源MAC地址为发送方的MAC地址,目标MAC地址为广播地址FF:FF:FF:FF:FF:FF,目标IP地址为目标设备的IP地址,发送方的IP地址为发送方IP地址。
3. 目标设备接收到ARP请求数据包后,如果发现请求中目标IP与自己的IP地址相同,则回复一个ARP应答数据包,表明自己的MAC地址是什么,此时源设备可以获取到目标设备的MAC地址,并在以后的网络通信中使用该地址。
二、 Linux C语言下的ARP实现
在Linux下,ARP协议的实现主要由C语言编写。下面将介绍Linux C语言下ARP协议实现的主要代码框架。
1. ARP协议数据结构
在Linux中,ARP请求数据包与应答数据包的结构是一致的。下面是ARP数据包的数据结构定义。
“`c
struct arphdr {
__be16 ar_hrd; //硬件地址类型
__be16 ar_pro; //协议地址类型
unsigned char ar_hln; //硬件地址长度
unsigned char ar_pln; //协议地址长度
__be16 ar_op; //ARP操作码
unsigned char ar_sha[ETH_ALEN]; //源MAC地址
__be32 ar_sip; //源IP地址
unsigned char ar_tha[ETH_ALEN]; //目标MAC地址
__be32 ar_tip; //目标IP地址
};
“`
其中,ar_hrd表示硬件地址类型,ar_pro表示协议地址类型,ar_hln表示硬件地址长度,ar_pln表示协议地址长度,ar_op表示ARP操作码,ar_sha表示源MAC地址,ar_sip表示源IP地址,ar_tha表示目标MAC地址,ar_tip表示目标IP地址。
2. ARP协议接口程序
ARP协议的实现主要由arp.c程序实现,下面是该程序的主要代码框架。
“`c
#include
#include
#include
#include
void arp_rcv(struct sk_buff *skb) {
//接收ARP数据包并进行处理
}
int arp_send(unsigned int type, struct net_device *dev,
unsigned long dest_ip, const unsigned char *dest_hw,
unsigned long src_ip, const unsigned char *src_hw,
const unsigned char *target_hw) {
//发送ARP数据包
}
void arp_create(struct net_device *dev) {
//创建ARP缓存
}
void arp_destroy(struct net_device *dev) {
//销毁ARP缓存
}
void arp_timer(unsigned long data) {
//处理ARP缓存中的超时数据
}
static struct neigh_parms * arp_parms_alloc(struct net_device *dev) {
//分配neigh_parms结构体
}
static void arp_parms_free(struct neigh_parms *parms) {
//释放neigh_parms结构体
}
static struct neigh_parms_template arp_parms_template = {
.parmsize = sizeof(struct arp_parms),
.neigh_priv_size = sizeof(struct arp_neigh),
.neigh_setup = arp_neigh_setup,
.neigh_cleanup = arp_neigh_cleanup,
};
void __init arp_init(void) {
//注册ARP协议到内核
}
“`
其中,arp_rcv函数用于接收ARP数据包,并进行处理;arp_send函数用于发送ARP数据包;arp_create函数用于创建ARP缓存;arp_destroy函数用于销毁ARP缓存;arp_timer函数用于处理ARP缓存中的超时数据。此外,arp_parms_alloc函数和arp_parms_free函数用于分配和释放neigh_parms结构体,而arp_parms_template结构体则定义了ARP协议相关的参数模板。
3. ARP协议的实现流程
ARP协议的实现流程主要包含以下几个步骤。
1. 接收ARP数据包
当一个ARP数据包到达时,首先需要通过arp_rcv函数接收数据包。
“`c
void arp_rcv(struct sk_buff *skb) {
struct arphdr *arp;
struct neighbour *neigh;
//检查数据包的长度是否正确
if (/* !数据包长度正确 */) {
kfree_skb(skb);
return;
}
//获取ARP协议头
arp = arp_hdr(skb);
//分配缓存结构体
neigh = neighbour_alloc(&arp_tbl, &arp->saddr, arp->ar_hln, 0, skb->dev);
if (neigh) {
//缓存数据包
neighbour_update(neigh, skb);
neighbour_release(neigh);
}
//释放缓存
kfree_skb(skb);
}
“`
在接收到数据包后,首先需要检查数据包的长度是否正确,然后通过arp_hdr函数获取ARP协议头。接下来需要分配缓存结构体,这里使用neighbour_alloc函数完成,该函数可以分配一个neighbour结构体并将其插入到neighbour表中。当缓存数据包后,使用neighbour_update函数更新缓存,并通过neighbour_release函数将缓存的neigh结构释放。最后将skb数据包指针释放。
2. 发送ARP数据包
当需要发送ARP数据包时,需要调用arp_send函数。
“`c
int arp_send(unsigned int type, struct net_device *dev,
unsigned long dest_ip, const unsigned char *dest_hw,
unsigned long src_ip, const unsigned char *src_hw,
const unsigned char *target_hw) {
struct sk_buff *skb;
struct arphdr *arp;
//分配skb缓存结构体
skb = alloc_skb(/* 指定缓存长度 */, GFP_ATOMIC);
if (!skb) {
return -ENOMEM;
}
//填充ARP头部
arp = (struct arphdr *) skb_put(skb, sizeof(struct arphdr));
//设置各个字段值
arp->ar_hrd = htons(ARPHRD_ETHER);
arp->ar_pro = htons(ETH_P_IP);
arp->ar_hln = ETH_ALEN;
arp->ar_pln = 4;
arp->ar_op = htons(type);
memcpy(arp->ar_sha, src_hw, ETH_ALEN);
arp->ar_sip = htonl(src_ip);
memset(arp->ar_tha, 0, ETH_ALEN);
arp->ar_tip= htonl(dest_ip);
if (target_hw) {
memcpy(arp->ar_tha, target_hw, ETH_ALEN);
}
//填充数据链路头
//调用dev_hard_start_xmit函数发送数据包
//释放skb缓存结构体
return 0;
}
“`
发送ARP数据包时,首先需要分配一个skb缓存结构体,然后填充ARP头部,设置各个字段值。最后将数据链路头填充,调用dev_hard_start_xmit函数发送数据包,发送完成后释放skb缓存结构体。
3. 创建和销毁ARP缓存
在ARP协议的实现中,需要创建一个缓存表用于存储ARP请求的响应数据。当缓存中的数据超时后,需要将其从缓存表中释放。
“`c
void arp_create(struct net_device *dev) {
//创建ARP缓存
}
void arp_destroy(struct net_device *dev) {
//销毁ARP缓存
}
“`
这里的arp_create和arp_destroy函数用于创建和销毁ARP缓存表。
4. ARP定时器
在ARP协议的实现中,由于网络环境可能会发生变化,ARP缓存中的数据可能会失效。因此,需要使用ARP定时器定期检查ARP缓存中的数据是否已经超时,如果已经超时,则需要将其释放。
“`c
void arp_timer(unsigned long data) {
//处理ARP缓存中的超时数据
}
“`
在定时器中,需要遍历缓存表,检查缓存中每个元素的时间戳是否已经超时,如果已经超时,则需要将其从缓存表中释放。
三、结论
相关问题拓展阅读:
- Linux主机如何防范ARP攻击?
Linux主机如何防范ARP攻击?
最根本的方法,是关掉网卡的ARP功能(ifconfig ethx -arp)。很多情况下,我们只需要与网关通信,网络里面其他的机器很少通信。所以我们建立一个ip地址和mac地址的对应关系文件:/etc/ethers
cat /etc/ethers
192.168.1.:14:78:8B:C4:54
然后执行 arp -f 的命令,即可绑定。
经过以上两个步骤,arp攻击中对你的欺骗裂谨就不起作用了。但是,arp欺骗还有另外一种方式,就是欺骗网关,以至于网关无法获得你棚档的正确mac地址,这个问题又要怎样解决呢?
arping -U -I eth0 -s 192.168.1.17 192.168.1.254
这个命令的含义为将绑定在eth0上的IP地址(192.168.1.17)对应的MAC地址告诉网关(192.168.1.254)
但是,请链源乱大家注意,关闭了网卡的arp功能之后,这个命令也就不能使用了。也就是说,以上两个方法分别可以应付单一的ARP欺骗攻击。但是由于上述两法无法同时使用,攻击方若采取“中间人”攻击,被攻击的机器必然无法正常与网关通信,但是“中间人”的攻击也是无法得逞的。
我仍然在寻找更好的方法,如有哪位朋友知道,还请不吝赐教!
arp欺骗的原理不多述,基本就是利用发 送假的arp数据包,冒充网关。一般在网上通讯的时候网关的IP和MAC的绑定是放在arp 缓存里面的,假的arp包就会刷新这个缓存,导致本该发送到网关的数据包发到了欺骗 者那里。解决的办法就是静态arp。
假设网关的IP是192.168.0.1,我们要 先得到网关的正确MAC,先ping一下网关:
ping 192.168.0.
然后运行arp查看arp缓存中的网关MAC:
localhost~$ arp
AddressHWtype HWaddressFlags Mask Interface
192.168.0.1 ether 00:12:34:56:78:9A Ceth0
、这里得到的网关MAC假定 为00:12:34:56:78:9A,C代表这个绑定是保存在缓冲里的,我们要做的就是把毕棚这个IP和 MAC静态的绑定在一起,首先建立/etc/ethers文件,输入以下内容:
192.168.0.1 00:12:34:56:78:9A
保存退出,之后便是应 用这手族则个静态绑定:
localhost~$ arp -f
再运行arp查看:
localhost~$ arp
AddressHWtype HWaddressFlags Mask Interface
192.168.0.1 ether 00:12:34:56:78:9A CMeth0
多了个M,表示静态网关 ~
另外,如果你不会和局域网内的用户通讯的话,那么可以干脆 把arp解析关掉,假定你的网卡是eth0,那么可以运行:
localhost~$ ifconfig eth0 -arp
这样对付那些终结者软件就可以了,但是真的有人 向攻击的话,这样还是不够的,因为攻击者还可以欺骗网关,解决的办法就是在网关和 局域网内机器上做双向绑定,原理方法同上,一般网吧里面也是这样做的。穗辩
试试金山的ARP防火墙。。。
关于linux c arp的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站。
香港服务器首选树叶云,2H2G首月10元开通。
树叶云(www.IDC.Net)提供简单好用,价格厚道的香港/美国云服务器和独立服务器。IDC+ISP+ICP资质。ARIN和APNIC会员。成熟技术团队15年行业经验。
文章来源网络,作者:运维,如若转载,请注明出处:https://shuyeidc.com/wp/180356.html<