专业编程基础技术教程

网站首页 > 基础教程 正文

常用网络协议整理笔记(二)---ARP/RARP协议

ccvgpt 2025-01-11 10:51:11 基础教程 3 ℃

一、ARP/RARP作用:

1. ARP(地址解析协议,Address Resolution Protocol)是一种工作在OSI模型第二层(数据链路层)的协议,用于将IP地址转换为对应的物理MAC地址;

2. ARP是IPv4协议栈中的一个重要组成部分,主要用于同一局域网内设备之间的通信, 因为同一局域网中的两台主机进行通信时,需要通过MAC地址进行定位,然后才能进行数据包的发送;

常用网络协议整理笔记(二)---ARP/RARP协议

3. ARP协议仅存在于IPv4, IPv6中没有ARP协议。其原因是因为IPv6采用了邻居发现协议(Neighbor Discovery Protocol,NDP)来处理地址解析和邻居发现,以取代IPv4中的ARP;

4. RARP(反向地址解析协议)RARP的主要作用是将数据链路层的MAC地址转换为网络层的IP地址。主要用于在网络启动时为无盘工作站或某些设备动态获取IP地址。现在RARP在现代网络中已经被DHCP等更为先进的协议所取代; 有如下作用:

a. IP地址获取:RARP的主要作用是帮助设备获取其IP地址。通常用于无盘工作站或其他启动时没有存储介质的设备。这些设备在启动时只知道自己的MAC地址,但不知道自己的IP地址。

b. 反向解析:RARP通过广播请求,询问网络中是否有RARP服务器能够将其MAC地址解析为IP地址。RARP服务器会查找其配置的映射表,找到相应的IP地址并返回给请求设备。

----------------------------------------------------------------------------------------------------------------

二.工作流程和原理:

1. 普通ARP通信(同一子网内):


1). 查询ARP缓存表:当一个设备(如主机A,IP为192.168.1.2)需要发送数据到另一个设备(如主机B,IP为192.168.1.3)时,它首先检查自己的ARP缓存(一个存储IP地址与MAC地址间的映射表);

2). 发送ARP请求。如果缓存中没有目标设备的MAC地址,主机A会广播一个ARP请求,询问“谁拥有这个IP地址?”;

3) .主机B响应:网络中所有设备都会接收到这个ARP请求,但只有拥有该IP地址的设备(主机B)会发送一个ARP响应,包含自己MAC地址信息;

4).更新缓存:主机A接收到ARP响应后,会更新自己的ARP缓存,将IP地址与对应的MAC地址进行关联;

5). 发送数据:一旦主机A得到了主机B的MAC地址,它就可以将数据帧发送到B机B。

以上为一般的普通ARP通信流程,其它几种特殊ARP请求在报文内容稍有区别。


2.代理ARP通信(不同子网):

如果是在不同链路间如何发送ARP请求呢?这就要使用到 代理 ARP 了。代理ARP(Proxy ARP)允许路由器在网络中充当代理,响应目标设备的ARP请求,从而使设备可以在没有直接连接的情况下与目标设备通信。

假设我们有以下的网络拓扑,有如下的通信需求:

PC1在子网1中,但它需要与子网2中的PC2进行通信。PC1知道PC2的IP地址(172.16.20.100),但是由于它在不同的子网中,它无法直接访问PC2的MAC地址。

---子网 1 (172.16.10.0/24):连接着PC1(IP地址:172.16.10.100)。

---子网 2 (172.16.20.0/24):连接着PC2(IP地址:172.16.20.100,MAC:00:00:0C:94:36:CC)。

---路由器:连接着两个子网,接口1(172.16.10.0/24)连接到子网1,接口2(172.16.20.0/24)连接到子网2, MAC为:00:00:0C:94:36:AB

因此,PC1发送一个ARP请求,希望知道目标IP地址(172.16.20.100)对应的MAC地址。

具体步骤如下:

1). PC1广播发送ARP请求:

PC1准备发送数据包到PC2的IP地址(172.16.20.100),但它不清楚目标IP对应的MAC地址。于是,计算机A会向本地网络广播一个ARP请求:


ARP请求:谁拥有IP地址 172.16.20.100?请告诉 172.16.10.100。

这个ARP请求会被广播到子网1中的所有设备,包括路由器。

2). 路由器监听ARP请求并作出响应:

路由器知道目标IP地址(172.16.20.100)位于子网2(172.16.20.0/24)中,而计算机A位于子网1(172.16.10.0/24)中。路由器将检查其路由表,确认它能够路由到目标IP。

在代理ARP的工作模式下,路由器会假装自己是目标设备(PC2),并向PC1发送一个ARP响应。路由器将自己的MAC地址作为目标MAC地址,告诉PC1:“我就是目标IP(172.16.20.100)对应的MAC地址。”


路由器的ARP响应类似于:

ARP响应:172.16.20.100 的MAC地址是00:00:0C:94:36:AB。(这是路由器的MAC地址)

3). 计算机A更新ARP缓存并发送数据包

PC1收到路由器的ARP响应后,认为172.16.20.100对应的MAC地址是路由器的MAC地址(00:00:0C:94:36:AB)。因此,PC1将这个MAC地址存入其ARP缓存中,并将数据包发送给路由器,而不是直接发送给PC2。

此时,PC1的ARP缓存中会记录:

192.168.2.20 ---> 00:00:0C:94:36:AB (路由器的MAC地址)

4). 路由器转发数据包到PC2

路由器收到PC1发来的数据包后,发现数据包的目标IP是172.16.20.100,并且知道这个IP地址属于子网2。于是,路由器会将数据包转发到PC2。路由器根据其路由表找到PC2的MAC地址,并将数据包发送给PC2。


3.RARP(类似于DHCP):

1). 请求:当一个设备(如无盘工作站)启动时,它知道自己的MAC地址,但不知道自己的IP地址。它会广播一个RARP请求,请求网络中的RARP服务器提供其对应的IP地址。

2).响应:网络中的RARP服务器会接收到这个请求,检查其数据库中MAC地址与IP地址的映射关系,并发送一个RARP响应,包含对应的IP地址。

. 配置IP地址:无盘工作站接收到RARP响应后,会配置自己的IP地址,以便参与网络通信。

----------------------------------------------------------------------------------------------------------------

三. ARP/RARP协议格式

ARP报文分为ARP请求报文和ARP响应报文,其格式如下:

1.ARP请求报文格式:


ARP报文格式总的来说包括以下几个部分:

字段

长度(字节)

说明

硬件类型

2

指定网络类型,值为 1 表示以太网(Ethernet)。

协议类型

2

指定协议类型,值为 0x0800 表示IPv4协议。

硬件地址长度

1

指定硬件地址的长度(以太网为6字节)。

协议地址长度

1

指定协议地址的长度(IPv4地址为4字节)。

操作类型

2

表示ARP操作类型,1 表示请求(ARP Request),2 表示响应(ARP Reply)。

源MAC地址

6

发送方的MAC地址(以太网地址,6字节)。

源IP地址

4

发送方的IP地址(IPv4地址,4字节)。

目标MAC地址

6

目标方的MAC地址(ARP请求时为空,ARP响应时为目标设备的MAC地址)。

目标IP地址

4

目标方的IP地址(4字节)。

ARP请求报文格式示例

假设设备A(IP: 192.168.1.1,MAC: 00:11:22:33:44:55)想要发送数据给设备B(IP: 192.168.1.2),但是它不知道设备B的MAC地址,于是它会发送一个ARP请求,询问"谁拥有IP地址192.168.1.2?"。

字段名

示例值 (十六进制表示)

硬件类型 (Hardware Type)

0x0001 (以太网)

协议类型 (Protocol Type)

0x0800 (IPv4)

MAC地址长度

0x06 (6字节)

IP地址长度

0x04 (4字节)

操作类型 (Operation)

0x0001 (ARP请求)

发送者MAC地址 (Sender Hardware
Address)

00:11:22:33:44:55 (设备A的MAC地址)

发送者IP地址 (Sender Protocol
Address)

192.168.1.1 (设备A的IP地址)

目标MAC地址 (Target Hardware
Address)

00:00:00:00:00:00 (ARP请求时为空)

目标IP地址 (Target Protocol
Address)

192.168.1.2 (设备B的IP地址)

2. ARP响应报文格式:

a. ARP响应的格式与请求相似,只是响应时填写了目标设备的MAC地址,确保目标设备能够获取到响应者的MAC地址。

b. ARP响应报文格式示例

设备B收到ARP请求后,知道设备A想要发送数据给它,并且它拥有IP地址 192.168.1.2,所以它会发送一个ARP响应,告知设备A自己的MAC地址 00:99:88:77:66:55。

字段名

示例值 (十六进制表示)

硬件类型
(Hardware Type)

0x0001 (以太网)

协议类型
(Protocol Type)

0x0800 (IPv4)

MAC地址长度 (Hardware Address Length)

0x06 (6字节)

IP地址长度 (Protocol Address Length)

0x04 (4字节)

操作类型 (Operation)

0x0002 (ARP响应)

发送者MAC地址 (Sender Hardware Address)

00:99:88:77:66:55 (设备B的MAC地址)

发送者IP地址 (Sender Protocol Address)

192.168.1.2 (设备B的IP地址)

目标MAC地址 (Target Hardware Address)

00:11:22:33:44:55 (设备A的MAC地址)

目标IP地址 (Target Protocol Address)

192.168.1.1 (设备A的IP地址)

3.RARP格式:

RARP协议的报文格式与ARP非常相似,因为它们在设计上是紧密相关的。RARP的报文格式包括以下字段:

字段

长度
(字节)

说明

硬件类型

2

指定网络类型,值为 1 表示以太网(Ethernet)。

协议类型

2

指定协议类型,值为 0x0800 表示IPv4协议。

MAC地址长度

1

指定硬件地址的长度(以太网为6字节)。

IP地址长度

1

指定协议地址的长度(IPv4地址为4字节)。

操作类型
(Operation)

2

表示RARP操作类型,通常为 3 表示RARP请求,4 表示RARP响应。

发送者MAC地址 (Sender Hardware Address)

6

发送方的MAC地址(以太网地址,6字节)。

发送者IP地址 (Sender Protocol Address)

4

通常为空,因为请求方不知道自己的IP地址。

目标MAC地址 (Target Hardware Address)

6

目标方的MAC地址,通常与发送者MAC地址相同。

目标IP地址 (Target Protocol Address)

4

通常为空,因为请求方不知道目标的IP地址。

----------------------------------------------------------------------------------------------------------------

四、 使用场景

ARP协议在平常使用有典型的四种情况,具体说明如下:

1. 普通ARP:


a.说明:

普通ARP是标准的地址解析协议,用于将网络层的IP地址转换为数据链路层的MAC地址。它在局域网中广泛使用,允许设备通过IP地址找到对应的MAC地址,以便进行数据帧的发送。

(1). 报文:

a. 请求报文:

以设备A发送ARP广播为例子说明报文格式如下.

---Sender MAC address: a4:56:02:c9:51:dc (设备A自己MAC)

---Sender IP address: 192.168.0.1 (设备A自己IP)

---Target MAC address: FF:FF:FF:FF:FF:FF (广播地址)

---Target IP address: 192.168.0.3 (需要查询设备MAC的IP)

(2) . 响应报文:

设备C回应带上自己的MAC和IP;

(3). 用途:

· 地址解析:普通ARP的主要作用是将目标设备的IP地址解析为其MAC地址,以便在局域网内进行通信。

· ARP请求和响应:当设备需要发送数据到另一个设备时,它会发送ARP请求,询问目标IP地址对应的MAC地址。拥有该IP地址的设备会响应并提供其MAC地址。

· ARP缓存:普通ARP会将解析得到的IP地址和MAC地址的映射存储在ARP缓存中,以提高后续通信的效率。


2. 免费ARP(Gratuitous ARP):

(1). 说明:免费ARP是一种特殊的ARP请求,主要用于在网络中确认某个IP地址是否已经被其他设备占用。它通常在设备启动时使用,以确保所配置的IP地址没有冲突。

(2). 报文:

a. 请求报文:

以设备A发送ARP广播为例子说明报文格式如下.

---Sender MAC address: a4:56:02:c9:51:dc (设备A自己MAC)

---Sender IP address: 192.168.0.1 (设备A自己IP)

---Target MAC address: FF:FF:FF:FF:FF:FF (广播地址)

---Target IP address: 192.168.0.1 (设备A自己IP)

b. 响应报文:

--如果没有收到响应,则此IP可用;

--如果收到响应,则同一网络存在IP冲突;


(3). 用途:

· 该类型报文起到一个宣告作用。它以广播的形式将数据包发送出去,不需要得到回应,只为了告诉其他计算机自己的IP地址和MAC地址。

· 可用于检测IP地址冲突。当一台主机发送了免费ARP请求报文后,如果收到了ARP响应报文,则说明网络内已经存在使用该IP地址的主机。

· 可用于更新其他主机的ARP缓存表。如果该主机更换了网卡,而其他主机的ARP缓存表仍然保留着原来的MAC地址。这时,可以发送免费的 ARP数据包。其他主机收到该数据包后,将更新ARP缓存表,将原来的 MAC地址替换为新的MAC地址。



3. 代理ARP:


(1). 说明:

在代理ARP中,当路由器接收到ARP请求时,它会检查请求中的目标IP地址,如果该IP地址属于另一个子网,路由器将响应请求,假装自己是目标设备,并提供其自己的MAC地址。这样,ARP请求的发起者就能够将数据包发送到路由器,而路由器则会负责将数据包转发到目标设备。


(2).报文:

代理ARP(Proxy ARP)并没有独特的请求和响应报文格式,实际上,代理ARP使用的是标准的ARP请求和响应报文。唯一的区别在于,代理ARP中的路由器会伪造ARP响应,以自己的MAC地址回应ARP请求,而不是目标设备的MAC地址。

如果路由器发现目标IP属于另一个子网,路由器将使用其自身的MAC地址响应ARP请求,伪造ARP响应,如下:

a. 设备A请求报文:

以设备A发送ARP广播为例子说明报文格式如下.

---Sender MAC address: a4:56:02:c9:51:dc (设备A自己MAC)

---Sender IP address: 192.168.0.1 (设备A自己IP)

---Target MAC address: FF:FF:FF:FF:FF:FF (广播地址)

---Target IP address: 192.168.1.3 (需要查询设备MAC的IP,不同子网)

b. AP响应报文:

---Sender MAC address: a4:56:02:c9:51:dc (路由器AP自己MAC,不是设备B的MAC!!)

---Sender IP address: 192.168.1.3 (设备B的IP,192.168.1.3)

---Target MAC address: a4:56:02:c9:51:dc (设备A的MAC)

---Target IP address: 192.168.0.1 (设备A的IP)


(3). 用途:

a. 跨子网通信:代理ARP使得不同子网中的设备能够相互通信,而不需要设备了解目标设备的实际位置。设备只需知道目标设备的IP地址,路由器会代理ARP请求并提供相应的MAC地址。

b. 简化网络配置:使用代理ARP,网络中的设备不需要配置复杂的路由信息和网络掩码。设备只需配置自己的IP地址和默认网关(通常是路由器的IP地址),路由器会处理跨子网的通信。

c. 支持旧设备:一些旧设备可能不支持更复杂的网络协议(如RIP、OSPF等),而代理ARP可以为这些设备提供必要的地址解析支持。

(4) d. 网络地址重叠:在某些情况下,可能存在多个子网使用相同的IP地址范围。代理ARP可以帮助路由器处理这些情况,从而使得设备能够在不同的子网中通信,而不需要更改IP地址。

e. 透明性:对于终端设备来说,代理ARP提供了一种透明的通信方式。设备无需关心网络拓扑的复杂性,能够像在同一网络中一样进行数据传输。


3.ARP缓存

(1). 说明:

ARP缓存是主机在网络中管理和存储IP地址与其对应的MAC地址映射关系的数据结构。它在网络通信中扮演着重要的角色,帮助设备迅速识别和定位通信目标的物理地址,从而提高数据传输的效率。

(2). 作用:

a. 提高效率, 减小网络负载

避免频繁的ARP请求:ARP缓存通过存储IP地址和MAC地址的映射关系,减少了网络上ARP广播请求的频率,从而降低了网络开销。ARP缓存通过缓存MAC地址减少了网络流量。

(2) b. 支持网络通信的持续性

通过缓存IP和MAC地址的对应关系,ARP缓存为需要经常通信的设备间保持快速的ARP解析,确保网络的流畅性。

(3). 分类:

a. 静态ARP缓存:

--- 特性:静态ARP条目是由管理员手动配置的,其IP-MAC地址对不会被轻易更改或删除。

--- 用途:用于需要特别关注的关键网络设备,确保重要设备地址不会因网络变化而丢失。

--- 优点:提供稳定可靠的地址映射,避免ARP欺骗攻击。

--- 缺点:需要手动维护,信息不够灵活,网络拓扑改变时需手动更新。

b. 动态ARP缓存:

--- 特性:动态ARP条目是由系统通过ARP协议自动生成和更新的。

--- 用途:适用于大多数联网设备,能自动适应网络拓扑的变化。

--- 优点:易于管理,随着网络通信自动更新,减少了手动维护工作。

--- 缺点:缓存条目在一定时间后会过期,需要重新查询,若被不当利用可能存在ARP欺骗风险。


c. ARP缓存更新机制:

ARP缓存表更新机制是确保网络通信有效性和稳定性的关键组成部分。通过定期清理过时的ARP条目,网络设备能够保持最新的地址映射,从而提高通信效率,适应网络变化,并增强安全性.有如下三种更新机制:

---超时设置:

每个ARP缓存条目都有一个超时时间(TTL,Time To Live),当ARP条目被创建时,系统会记录下该条目的创建时间,并设置其超时时间。

---定期检查:

网络设备会定期检查ARP缓存表中的条目,查看哪些条目已经超时。超时的条目会被标记为无效,并从缓存中删除。

---重新查询:

如果设备在缓存中找不到目标IP地址的MAC地址,或者该条目已过期,设备会重新发送ARP请求,以获取目标IP地址的最新MAC地址。


4.ARP老化机制

(1).说明:

ARP老化机制(ARP Aging Mechanism)是指ARP缓存表中条目在一定时间后会自动失效并被删除的过程。这个过程旨在确保ARP表中保存的信息始终是最新的,同时避免缓存中的条目因设备的变化或网络的动态性而过时。老化机制是ARP缓存管理中的一个重要部分,它通过定期检查和删除过期的条目,确保网络通信的可靠性和效率。

(2).重要性:

a. 确保地址映射的准确性

网络中的设备可能会移动、更换IP地址或发生故障,导致MAC地址映射发生变化。ARP老化机制通过定期删除过期的缓存条目,确保ARP缓存中的信息始终是最新的,从而避免使用过时的MAC地址进行通信。

b. 避免ARP缓存污染

ARP缓存可能会被错误的或恶意的ARP响应污染,导致设备将错误的MAC地址与某个IP地址关联。老化机制可以定期清理缓存,减少这类问题的影响。

c. 适应网络拓扑变化

在动态的网络环境中,设备的加入、离开或重新配置可能会频繁发生。ARP老化机制确保设备在每次查询时都能够获得正确的MAC地址,帮助设备快速适应网络的变化。

d. 提高性能:

通过清理无效的ARP条目,ARP老化机制减少了ARP表中的冗余数据,提高了查找和查询的效率。设备不再需要维护大量过时的条目。

(3).设置方法:

在Linux系统中,ARP缓存的默认老化时间通常为60秒(可以通过sysctl命令进行查看和修改)。

---查看当前ARP缓存超时时间:

cat /proc/sys/net/ipv4/neigh/default/gc_stale_time

---修改ARP缓存老化时间:

sysctl -w net.ipv4.neigh.default.gc_stale_time=120

-----------------------------------------------------------------------------------------------

五、ARP 攻击和欺骗

由于ARP协议本身没有认证机制,任何设备都可以发送ARP请求和ARP响应。ARP攻击和欺骗正是利用了ARP协议的这种信任机制,能够伪造ARP消息,从而导致网络中数据包被错误地转发,可以导致严重的网络安全问题。

了解ARP攻击的原理和方式,以及采取有效的防范措施,是保护网络安全的重要一环。通过实施静态ARP条目、使用监控工具、启用动态ARP检查等方法,可以有效减少ARP攻击的风险。

1. ARP攻击原理:

结合上图举例说明其攻击原理:

网络中有A、B、C 三台主机,主机 A与主机 B 正常通信,主机 C 进入网络,开始实施 ARP 欺骗。流程如下:

a. 主机A想给主机B发送数据,只知道其IP,但不知道主机B的MAC信息,故在局域网内以广播方式发了一个ARP请求;

b. 主机 C在收到这个ARP请求后,给主机 A发一个 ARP 应答报文,报文显示主机B的 IP 地址映射主机C的 MAC;

c. 主机A收到这个报文,添加或更新自己的ARP 缓存表,修改主机B的 IP 地址对应的 MAC信息(主机C的MAC),这样,其后主机A发往主机B的数据包均会发给主机C;

d. 如果主机C不转发该数据包到主机 B,则主机 B 认为与主机 A的通信发生故障,而主机A无法察觉;如果主机 C 转发数据包到主机B,则主机B与主机A之间的通信不受影响,但主机C可以监听到主机A到主机 B的所有数据包;

e. 同理,主机C发ARP应答报文欺骗主机B, 则主机B发往主机A的数据包被主机 C 监听。


2. ARP攻击和欺骗分类:

(1). ARP欺骗(ARP Spoofing)

攻击者向局域网中的设备发送伪造的ARP响应,声称其MAC地址与一个合法的IP地址(如网关或其他设备)相关联。受害者设备接收到这些伪造的ARP响应后,会将攻击者的MAC地址更新到其ARP缓存中,从而错误地将数据发送给攻击者。

(2). ARP中毒(ARP Poisoning)

攻击者不断向网络中的设备发送伪造的ARP消息,污染多个设备的ARP缓存。

这种攻击通常是通过发送大量的ARP响应来完成,使目标设备的ARP表中存储错误的MAC地址。

(3). 拒绝服务攻击(DoS)

攻击者发送大量虚假的ARP请求,导致目标设备的ARP缓存表被填满或不断更新。

这可能导致合法的ARP请求被丢弃,影响设备的正常通信。使目标设备无法与其他设备正常通信,造成服务中断。

(4) 网关欺骗(Gateway Spoofing)

攻击者伪装成网络的默认网关,通过发送伪造的ARP响应,将自己的MAC地址与网关的IP地址关联。受害者设备会将流量发送到攻击者的设备,而不是合法的网关。

(5)主机重定向攻击

攻击者向特定的目标设备发送伪造的ARP消息,将其MAC地址与其他设备的IP地址进行关联。

这会导致目标设备的流量被重定向到攻击者的设备。使攻击者能够监视或篡改数据流,获取敏感信息。

(6) ARP请求洪水(ARP Request Flooding)

攻击者发送大量的ARP请求,试图快速填满网络中的ARP缓存。

这种攻击可能会消耗网络带宽并使其他设备无法正常处理请求。造成网络拥塞,影响正常的网络操作。

----------------------------------------------------------------------------------------------------------

六. 代码示例:

以下代码展示如何发送ARP请求并解析ARP响应。该代码会构造一个ARP请求,发送到网络,并监听网络接口以接收ARP响应。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/ether.h>
#include <netinet/ip.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
 
#define ARP_REQUEST 1
#define ARP_REPLY   2
 
// ARP头部结构
struct arp_header {
    uint16_t hw_type;       // 硬件类型
    uint16_t proto_type;    // 协议类型
    uint8_t hw_size;        // 硬件地址长度
    uint8_t proto_size;     // 协议地址长度
    uint16_t opcode;        // 操作码
    uint8_t sender_hw_addr[ETH_ALEN]; // 发送者硬件地址
    uint32_t sender_proto_addr;       // 发送者协议地址
    uint8_t target_hw_addr[ETH_ALEN]; // 目标硬件地址
    uint32_t target_proto_addr;        // 目标协议地址
};
 
// 发送ARP请求
void send_arp_request(int sockfd, const char *interface, const char *target_ip) {
    struct ifreq ifr;
    struct sockaddr_ll sa;
    struct arp_header arp_req;
    uint8_t packet[ETH_FRAME_LEN];
 
    // 获取网络接口信息
    memset(&ifr, 0, sizeof(ifr));
    strncpy(ifr.ifr_name, interface, IFNAMSIZ - 1);
    ioctl(sockfd, SIOCGIFHWADDR, &ifr);
 
    // 填充ARP请求
    memset(&arp_req, 0, sizeof(arp_req));
    arp_req.hw_type = htons(1); // Ethernet
    arp_req.proto_type = htons(0x0800); // IP
    arp_req.hw_size = ETH_ALEN; // MAC地址长度
    arp_req.proto_size = sizeof(in_addr_t); // IP地址长度
    arp_req.opcode = htons(ARP_REQUEST); // 操作码
    memcpy(arp_req.sender_hw_addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN); // 发送者MAC
    arp_req.sender_proto_addr = htonl(INADDR_ANY); // 发送者IP(可以是本机IP)
    memset(arp_req.target_hw_addr, 0x00, ETH_ALEN); // 目标MAC(未知)
    arp_req.target_proto_addr = inet_addr(target_ip); // 目标IP
 
    // 构造以太网帧
    memset(packet, 0, ETH_FRAME_LEN);
    memcpy(packet, arp_req.sender_hw_addr, ETH_ALEN); // 源MAC
    memset(packet + ETH_ALEN, 0xff, ETH_ALEN); // 目标MAC(广播)
    memcpy(packet + 12, &arp_req, sizeof(arp_req)); // ARP负载
 
    // 获取网络接口索引
    memset(&sa, 0, sizeof(sa));
    sa.sll_ifindex = if_nametoindex(interface);
    sa.sll_family = AF_PACKET;
 
    // 发送ARP请求
    if (sendto(sockfd, packet, sizeof(packet), 0, (struct sockaddr*)&sa, sizeof(sa)) < 0) {
        perror("sendto");
    } else {
        printf("ARP request sent for IP: %s\n", target_ip);
    }
}
 
// 解析ARP响应
void parse_arp_response(uint8_t *buffer, int len) {
    struct arp_header *arp_resp = (struct arp_header *)(buffer + 14); // 以太网头部为14字节
 
    if (ntohs(arp_resp->opcode) == ARP_REPLY) {
        printf("Received ARP reply:\n");
        printf("Sender MAC: %02x:%02x:%02x:%02x:%02x:%02x\n",
               arp_resp->sender_hw_addr[0],
               arp_resp->sender_hw_addr[1],
               arp_resp->sender_hw_addr[2],
               arp_resp->sender_hw_addr[3],
               arp_resp->sender_hw_addr[4],
               arp_resp->sender_hw_addr[5]);
        printf("Sender IP: %s\n", inet_ntoa(*(struct in_addr *)&arp_resp->sender_proto_addr));
    }
}
 
/////////////////////////3.main ////////////////////////////////
int main(int argc, char *argv[]) {
    if (argc != 3) {
        fprintf(stderr, "Usage: %s <interface> <target_ip>\n", argv[0]);
        exit(EXIT_FAILURE);
    }
 
    const char *interface = argv[1];
    const char *target_ip = argv[2];
 
    // 创建原始套接字
    int sockfd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
    if (sockfd < 0) {
        perror("socket");
        exit(EXIT_FAILURE);
    }
 
    /***** 1.发送ARP请求  ******/
    send_arp_request(sockfd, interface, target_ip);
 
    /**** 2.接收ARP响应  *****/
    uint8_t buffer[ETH_FRAME_LEN];
    struct sockaddr saddr;
    socklen_t saddr_len = sizeof(saddr);
 
    while (1) {
        ssize_t len = recvfrom(sockfd, buffer, ETH_FRAME_LEN, 0, &saddr, &saddr_len);
        if (len < 0) {
            perror("recvfrom");
            close(sockfd);
            exit(EXIT_FAILURE);
        }
 
        /*****3. 解析ARP响应  ****/
        parse_arp_response(buffer, len);
    }
 
    // 关闭套接字
    close(sockfd);
    return 0;
}

例子说明:

  • 权限:由于直接操作网络接口和发送原始数据包,程序需要在具有管理员权限的情况下运行。如:sudo ./arp_request_response eth0 192.168.1.1
  • 接口名称:确保提供的网络接口名称(如eth0)在系统中是有效的。
  • 目标IP:替换为你希望发送ARP请求的目标IP地址。
  • 安全性:使用原始套接字和ARP请求可能会引起网络管理员的注意,确保在合法和授权的环境中进行测试。

最近发表
标签列表