Build an ARP Simulator with Python#
Address Resolution Protocol (ARP) is a vital component of local network communication. It helps devices find the hardware (MAC) address of a device based on its IP address. In this blog post, we’ll dive into an ARP simulator project that provides a client-server model to simulate ARP processes. This tool is an excellent resource for learning about ARP and network programming.
You can view the GitHub repository for this project here:
ARP Server Implementation in Python#
This Python script demonstrates a simple ARP (Address Resolution Protocol) server that listens for incoming connections and responds to ARP requests. The server maintains a predefined dictionary of IP addresses and their corresponding MAC addresses. When a client sends an IP address to the server, it looks up the IP in the dictionary and returns the associated MAC address. If the IP address is not found in the dictionary, it responds with “Not Found”.
Key Components:
Network Dictionary: A dictionary named
NETWORK
is defined at the beginning of the script. This dictionary contains IP addresses as keys and their corresponding MAC addresses as values.Server Setup: The server is configured to listen on
127.0.0.1
(localhost) and port65432
. It uses the socket library to create a TCP socket and bind it to the specified IP address and port.Listening for Connections: The server starts listening for incoming connections. When a connection is established, it accepts the connection and enters a loop to continuously receive and respond to ARP requests from the client.
Handling ARP Requests: When the server receives an IP address from the client, it checks the
NETWORK
dictionary for the corresponding MAC address. If found, it sends the MAC address back to the client. If not, it responds with"Not Found"
.Continuous Operation: The server runs indefinitely, waiting for incoming connections and responding to ARP requests.
import socket
# Network dictionary
NETWORK = {
'192.168.1.1': '00:0A:95:9D:68:16',
'192.168.1.2': '00:0A:95:9D:68:17',
'192.168.1.3': '00:0A:95:9D:68:18',
'192.168.1.4': '00:0A:95:9D:68:19',
'192.168.1.5': '00:0A:95:9D:68:1A',
'192.168.1.6': '00:0A:95:9D:68:1B',
'192.168.1.7': '00:0A:95:9D:68:1C',
'192.168.1.8': '00:0A:95:9D:68:1D',
'192.168.1.9': '00:0A:95:9D:68:1E',
'192.168.1.10': '00:0A:95:9D:68:1F',
}
SERVER_IP = '127.0.0.1'
SERVER_PORT = 65432
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.bind((SERVER_IP, SERVER_PORT))
s.listen()
print("ARP server is listening...")
# Keep the server running
while True:
conn, addr = s.accept()
with conn:
print('Connected by', addr)
while True:
ip = conn.recv(1024).decode('utf-8')
if not ip: break
mac = NETWORK.get(ip, None)
response = mac if mac else 'Not Found'
print(f"Received ARP request for IP: {ip}. Responded with: {response}")
conn.sendall(response.encode('utf-8'))
ARP Client Implementation in Python#
This Python script demonstrates a simple ARP (Address Resolution Protocol) client that interacts with the previously implemented ARP server. The client sends an IP address to the server, requests the corresponding MAC address, and updates its local ARP table based on the server’s response.
Key Components:
Server Configuration: The client is configured to connect to the ARP server running on
127.0.0.1
(localhost) and port65432
.ARP Table Initialization: The client maintains a local ARP table, which is initially empty. This table stores IP addresses as keys and their corresponding MAC addresses as values.
User Input: The client prompts the user to enter an IP address for which the MAC address is required.
Communication with ARP Server: The client creates a TCP socket connection to the server, sends the IP address, and waits for the server’s response. The server responds with the corresponding MAC address or
"Not Found"
if the IP address is not in its dictionary.Updating ARP Table: Upon receiving the MAC address from the server, the client updates its local ARP table. If the MAC address is not found, it informs the user accordingly.
Continuous Operation: The client continuously prompts the user for IP addresses and updates the ARP table based on server responses.
import socket
SERVER_IP = '127.0.0.1'
SERVER_PORT = 65432
ARP_TABLE = {}
print("Initial ARP Table:", ARP_TABLE)
while True:
ip = input("Enter IP to ARP for: ")
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect((SERVER_IP, SERVER_PORT))
s.sendall(ip.encode('utf-8'))
mac = s.recv(1024).decode('utf-8')
mac = None if mac == 'Not Found' else mac
if mac:
ARP_TABLE[ip] = mac
print(f"Received ARP reply: {ip} is at {mac}")
else:
print(f"No ARP Reply for {ip}")
print("Current ARP Table:", ARP_TABLE)
How to run the code#
In order to run this code, you need to open both files up in pycharm or vscodes and run the server first and then the client. The server will be running in the background and the client will be sending requests to the server. Then you will interact within the client side to get the MAC address of the IP address you provide.
How the output will look:#
Here is a sample of the output from running the code, as you can see the table is updated each time you provide an IP address and the MAC address is found. Or if the IP address isn’t found, it repsonds with not found
and the table remains the same.
Client Output
Initial ARP Table: {}
Enter IP to ARP for: 192.168.1.1
Received ARP reply: 192.168.1.1 is at 00:0A:95:9D:68:16
Current ARP Table: {'192.168.1.1': '00:0A:95:9D:68:16'}
Enter IP to ARP for: 192.168.1.2
Received ARP reply: 192.168.1.2 is at 00:0A:95:9D:68:17
Current ARP Table: {'192.168.1.1': '00:0A:95:9D:68:16', '192.168.1.2': '00:0A:95:9D:68:17'}
Enter IP to ARP for: 192.168.0.0
No ARP Reply for 192.168.0.0
Current ARP Table: {'192.168.1.1': '00:0A:95:9D:68:16', '192.168.1.2': '00:0A:95:9D:68:17'}
Enter IP to ARP for: 192.168.1.6
Received ARP reply: 192.168.1.6 is at 00:0A:95:9D:68:1B
Current ARP Table: {'192.168.1.1': '00:0A:95:9D:68:16', '192.168.1.2': '00:0A:95:9D:68:17', '192.168.1.6': '00:0A:95:9D:68:1B'}
Enter IP to ARP for: 192.168.1.5
Received ARP reply: 192.168.1.5 is at 00:0A:95:9D:68:1A
Current ARP Table: {'192.168.1.1': '00:0A:95:9D:68:16', '192.168.1.2': '00:0A:95:9D:68:17', '192.168.1.6': '00:0A:95:9D:68:1B', '192.168.1.5': '00:0A:95:9D:68:1A'}