ARP:地址解析协议

以太网内部是用MAC地址传输的,ARP就是IP到MAC的映射。

本机的IP和MAC信息:

[winlin@dev6 ~]$ ifconfig
eth1      Link encap:Ethernet  HWaddr 08:00:27:55:0F:09 

在hosts中添加一个地址记录:

vi /etc/hosts

192.168.20.190 winlin002

其中,winlin002的信息:

[winlin@localhost ~]$ /sbin/ifconfig
eth0      Link encap:Ethernet  HWaddr 08:00:27:A4:C1:93  

然后用tcpdump抓包:

sudo tcpdump -i eth1 -e|grep winlin002

用ssh登录到winlin002:

ssh winlin002

这个时候,可以看到tcpdump打出来的消息:

22:01:35.109166 08:00:27:55:0f:09 (oui Unknown) > Broadcast, ethertype ARP (0x0806), length 42: Request who-has winlin002 tell dev6, length 28
22:01:35.110199 08:00:27:a4:c1:93 (oui Unknown) > 08:00:27:55:0f:09 (oui Unknown), ethertype ARP (0x0806), length 60: Reply winlin002 is-at 08:00:27:a4:c1:93 (oui Unknown), length 46
22:01:35.110204 08:00:27:55:0f:09 (oui Unknown) > 08:00:27:a4:c1:93 (oui Unknown), ethertype IPv4 (0x0800), length 74: dev6.46897 > winlin002.ssh: Flags [S], seq 2614233586, win 5840, options [mss 1460,sackOK,TS val 130855853 ecr 0,nop,wscale 5], length 0

第一条是本机(08:00:27:55:0f:09)向以太网广播一条消息,ARP协议,问“who-has winlin002 tell dev6”。

第二条是winlin002(08:00:27:a4:c1:93)回复本机:“Reply winlin002 is-at 08:00:27:a4:c1:93”

第三条就是IP消息了:

08:00:27:55:0f:09> 08:00:27:a4:c1:93, ethertype IPv4 (0x0800), length 74: dev6.46897 > winlin002.ssh

用arp看,多了一条缓存:

[winlin@dev6 ~]$ arp -a
winlin002 (192.168.20.190) at 08:00:27:a4:c1:93 [ether] on eth1

可以删除它:

[winlin@dev6 ~]$ sudo arp -d winlin002
[winlin@dev6 ~]$ arp -a
winlin002 (192.168.20.190) at <incomplete> on eth1
localhost (192.168.20.1) at 28:94:0f:ed:a9:3f [ether] on eth1
localhost (192.168.20.26) at d4:be:d9:a3:51:14 [ether] on eth1
[winlin@dev6 ~]$ 

下面是一个简单的 C 语言 ARP 报文发送程序示例: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <netinet/in.h> #include <arpa/inet.h> #include <sys/socket.h> #include <sys/ioctl.h> #include <net/if.h> #include <net/if_arp.h> #define ARP_REQUEST 1 #define ARP_REPLY 2 struct arp_packet { unsigned short hardware_type; unsigned short protocol_type; unsigned char hardware_size; unsigned char protocol_size; unsigned short opcode; unsigned char sender_mac[6]; unsigned char sender_ip[4]; unsigned char target_mac[6]; unsigned char target_ip[4]; }; void get_mac_address(char *interface, unsigned char *mac) { struct ifreq ifr; int sock = socket(AF_INET, SOCK_DGRAM, 0); strcpy(ifr.ifr_name, interface); ioctl(sock, SIOCGIFHWADDR, &ifr); memcpy(mac, ifr.ifr_hwaddr.sa_data, 6); close(sock); } void get_ip_address(char *interface, unsigned char *ip) { struct ifreq ifr; int sock = socket(AF_INET, SOCK_DGRAM, 0); strcpy(ifr.ifr_name, interface); ioctl(sock, SIOCGIFADDR, &ifr); memcpy(ip, &((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr, 4); close(sock); } void send_arp_request(char *interface, char *target_ip) { int sock = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ARP)); unsigned char source_mac[6]; get_mac_address(interface, source_mac); unsigned char source_ip[4]; get_ip_address(interface, source_ip); unsigned char broadcast_mac[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; unsigned char target_ip_addr[4]; inet_aton(target_ip, (struct in_addr *)target_ip_addr); struct arp_packet request; request.hardware_type = htons(ARPHRD_ETHER); request.protocol_type = htons(ETH_P_IP); request.hardware_size = 6; request.protocol_size = 4; request.opcode = htons(ARP_REQUEST); memcpy(request.sender_mac, source_mac, 6); memcpy(request.sender_ip, source_ip, 4); memset(request.target_mac, 0, 6); memcpy(request.target_ip, target_ip_addr, 4); struct sockaddr_ll socket_address; socket_address.sll_family = PF_PACKET; socket_address.sll_protocol = htons(ETH_P_ARP); socket_address.sll_ifindex = if_nametoindex(interface); socket_address.sll_hatype = ARPHRD_ETHER; socket_address.sll_pkttype = PACKET_BROADCAST; socket_address.sll_halen = ETH_ALEN; memcpy(socket_address.sll_addr, broadcast_mac, 6); sendto(sock, &request, sizeof(request), 0, (struct sockaddr *)&socket_address, sizeof(socket_address)); close(sock); } int main(int argc, char **argv) { if (argc != 3) { printf("Usage: %s <interface> <target_ip>\n", argv[0]); return 1; } send_arp_request(argv[1], argv[2]); printf("ARP request sent to %s\n", argv[2]); return 0; } ``` 这个程序使用了 Linux 下的原始套接字接口和 ioctl 函数来获取本机的 MAC 地址和 IP 地址,并利用这些信息构造并发送了一个 ARP 请求报文。需要注意的是,发送 ARP 报文需要有 root 权限。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

winlinvip

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值