ARP — Address Resolution Protocol

Mapping IPv4 addresses to MAC addresses inside a subnet. The cache, the request/reply, and the spoofing risk.

Building Block Foundational
8 min read
arp network-layer layer-2 security

What it is#

ARP (Address Resolution Protocol, RFC 826, 1982) is the small but essential glue that lets IPv4 ride on Ethernet. When a host wants to send an IP datagram to another host on the same subnet, it knows the destination’s IP address but the Ethernet card only takes a MAC address. ARP is how the host asks the network “who has IP 192.0.2.10? Tell 192.0.2.5,” and gets the answer “192.0.2.10 is at 52:54:00:ab:cd:ef.”

ARP runs directly over Ethernet — it is not encapsulated in IP. The Ethertype is 0x0806. Each host maintains an ARP cache (ip neigh on Linux, arp -a on macOS / Windows) mapping IP to MAC with a TTL of a few minutes; this avoids broadcasting a request for every packet.

ARP is IPv4-only. IPv6 replaces it with Neighbor Discovery (NDP), which runs over ICMPv6 and uses multicast instead of broadcast. The conceptual job is identical — resolve a Layer-3 address to a Layer-2 address on the same link.

When to use it#

You never call ARP directly from application code — the OS does it transparently when you send() on a TCP socket and the destination is local. You think about ARP in three operational contexts:

  • Debugging “can’t reach the gateway”. ping to the default route fails; ip neigh shows FAILED for the gateway. Either the gateway is down, the cable is unplugged, or VLAN tagging is wrong.
  • Spoofing investigations. Two hosts claiming the same IP, or a sudden change in the MAC behind a gateway IP, is either a flaky host or an active attack (ARP poisoning).
  • High-availability failover. VRRP / HSRP / Keepalived send Gratuitous ARP when a virtual IP fails over to a backup router, so neighbors update their caches and start sending to the new MAC immediately.

You also see ARP behaviour on cloud platforms: AWS, Azure, and GCP intercept ARP at the hypervisor and rewrite it, which is why “secondary IPs” require explicit configuration in the cloud control plane — naive ARP would not reach the underlying fabric.

How it works#

The packet#

Ethernet frame
+----------------+----------------+----------+
| dst MAC (ff..) | src MAC | type 0806|
+----------------+----------------+----------+
ARP payload
+--------+--------+----+----+--------+
| HTYPE | PTYPE | HLN| PLN| OPER |
+--------+--------+----+----+--------+
| Sender MAC (6 bytes) |
+-----------------------------------+
| Sender IP (4 bytes) |
+-----------------------------------+
| Target MAC (6 bytes) |
+-----------------------------------+
| Target IP (4 bytes) |
+-----------------------------------+

HTYPE = 1 (Ethernet), PTYPE = 0x0800 (IPv4), HLN = 6, PLN = 4, OPER = 1 (request) or 2 (reply).

Request and reply sequence#

Host A: 192.0.2.5 / MAC aa:aa:aa:aa:aa:aa
Host B: 192.0.2.10 / MAC bb:bb:bb:bb:bb:bb
Step 1: A wants to send to 192.0.2.10. ARP cache miss.
A broadcasts:
src MAC aa:aa:aa:aa:aa:aa
dst MAC ff:ff:ff:ff:ff:ff (broadcast)
ARP request:
sender = (aa:aa:..., 192.0.2.5)
target = (00:00:00:00:00:00, 192.0.2.10)
OPER = 1
Step 2: Every host on the LAN sees the broadcast.
Only B (the one with 192.0.2.10) replies.
B unicasts back to A:
src MAC bb:bb:bb:bb:bb:bb
dst MAC aa:aa:aa:aa:aa:aa
ARP reply:
sender = (bb:bb:..., 192.0.2.10)
target = (aa:aa:..., 192.0.2.5)
OPER = 2
Step 3: A caches the mapping (192.0.2.10 -> bb:bb:bb:bb:bb:bb)
and sends the original IP datagram.
Step 4: B opportunistically caches A's mapping from the request
(the request also carries sender IP/MAC, so it is a free entry).

Subsequent packets between A and B use the cached MAC and skip ARP entirely until the cache entry ages out (Linux default: ~60 seconds reachable, then re-probe).

Gratuitous ARP#

A host announces its own mapping unsolicited — useful at boot (“I am 192.0.2.5 at aa:.., update your caches”) and at failover (a VRRP master telling the LAN that the virtual IP 192.0.2.1 now resolves to the master’s real MAC). The packet is an ARP request where sender IP == target IP.

Proxy ARP#

A router answers ARP requests for IPs that are not its own, on behalf of hosts on a different segment. Useful when a host is configured with a /16 but the network is split into smaller subnets — the gateway pretends to be every remote host. Generally considered a hack; routing should solve this instead.

ARP cache lifecycle (Linux)#

state meaning
NONE no entry
INCOMPLETE request sent, no reply yet
REACHABLE recently confirmed (default 30s, randomised to 60s)
STALE entry exists but unconfirmed; will re-probe before next use
DELAY waiting briefly for confirmation
PROBE active probe in flight
FAILED probes exhausted, entry effectively dead

ip neigh show exposes the state. ip neigh flush dev eth0 wipes it after a network change.

Variants#

  • Standard ARP (RFC 826). Broadcast request, unicast reply. The default for IPv4-on-Ethernet.
  • Gratuitous ARP. Self-announcement used at boot, IP-change, and HA failover. Critical for VRRP / Keepalived.
  • Proxy ARP (RFC 1027). Router answers ARP for off-segment IPs. Useful for backward-compatibility hacks; generally avoid.
  • Reverse ARP (RARP). Historic — diskless workstations asked “what’s my IP?” by sending their MAC. Replaced by BOOTP and DHCP.
  • InARP. Frame-Relay/ATM variant — asks “what IP is at the other end of this PVC?” Obsolete with modern transport.
  • NDP — Neighbor Discovery (IPv6). ICMPv6 Types 135/136 (Solicitation/Advertisement). Uses solicited-node multicast (ff02::1:ffXX:XXXX) instead of broadcast — only hosts whose IPv6 last-24-bits match get the request. Drastically reduces broadcast load on busy links.

Trade-offs#

ARP (IPv4) — simple, decades of tooling, every Ethernet device understands it, broadcast model trivially discoverable. Broadcast cost scales linearly with LAN size; no authentication, so trivially spoofable by anyone on the segment.
NDP (IPv6) — multicast-based (less broadcast cost), unified with router discovery and PMTUD, optional cryptographic protection (SEND, RFC 3971 — rarely deployed). Larger packets, ICMPv6 dependency means firewall mistakes break the LAN, harder to debug than ARP for engineers used to v4.

Other tensions:

  • Cache freshness vs traffic cost. Aggressive re-probes catch failovers quickly but generate broadcast load. Linux default gc_stale_time is 60s; tighter is rare.
  • Trust model. ARP has none. Any host on the LAN can claim any IP. Dynamic ARP Inspection (DAI) on managed switches binds ARP replies to known IP-MAC pairs from DHCP snooping. Required in untrusted-tenant LANs.
  • Broadcast amplification. On a /16 flat LAN, every ARP request hits 65k hosts. Most modern designs limit broadcast domains to /24 or smaller and bridge upward with routing.
Why does ARP not use IP?

Chicken-and-egg. ARP exists because you do not yet know how to send an IP packet to the destination — you do not have its MAC. If ARP itself were carried over IP, you would need ARP to send the ARP. So it runs directly over the link layer with its own Ethertype. The same reason DHCP DISCOVER uses broadcast at the IP layer — you do not yet have an IP, so you cannot unicast.

Common pitfalls#

  • ARP cache poisoning. An attacker on the LAN sends Gratuitous ARP claiming the gateway’s IP with their own MAC. Victims start sending the attacker’s MAC; the attacker forwards to the real gateway and reads everything. Mitigations: Dynamic ARP Inspection (DAI), static ARP entries for critical hosts, 802.1X with port-based authentication.
  • Duplicate IP detection. Two hosts with the same IP cause flapping cache entries — one host gets traffic for a while, then the other. Hard to spot without arping or switch CAM analysis.
  • Believing ARP works across routers. It does not. ARP is link-local. Cross-subnet traffic is forwarded by a router which performs ARP on each side independently.
  • Forgetting Gratuitous ARP after IP change. Move an IP from interface A to interface B without sending Gratuitous ARP and the rest of the LAN holds the stale entry until it expires — connectivity is broken for up to a minute.
  • Hard-coded static ARP without monitoring. Static entries do not age out; if the peer changes MAC (NIC swap, VM migration) the static entry is now wrong forever.
  • ARP queue overflow during a storm. A burst to many unresolved destinations queues many ARP requests; Linux defaults limit the unresolved queue, after which socket() calls fail with ENOBUFS. Watch /proc/net/stat/arp_cache.
  • Cloud surprise. AWS, GCP, and Azure intercept ARP at the hypervisor. Adding a secondary IP without telling the control plane means no ARP reply ever flows.
  • Confusing ARP with DNS. DNS resolves names to IPs (control plane, hierarchical, cacheable for minutes-to-hours). ARP resolves IPs to MACs (link-local, no hierarchy, cached for seconds). Different layers, different lifetimes.
Search ESC

Keyboard shortcuts

Shortcuts are disabled while typing in inputs.