By Sean Reifschneider Date March 2, 2013
Understanding how ARP works can allow you to do many useful things. For example, a machine was recently set up accidentally with the IP address of another machine. This is an hour away, and accessing the system was tested before leaving the location, but after traveling back another machine was responding to that IP. Knowing ARP can allow you to fix this without having to go back to the location.
Outside of the classroom and interview environments, the OSI model network layers boil down mainly to layers 2, 3, and 7. The number of times I've encountered the other layers in the real world over the last several decades amounts to only a handful. For ARP, we are talking about layer 2.
Layer 2 is the level that lower-end switches operate at, and is all about the MAC addresses. The MAC address is an ID, typically assigned by the manufacturer (though usually can be changed by software), which you see next to "HWaddr" if you run "ifconfig". It is a string of 6 pairs of hex digits, usually with the pairs separated by colons, for example: "3c:97:0e:44:be:ef".
The MAC address is how machines on a subnet communicate. When machine A sends packets to another machine on its subnet, it sends it using the MAC address. When sending a packet to a machine on the public Internet, the packet is sent to the MAC address of the router interface that is the default gateway. IP addresses are used to figure out the MAC address to send to using ARP.
ARP stands for Address Resolution Protocol. When you try to ping an IP address on your local network, say 192.168.1.1, your system has to turn the IP address 192.168.1.1 into a MAC address. This involves using ARP to resolve the address, hence its name.
Systems keep an ARP look-up table where they store information about what IP addresses are associated with what MAC addresses. When trying to send a packet to an IP address, the system will first consult this table to see if it already knows the MAC address. If there is a value cached, ARP is not used.
If the IP address is not found in the ARP table, the system will then send a broadcast packet to the network using the ARP protocol to ask "who has 192.168.1.1". Because it is a broadcast packet, it is sent to a special MAC address that causes all machines on the network to receive it. Any machine with the requested IP address will reply with an ARP packet that says "I am 192.168.1.1", and this includes the MAC address which can receive packets for that IP.
In the case where multiple machines have the same IP address, you may get multiple responses. The one that gets placed in the ARP table can vary depending on the networking implementation, how busy hosts are, and how quickly they respond, etc... Once it's in the ARP table, that MAC address is cached and continues to be used until the entry expires or is forcibly cleared. At that point another ARP is done and you may or may not get the same MAC in the ARP table.
On Linux systems, you can display the ARP table with the command "arp -an". For example:
# arp -an | grep 10 ? (10.241.1.114) at 00:25:90:3e:dc:fc [ether] on vlan241 ? (10.252.1.8) at 00:c0:b7:76:ac:19 [ether] on vlan244 ? (10.252.1.9) at 00:c0:b7:76:ae:56 [ether] on vlan244 ? (10.241.1.111) at 00:30:48:f2:23:fd [ether] on vlan241 ? (10.252.1.6) at 00:c0:b7:74:fb:9a [ether] on vlan244 ? (10.241.1.121) at 00:25:90:2c:d4:f7 [ether] on vlan241 [...]
An entry for the IP address 192.168.1.1 can be deleted from the ARP table using the command "arp -d 192.168.1.1". The next time a packet needs to go to that IP, a new ARP negotiation will be done.
If you want to make a specific MAC address be used for an IP, you can use the command: "arp -s 192.168.1.1 [MAC ADDR]".
If you are in a situation where you have two machines that have the same IP address, the above can be used so that you access a specific one. How do you know what the MAC addresses are?
If you are able to access the system, you can find the MAC address by using the "ifconfig" or "ip addr ls" commands. That doesn't help if you are in a remote location and accidentally gave the same IP address to two machines though.
tcpdump is a wonderful tool for this. Open two terminals on a system on the network that has two machines with the same IP. In one, run "tcpdump -lni any arp", and in the other delete the ARP entry with "arp -d [IP ADDRESS]". Now ping that IP address, you should see some ARP packets go by.
For example, running the tcpdump in the background and then doing the arp and ping in another shell instance:
[root@host ~]# tcpdump -lni any arp & ( sleep 1; arp -d 10.0.0.254; ping -c1 -n 10.0.0.254 )  31920 tcpdump: WARNING: Promiscuous mode not supported on the "any" device tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on any, link-type LINUX_SLL (Linux cooked), capture size 96 bytes 17:58:02.155495 arp who-has 10.2.1.224 tell 10.2.1.253 17:58:02.317444 arp who-has 10.0.0.96 tell 10.0.0.253 17:58:02.370446 arp who-has 10.3.1.12 tell 10.3.1.61 PING 10.0.0.254 (10.0.0.254) 56(84) bytes of data. 17:58:02.636895 arp who-has 10.0.0.254 tell 10.0.0.24 17:58:02.637160 arp reply 10.0.0.254 is-at 00:25:90:03:b3:98 64 bytes from 10.0.0.254: icmp_seq=1 ttl=64 time=1.23 ms --- 10.0.0.254 ping statistics --- 1 packets transmitted, 1 received, 0% packet loss, time 0ms rtt min/avg/max/mdev = 1.238/1.238/1.238/0.000 ms
In this case, there is only one system at the MAC address 10.0.0.254, and we can see it in the "is-at" line above. As you can see above, if you are on a busy network or busy machine, you may get a lot of ARP packets and you will have to hunt to find the one you need.
Normally, ARP "is-at" replies, which cause machines to update their ARP tables, are sent in response to an ARP "who-has" request packet. However, if an IP address changes the MAC address it is at, for example if you move a service from one machine to another, other machines on that subnet will continue to cache the old value for some period of time.
You can cause machines on a subnet to update their ARP tables by broadcasting an ARP reply packet which is not in response to a specific request. This is called a "Gratuitous ARP".
You can send a Gratuitous ARP using the "arping" command. Say that your IP address is 172.16.42.161 on interface eth0:
arping -A -I eth0 172.16.42.161
This will send "ARP Reply" packets to the broadcast MAC address on eth0, over and over until you press Control-C. Other machines on the network will update their ARP tables when they see these packets.
An Ethernet "learning bridge" is a device with multiple interfaces, which figures out what MAC addresses are on each of its segments. It will forward packets onto segments that they are destined for. A network switch is a bridge with many ports.
Proxy ARP can produce similar results, by manually publishing ARP entries on one interface for machines on another interface. In this way, machines on one network segment know that they can reach machines on the other segment via this intermediary machine.
This does require that the IP addresses be in the same subnet, of course. Ethernet (at layer 2) doesn't understand routing at all. When a packet is sent to an IP that isn't in a local subnet, the routing table is consulted to find a machine on the local network that can reach the destination network, and packets are sent using the MAC of the router.
I once used this trick to set up a DMZ for a client, with the machine between the segments doing firewalling. These days you also have the option of using "ebtables" to implement firewall rules on an Ethernet bridge, but that wasn't an option when I set up the firewall for this client. Their ISP would only give them 5 usable IPs, so subnetting it and routing was not an option.
To do this, you need to use the "-i" option to "arp" which specifies the interface to publish it on. So you can take an IP address for a machine that is on eth0 interface, and publish it on eth1 using the eth1 MAC address. The "-Ds" option simplifies this by figuring out what MAC address to use:
arp -i eth1 -Ds 10.0.0.1 eth1 pub
You also need to enable IP forwarding and proxy ARP:
echo 1 > /proc/sys/net/ipv4/conf/eth0/proxy_arp echo 1 > /proc/sys/net/ipv4/conf/eth1/proxy_arp echo 1 > /proc/sys/net/ipv4/ip_forward
I've been doing IT work since the early '90s. While I don't often end up having to consult ARP tables or use the "arp" command, understanding ARP makes many networking situations much more clear. It's one of the things you need to understand to be in the top 10% of IT professionals.