Learn ARP with arpend command
Quoted from https://mp.weixin.qq.com/s?__biz=MzkxMTMxNjQ0NQ==&mid=2247483685&idx=1&sn=c3d27891c3226f35b21a5ba052fa38bb&chksm=c11f4597f668cc811aaf5db73da6e8506efedb0318f9e1a37b56cdeb84dc3d1a01b01614da19#rd
The task of ARP (Address Resolution Protocol) is to resolve IP address (network layer address) to MAC address (link layer address). This paper first briefly introduces the use of arpend command, then analyzes the format of ARP packet (ARP packet=ARP packet) through tcpdump and Wireshark, and finally analyzes the source code of arpend command to see how to send and receive ARP packet.
1. Install arpend command
When experimenting with ARP, the easiest tool to think of is the ARP command. However, the ARP command can only operate on the ARP table (Ref https://github.com/ecki/net-tools/blob/master/arp.c#L785 ), ARP query packets cannot be sent to any IP address. Fortunately, there is also the arpend command to make up for the deficiency of the ARP command.
The installation method of arpend command is very simple. In Ubuntu, you can install it through the following commands:
# apt install vzctl # arpsend Usage: arpsend <-U -i <src_ip_addr> | -D -e <trg_ip_addr> [-e <trg_ip_addr>] ...> [-c <count>] [-w <timeout>] interface_name
In order to debug with gdb, you can download the source code of vzctl and compile it manually with the - O0 -ggdb3 compilation option:
# apt source vzctl # cd vzctl-4.9.4 # ./configure CFLAGS="-O0 -ggdb3" --without-ploop --without-cgroup # make
2. Send ARP query packet
After installing the arpend command, send the ARP query packet to the specified IP address through the following command:
# arpsend -D -e 172.28.128.2 enp0s8 -v arpsend: got addresses hw='08:00:27:84:bc:b0', ip='172.28.128.3' arpsend: send packet: eth '08:00:27:84:bc:b0' -> eth 'ff:ff:ff:ff:ff:ff'; arp sndr '08:00:27:84:bc:b0' '172.28.128.3'; request; arp recipient 'ff:ff:ff:ff:ff:ff' '172.28.128.2' arpsend: recv unknown packet eth '08:00:27:84:bc:b0' -> eth 'ff:ff:ff:ff:ff:ff'; arp sndr '08:00:27:84:bc:b0' '172.28.128.3'; request; arp recipient 'ff:ff:ff:ff:ff:ff' '172.28.128.2' arpsend: recv packet eth '08:00:27:bf:03:bd' -> eth '08:00:27:84:bc:b0'; arp sndr '08:00:27:bf:03:bd' '172.28.128.2'; reply; arp recipient '08:00:27:84:bc:b0' '172.28.128.3' arpsend: 172.28.128.2 is detected on another computer : 08:00:27:bf:03:bd
The parameter - D -e needs to be used together to send ARP query packets to the target IP address specified by - E- The v parameter is used to start the debug log. Enp0s8 indicates that ARP query packets should be sent from the network card enp0s8 (next, tcpdump is also used to capture the traffic on the network card).
# ifconfig enp0s8 enp0s8: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 172.28.128.3 netmask 255.255.255.0 broadcast 172.28.128.255 inet6 fe80::a00:27ff:fe84:bcb0 prefixlen 64 scopeid 0x20<link> ether 08:00:27:84:bc:b0 txqueuelen 1000 (Ethernet)
2.1. Structure of ARP packet
Next, let's start tcpdump and then execute arpend to grab ARP packets.
# tcpdump "arp" -vvvv -ttt -i enp0s8
Execute arpend - D - e 172.28.128.2 enp0s8 again, and you can see the tcpdump output:
00:00:00.000000 ARP, Ethernet (len 6), IPv4 (len 4), Request who-has 172.28.128.2 (Broadcast) tell 172.28.128.3, length 46 00:00:00.000322 ARP, Ethernet (len 6), IPv4 (len 4), Request who-has 172.28.128.2 (Broadcast) tell 172.28.128.3, length 46 00:00:00.000008 ARP, Ethernet (len 6), IPv4 (len 4), Reply 172.28.128.2 is-at 08:00:27:bf:03:bd (oui Unknown), length 46 00:00:00.000012 ARP, Ethernet (len 6), IPv4 (len 4), Reply 172.28.128.2 is-at 08:00:27:bf:03:bd (oui Unknown), length 46
Import into Wireshark:
We can draw the following conclusions from the above figure:
- Address Resolution Protocol (request):
- The ARP query packet contains the IP address and MAC address of the requesting host (the penultimate lines 3 and 4)
- The ARP query packet uses the MAC broadcast address (the penultimate line, target MAC address: Broadcast (FF: FF: FF: FF: FF: FF: FF))
- Opcode: request (1) indicates that this ARP group is a query request. The format of query grouping and response grouping of ARP is the same, but it is distinguished by this field
- Ethernet Part II:
- The Target MAC address is also a Mac broadcast address, which is consistent with the Target MAC address in ARP
ARP packet is encapsulated in Ethernet frame, and Ethernet frame has a Type field, which indicates what network protocol is adopted by the upper layer. The value of this field is usually Type: IPv4 (0x0800), because IPv4 protocol is the mainstream protocol of the upper network layer of Ethernet (data link layer). However, in the Ethernet frame encapsulated with ARP packet, the value of this field is Type: ARP (0x0806), which indicates that the "upper layer" protocol of Ethernet is ARP and needs to be processed by ARP module. So the problem is, after the ARP module has processed the ARP packet, which upper layer protocol / module should be handed over to continue processing?
The answer is in the Protocol type: IPv4 (0x0800) field of ARP packet. Originally, it was to be handled by IPv4 protocol / module. However, there is still a question here. According to section 6.4.1 of the seventh edition of computer network top-down method:
Original text:... And (because of the broadcast address) each adapter passes the ARP packet within the frame up to its ARP module Each of these ARP modules checks to see if its IP address matches the destination IP address in the ARP packet. The one with a match sends back to the querying host a response ARP packet with the desired mapping.
And (due to the broadcast address) each adapter passes up the ARP packet in the frame to the ARP module. Each of these ARP modules checks whether its IP address matches the destination IP address in the ARP packet. The matching one sends back a response ARP packet with the desired mapping to the query host.
Instead of checking the IP Protocol / module, the ARP module should check whether the target IP address matches the IP address of the local network card. So what's the use of the Protocol type field in ARP grouping (I'm afraid I have to find the answer from RFC826)?
Finally, let's look at the format of ARP response packet:
The query packet and response packet of ARP have the same format, but Opcode: reply (2) indicates that it is a response, and sender MAC address: pcscopu_ BF: 03: BD (08:00:27: BF: 03: BD) is who has 172.28.128.2? Answer to tell 172.28.128.3.
2.2. Source code analysis of arpend command
Next, let's briefly analyze the source code of arpend command to see how to directly send a packet at the data link layer (some people think ARP belongs to the network layer).
Source code: https://github.com/blueboxgroup/vzctl/blob/master/src/arpsend.c
int main(int argc, char** argv) { // ... parse_options (argc, argv); // Special treatment for IPv6, because IPv6 no longer uses ARP, but uses ICMPv6 to send neighbor discovery messages sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ARP)); // ... if (init_device_addresses(sock, iface) < 0) exit(EXC_SYS); create_arp_packet(&pkt); // ... sender(); while(1) { u_char packet[4096]; struct sockaddr_ll from; socklen_t alen = sizeof(from); int cc; cc = recvfrom(sock, packet, sizeof(packet), 0, (struct sockaddr *)&from, &alen); // ... recv_pack(packet, cc, &from); // recv_ The pack will call finish() to exit the loop } exit(EXC_OK); }
The overall process is relatively clear (the part of timeout signal processing is omitted):
- Parsing command line parameters
- When creating a socket, note that the parameters here are different from those used when creating a TCP/UDP socket
- Call init_device_addresses() resolves the network card name in the form of "eth0" and "enp0s8", and initializes the global variable struct sockaddr_ll iaddr;
- Create an ARP group, that is, fill in the global variable struct arp_packet pkt; Fields of
- Send ARP packet
- Receive ARP packet
There are several interesting points in the code:
sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ARP));, Eth among them_ P_ ARP is defined in < Linux / if_ ether. h>:
#define ETH_P_ARP 0x0806 /* Address Resolution packet */
0x0806 is the value of Ethernet frame Type field. Remember the value of the third parameter of socket() when creating a TCP/UDP socket?
The Ethernet frame encapsulating the ARP packet is defined in the structure struct ARP_ The fields in packet {correspond to those in Wireshark one by one. The macro ETH_ALEN and IP_ADDR_LEN are defined as follows:
// <linux/if_ether.h> #define ETH_ALEN 6 /* Octets in one ethernet addr */ // arpsend.c #define IP_ADDR_LEN 4
At the end of the article, another question is raised. What happens if arpend the IP address in another network segment? The answer is given in section 6.4.1 of the seventh edition of computer network top-down method, but it seems to be inconsistent with arpend's behavior.
3. Reference
Section 6.4.1 of computer network top-down method Seventh Edition
Section 5.3 of graphical TCP/IP version 5
RFC 826 https://datatracker.ietf.org/doc/html/rfc826
RFC 5227 https://datatracker.ietf.org/doc/html/rfc5227