ARP是什么
地址解析协议(Address Resolution Protocol,ARP)是一种用于在IPv4网络中将IP地址映射到物理MAC地址的协议。它在局域网中帮助设备找到其他设备的物理地址,以便将网络数据包正确地传送到目标设备。
ARP报文传输过程:
当一个设备(主机或路由器)需要发送数据包到一个目标设备的IP地址时,它首先会检查本地的ARP缓存表,查看是否已经知道了目标IP对应的MAC地址。如果没有,设备会执行以下步骤来获取目标设备的MAC地址:
ARP请求(ARP Request):
发送方设备创建一个ARP请求报文,其中包含以下字段:
源MAC地址
源IP地址
目标IP地址(待查询的IP地址)
这个ARP请求报文会以广播方式发送到本地局域网中的所有设备。
ARP应答(ARP Reply):
目标设备接收到广播的ARP请求后,会检查请求中的目标IP地址是否与自己的IP地址匹配。如果匹配,它将创建一个ARP应答报文,其中包含以下字段:
源MAC地址
源IP地址
目标MAC地址(请求方的MAC地址)
目标IP地址(请求方的IP地址)
这个ARP应答报文会单播发送给请求方,以便请求方可以更新自己的ARP缓存表,将目标IP和MAC地址映射存储起来。
ARP报文字段
1.Dest MAC:目的MAC地址
2.Src MAC:源MAC地址
3.帧类型:0x0806
4.硬件类型:1(以太网)
5.协议类型:0x0800(IP地址)
6.硬件地址长度:6
7.协议地址长度:4
8.OP:1(ARP请求),2(ARP应答),3(RARP请求),4(RARP应答)
ARP请求抓包对应字段
ARP应答抓包对应字段
以太网头部
struct ether_header 所在位置:#include <net/ethernet.h> (首选)
struct ethhdr; 所在位置:#include<linux/if_ether.h>
ARP头部
struct arphdr ; 所在位置 /usr/include/net/if_arp.h #include <net/if_arp.h>
编码案例:组包获取ip对应mac
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <net/if.h>
#include <netinet/if_ether.h>
#include <netpacket/packet.h>
#include <unistd.h>
#include <sys/ioctl.h>
//#define TARGET_IP "192.168.xxx.xxx"
void get_mac_address(const char *target_ip) {
// 创建原生套接字以发送和接收以太网帧
int sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ARP));
if (sock == -1) {
perror("socket");
return;
}
// 设置发送套接字地址结构
struct sockaddr_ll socket_address;
struct ifreq ifr;
memset(&socket_address, 0, sizeof(struct sockaddr_ll));
socket_address.sll_family = PF_PACKET;
socket_address.sll_protocol = htons(ETH_P_ARP);
// 设置要使用的网络接口名
strncpy(ifr.ifr_name, "ens33", IFNAMSIZ);
if (ioctl(sock, SIOCGIFINDEX, &ifr) == -1) {
perror("ioctl");
close(sock);
exit(2);
}
socket_address.sll_ifindex = ifr.ifr_ifindex;
// 构建以太网帧头部
struct ether_header eth_hdr;
struct ether_arp arp_hdr;
unsigned char broadcast_mac[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
unsigned char my_mac[6] =YOURMAC;
const char *my_ip = "xxx";
memcpy(eth_hdr.ether_dhost, broadcast_mac, 6);
memcpy(eth_hdr.ether_shost, my_mac, 6);
eth_hdr.ether_type = htons(ETH_P_ARP);
// 构建ARP请求包
arp_hdr.arp_hrd = htons(ARPHRD_ETHER);
arp_hdr.arp_pro = htons(ETH_P_IP);
arp_hdr.arp_hln = 6;
arp_hdr.arp_pln = 4;
arp_hdr.arp_op = htons(ARPOP_REQUEST);
memcpy(arp_hdr.arp_sha, my_mac, 6);
inet_pton(AF_INET, my_ip, arp_hdr.arp_spa);
memset(arp_hdr.arp_tha, 0, 6);
inet_pton(AF_INET, target_ip, arp_hdr.arp_tpa);
// 构建完整的以太网帧
unsigned char buffer[sizeof(struct ether_header) + sizeof(struct ether_arp)];
memcpy(buffer, ð_hdr, sizeof(struct ether_header));
memcpy(buffer + sizeof(struct ether_header), &arp_hdr, sizeof(struct ether_arp));
// 发送ARP请求
if (sendto(sock, buffer, sizeof(buffer), 0, (struct sockaddr *)&socket_address, sizeof(struct sockaddr_ll)) == -1) {
perror("sendto");
close(sock);
exit(3);
}
// 接收并解析ARP响应
unsigned char response_buffer[1024];
ssize_t response_len = recv(sock, response_buffer, sizeof(response_buffer), 0);
if (response_len < 0) {
perror("recv");
close(sock);
exit(4);
}
// 解析收到的以太网帧
if (response_len >= sizeof(struct ether_header) + sizeof(struct ether_arp)) {
struct ether_header *received_eth_hdr = (struct ether_header *)response_buffer;
if (ntohs(received_eth_hdr->ether_type) == ETH_P_ARP) {
struct ether_arp *received_arp_hdr = (struct ether_arp *)(response_buffer + sizeof(struct ether_header));
if (ntohs(received_arp_hdr->arp_op) == ARPOP_REPLY) {
// 输出目标IP的MAC地址
printf("MAC Address of %s: %02X:%02X:%02X:%02X:%02X:%02X\n",
target_ip,
received_arp_hdr->arp_sha[0],
received_arp_hdr->arp_sha[1],
received_arp_hdr->arp_sha[2],
received_arp_hdr->arp_sha[3],
received_arp_hdr->arp_sha[4],
received_arp_hdr->arp_sha[5]);
}
}
}
// 关闭套接字
close(sock);
}
int main(int argc, char *argv[]) {
if (argc != 2) {
fprintf(stderr, "Usage: %s <target_ip>\n", argv[0]);
return 1;
}
const char *target_ip = argv[1];
get_mac_address(target_ip);
return 0;
}
运行结果
总结
当涉及ARP(地址解析协议)时,它是IPv4网络中的关键协议,用于将IP地址映射到物理MAC地址。ARP协议帮助设备在局域网内找到其他设备的物理地址,从而确保网络数据包能够正确传递到目标设备。
ARP报文的传输过程包括两个关键步骤:ARP请求和ARP应答。当设备需要将数据包发送到目标IP地址时,它会首先检查本地ARP缓存表,以查找目标IP对应的MAC地址。如果没有找到,设备会广播发送ARP请求,其中包含源MAC和IP地址以及目标IP地址。目标设备接收到请求后,如果它的IP地址匹配目标IP,它会发送ARP应答,其中包含自己的MAC和IP地址,以便请求方可以更新ARP缓存表。
ARP报文包含多个字段,如目标MAC地址、源MAC地址、硬件类型、协议类型、操作码等。这些字段在报文中起到关键作用,确保正确地执行地址解析过程。
为了进一步理解ARP,本文提供了一个使用C语言编写的ARP请求示例代码。该代码展示了构建ARP请求报文的过程,以及如何解析收到的ARP应答报文,从而获取目标IP的MAC地址。