# Address resolution protocol

Het address resolution protocol (ARP) is een protocol binnen TCP/IP dat computers - die allemaal op hetzelfde subnetwerk (meer specifiek: LAN) zijn aangesloten - in staat stelt het unieke hardware-adres (MAC-adres) van een andere PC binnen dat netwerk te leren, aan de hand van het IP-adres van deze PC. De implementatie van ARP is gebaseerd op de standaard beschreven in RFC 826 uit 1982.

## Techniek

Stel dat computer A verbinding wil maken met computer B, waarvan het IP-adres bekend is bij computer A maar zijn hardware-adres niet. Computer A zendt daarvoor een ARP-bericht op het netwerk. Dit ARP-bericht wordt uitgestuurd als een broadcast. Een broadcast houdt in dat een ontvangstadres (laag 2) gebruikt wordt dat aangeeft dat het bericht feitelijk door iedere op dat netwerk aangesloten computer moet worden ontvangen. Het ARP-bericht bevat het IP-adres van computer B. Uitsluitend computer B zal zijn eigen IP-adres herkennen, en zal op grond daarvan het bericht beantwoorden, met daarin zijn hardware-adres (ook wel MAC-adres genoemd). Op dat moment is het ARP-protocol klaar want A heeft het hardware-adres van B.
Er is een vergelijking te trekken met: je moet contact leggen met een 'Hans' uit een groep onbekenden. Je zorgt dat je midden in de groep gaat staan en roept luid: "Wie heet er Hans?". De persoon die reageert met: 'Dat ben ik!', dat is je contactpersoon. Net zoals met netwerken treedt er een probleem op als er meer mensen zijn die Hans heten. De kans dat er twee dezelfde hardware-adressen aangesloten zijn is echter vrij klein, Ethernet dat veel gebruikt wordt kent hardwareadressen van 6 bytes (48 bits) dus er zijn 2$^{48}$ = 281474976710656 (ruim 281 biljoen) verschillende adressen mogelijk. Over het algemeen worden de eerste drie bytes gebruikt als leverancier-ID en de laatste drie als een volgnummer per leverancier.

### Voorbeeld van ARP-communicatie

Hieronder een voorbeeld van een complete ARP-transactie: dus het ARP Request en het ARP Reply. Voor dit voorbeeld gebruiken we de volgende gegevens:
    De aanvragende pc met als IP-adres 192.168.1.11 en ethernet-MAC-adres 00:24:d7:c9:5f:f8 (=Intel wifi-MAC-adres)
    De host/server heeft als IP-adres 192.168.1.10 en een ethernet-MAC-adres 00:16:ce:29:81:22 (=HonHai Precision Industries)
Elke netwerkkaart (NIC) bouwt een tabel op met daarin de IP adressen in je lokale IP-subnet en de bijbehorende MAC-adressen. Als een computer verbinding wil maken met een andere machine zoekt hij in deze ARP-tabel of hij het benodigde MAC-adres van de bestemming al kent. Onder Windows kan je de inhoud van de ARP-tabel opvragen via arp -a. In deze tabel staat het IP-adres, het bijbehorende MAC-adres en wat voor type het is of status van de entry (dynamic, static, incomplete etc). Alle entries die de NIC geleerd heeft via een ARP request en het bijbehorende antwoord staan in de tabel als 'dynamic'. De informatie wordt een bepaalde tijd vastgehouden en als die tijd verstrijkt dan wordt de vermelding gewist. Als voor het verstrijken van deze tijd communicatie is met betreffende bestemming dan wordt de timer gereset (en als de communicatie mislukt dan kan de status eveneens wijzigen).
We gaan er in dit voorbeeld van uit dat de aanvragende pc het adres van de server nog niet in zijn ARP-tabel heeft. Vervolgens wil een applicatie verbinding maken met een host. Allereerst bepaalt de netwerklaag van de IP-stack dat de host in zijn eigen IP-subnet is: hij moet de host dus via zijn eigen LAN-segment kunnen bereiken. Om te leren op welk hardwareadres (MAC-adres) het IP-adres 192.168.1.10 te vinden is stuurt de NIC een ARP Request Broadcast. Het broadcastpakket wat gestuurd wordt bevat de volgende gegevens:
    source MAC: 00:24:d7:c9:5f:f8, source IP: 192.168.1.11
    destination MAC: ff:ff:ff:ff:ff:ff (broadcast), destination IP: 192.168.1.10
Als je het pakket analyseert met -bijvoorbeeld- Wireshark dan is te zien dat het vertaald wordt met: Who has 192.168.1.10? tell 192.168.1.11
Omdat het een ethernetbroadcast is, moet elke NIC die het ontvangt het frame verwerken. De TCP/IP-stack van elke computer die het frame heeft ontvangen gaat vervolgens op IP-niveau kijken of het voor hem is. Hij checkt of hij zelf de NIC is voor 192.168.1.10: indien niet dan negeert hij de broadcast, als hij het wel is stuurt hij een unicastpakket terug:
    source MAC: 00:16:ce:29:81:22, source IP: 192.168.1.10
    destination MAC: 00:24:d7:c9:5f:f8, destination IP: 192.168.1.11
en dat wordt door Wireshark vertaald als 192.168.1.10 is at 00:16:ce:29:81:22' Vervolgens zet de host deze informatie in zijn eigen ARP-tabel en na ontvangst door de pc die het ARP-request verstuurde zet hij de informatie in zijn MAC-tabel. Dus als je een arp -a doet op de pc zie je: 192.168.1.10 00-16-ce-29-81-22 dynamic
In de ARP-tabel ziet men naast de geleerde (dynamic) adressen ook een paar vaste (static) adressen staan die in de tabel worden gezet op het moment dat de IP-stack wordt opgebouwd:
Interface: 192.168.1.11 --- 0xf
Wat te zien is, is dat het IP-subnet-broadcastadres 192.168.1.255 wordt vertaald naar het ethernetbroadcastadres en er staan 4 entries in voor Multicast waarbij de IP-multicastadressen vertaald worden naar vaste ethernetmulticastadressen. Het is overigens mogelijk om handmatig ARP-entries in de tabel te zetten: soms kan dit handig zijn voor troubleshooting-activiteiten: als je bijvoorbeeld een duplicaat-IP-adres op je netwerk hebt en je wilt verbinding maken met een van die machines (bijvoorbeeld om het IP-adres van die machine te wijzigen) dan kun je het MAC-adres van de machine waarmee je verbinding wilt maken handmatig in de ARP-tabel zetten via: arp -s <ip adres> <MAC adres> dus bijvoorbeeld: arp -s 192.168.1.10 00-16-ce-29-81-22

### Een ARP-conversatie

Behalve de bovenstaande data staat er ook nog andere informatie in het verzonden frame. Een ARP-Request/Reply-sessie is vrij eenvoudig van opzet. Als je het frame byte voor byte analyseert zie je het volgende:
Een ARP-ethernetframe is 42 bytes lang (zowel request als reply) en heeft achtereenvolgens de volgende velden:

### Details van ARP-request

De ethernet-frameheader -destination MAC (in het request dus allemaal '1' ofwel ff:ff:ff:ff:ff:ff -source MAC: in ons voorbeeld dus: 00:24:d7:c9:5f:f8 -type: ARP hex: 08:06 -trailer: padding om aan de minimum grootte van een ethernet-frame te voldoen
En daarna volgt de datalinkinhoud: -de data voor een ARP request of reply ---hardware-type: ethernet (hex: 00:01) ---protocol type: IP (hex: 08:00) ---hardware size: 6 (lengte van het MAC adres, bij ethernet dus altijd 6 bytes) hex: 06 ---protocol size: 4 (indien het een IPv4 ipadres is zoals in ons voorbeeld): hex: 04 ---opcode: voor ARP request 1 (hex: 00:01)
---sender MAC adres: is hetzelfde als het source MAC adres in de bovengenoemde frame-header 00:24:d7:c9:5f:f8 ---sender IP adres: de HEX weergave van het IP adres, in ons voorbeeld: c0:a8:01:0b (=192.168.1.11) ---target MAC: in het request allemaal 0 (00:00:00:00:00:00)
---target IP adres: de HEX weergave van het IP adres, in ons voorbeeld: c0:a8:01:0a (=192.168.1.10)

### Details van ARP-reply

In geval van het antwoord: -destination MAC (in het antwoord: 00:24:d7:c9:5f:f8) -source MAC: in ons voorbeeld dus: 00:16:ce:29:81:22 -type: ARP hex: 08:06 -trailer: padding om aan de minimum grootte van een ethernetframe te voldoen
-de data voor een ARP request of reply ---hardware-type: ethernet (hex: 00:01) ---protocol type: IP (hex: 08:00) ---hardware size: 6 (lengte van het MAC adres, bij ethernet dus altijd 6 bytes) hex: 06 ---protocol size: 4 (indien het een IPv4 ipadres is zoals in ons voorbeeld): hex: 04 ---opcode: voor ARP reply: 2 (hex: 00:02) ---sender MAC adres: is hetzelfde als het source MAC adres in de bovengenoemde frame-header 00:16:ce:29:81:22 ---sender IP adres: de HEX weergave van het IP adres, in ons voorbeeld: c0:a8:01:0a (=192.168.1.10) ---target MAC: 00:24:d7:c9:5f:f8)
---target IP adres: de HEX-weergave van het IP adres, in ons voorbeeld: c0:a8:01:0b (=192.168.1.11)
Omdat alle NIC's in het netwerk alle broadcasts moeten verwerken is het van belang dat dit heel snel kan gebeuren en weinig CPU-belasting genereert. De meeste NIC-drivers zullen een ARP-request helemaal 'on board' kunnen uitvoeren en dus geen of extreem weinig beslag leggen op de CPU van betreffende server of werkstation. Omdat een ARP-requestframe een heel eenvoudige vaste structuur heeft kan dat ook eenvoudig: de lengte staat altijd vast en alle benodigde informatie om een ARP-request te kunnen verwerken is lokaal op de NIC bekend. Als dat niet het geval zou zijn dan zou de NIC voor elke binnenkomende broadcast een interrupt naar de CPU van de computer moeten sturen, vervolgens zou dan de CPU het ARP-request moeten verwerken, eventueel data ophalen uit het werkgeheugen enzovoorts: dit is ongewenst. Bij de definitie van het ARP-protocol in 1982 waren CPU's veel minder krachtig dan nu en was het van belang om deze zo efficiënt mogelijk te gebruiken.

## Misbruik van het ARP-protocol

Dit wordt ook wel ARP poisoning genoemd (ARP-vergiftiging).
Doordat het ARP-protocol staatloos is, is het mogelijk dit te misbruiken om zo het internetverkeer binnen een lokaal netwerk te verkrijgen (sniffen).

### Hoe gaat dit in zijn werk

    Gegeven: je hebt twee hosts, en een gateway (weg naar het internet).
   * De eerste host heeft IP-adres 1 en MAC-adres A
   * De tweede host heeft IP-adres 2 en MAC-adres B
   * De gateway heeft IP-adres 3 en MAC-adres C
    Stel nu: de eerste host wil al het internetverkeer van de tweede host verkrijgen.
    Hiervoor doet de eerste host het volgende:
   * verstuurt een ARP-reply naar de gateway, met bron-IP-adres 2 en bron-MAC-adres A
   * verstuurt een ARP-reply naar de tweede host, met bron-IP-adres 3 en bron-MAC-adres A
    Resultaat: Host2 denkt dat host1 de gateway is, en de gateway denkt dat host1 host2 is. Nu wordt alle verkeer tussen de tweede host en het internet naar host 1 gestuurd. Vervolgens stuurt host 1 alle traffic door naar de juiste host of gateway.