## Developing a Network Scanner for Cybersecurity: The Role of ARP in Network Monitoring
**Posted:** 2024-08-10
**Last Edited:** 2025-07-14
---
## Objective
In cybersecurity, understanding network protocols and how they work is essential. The Address Resolution Protocol (ARP) is especially important for mapping IP addresses to MAC addresses, which helps in understanding network architecture and doing further analysis.
This project is a super simple network scanner I built in Python as my first proper project to show the role of ARP in network security. There are probably millions of projects out there that do the same thing, but this was built purely for learning purposes.
My goal was to practise and demonstrate some Python programming while learning how to work with network protocols, and in this instance with ARP.
By scanning IP ranges and identifying devices on a network, this tool can help spot unauthorised devices and highlight potential security issues. It can also give an insight into a network’s setup and security.
---
## Background
ARP is essential for translating IP addresses into MAC addresses and mapping them on a local network. This allows devices to communicate with each other within a subnet.
ARP assists in managing and securing networks by identifying authorised and unauthorised devices. ARP scanning can also be used for identifying ARP spoofing attacks, where a malicious actor may impersonate a targets' device in order to intercept its traffic.
Each time a device send out an ARP packet to discover devices on a network, the mapped IP and MAC address are stored in a cache table on the device to reduce further ARP requests.
![[Developing a Network Scanner for Cybersecurity.png]]
**Credit** to [ClouDNS](https://www.cloudns.net/blog/arp-address-resolution-protocol-why-is-it-important/)
---
## Project Implementation
### 1. Import the Required Libraries
In Python projects, Python modules are imported at the start of a project to access pre-built functions and libraries that simplify coding and avoid us having to reinvent the wheel.
![[Developing a Network Scanner for Cybersecurity-1.png]]
- [customtkinter](https://customtkinter.tomschimansky.com/documentation/): A more modern extension of ‘Tkinter’ for creating custom and styled widgets and windows. This will form and create the Graphical User Interface (GUI).
- [**tkinter**](https://docs.python.org/3/library/tkinter.html): Provides the dialogue and alert type message boxes from the ‘Tkinter’ module.
- [**scapy**](https://scapy.net/): This is an “interactive packet manipulation library”, and in this project is used to craft ARP packets to broadcast within a network.
- [**ipaddress**](https://docs.python.org/3/library/ipaddress.html): This in-built python module handles IP address manipulation and allows us to validate IP address formats to handle any possible user errors.
- [**csv**](https://docs.python.org/3/library/csv.html), [**json**](https://docs.python.org/3/library/json.html): These in-built modules are used for saving scan results in different formats i.e., csv, json.
- [**requests**](https://pypi.org/project/requests/): A library for sending HTTP requests in Python. In this project it’s used for fetching the MAC address vendor information from an external API so we can identify the type of device.
- [**threading**](https://docs.python.org/3/library/threading.html): Another in-built Python library that lets us run multiple tasks at once (in separate threads), which help keep the GUI responsive during network scans and enables smooth updates like the progress bar animation.
---
### 2. Class Definition and Initialisation
For this project I wanted to demonstrate [Object-Oriented Programming (OOP)](https://realpython.com/python3-object-oriented-programming/). OOP is a way of coding where you use classes to define the structure and behaviour of different parts of a program. A class, in this instance, is like a template you can use to make an object with its own related data and actions. Using a class helps keep all the related code for the objects together and in one place, making it easier to read, use, and maintain.
![[Developing a Network Scanner for Cybersecurity-2.png]]
`NetworkScannerApp`: This class is the main template for the app. It holds all the code to manage the scanning features and the GUI.
`__init__`: This is a special function that runs when you make an object from the class. It sets up the application window and calls `setup_ui()` to build the GUI.
---
### 3. User Interface Setup
Using a GUI can make a program easier to use and accessible to people of varying technical skill levels which is why I wanted to implement it for this project. In Python, we can use functions like the one below to create reusable blocks of code that perform specific tasks and can be called whenever you need them.
![[Developing a Network Scanner for Cybersecurity-3.png]]
`setup_ui()`: This function sets up the layout and the look of the application window. It then adds labels, text entry fields, buttons, a text box for displaying scan results, and then lastly a progress bar. This makes the app easy to use by giving the user a clear way to input information, start a scan, see the scan’s results, and track a scan’s progress.
---
### 4. IP Validation Function
Validating a user’s input is import to ensure that the program handles data correctly and to reduce (and hopefully avoid) errors. In this project we want to check that an IP address or IP address range is properly formatted to prevent errors in scanning.
![[Developing a Network Scanner for Cybersecurity-4.png]]
`validate_ip(target_ip)`: This function uses the built-in Python module, `ipaddress`, to check if the entered IP address or range is valid. If the format is correct, it returns True. Otherwise, it catches the error to prevent the program from crashing.
---
### 5. MAC Address Vendor Lookup
Every network device has a unique MAC address, and part of that address can be used to identify its manufacturer. Looking up the vendor can help you recognise the type of device on the network.
This section utilises the free API provided by ‘[MA:CV:en:do:rs](https://macvendors.com/)’ to craft HTTP requests to get information back about the requested MAC address.
> [!Note]
> Since creating this project and writing this, the API has changed a lot. The API did not previously require an account to be made however, at the time of this edit, (2025–07–13), a free account now will allow you to generate **1,000 requests a day** and more importantly, **2 requests per second**.
>
> An edit to this project may be made in the future to account for this including adding a rate limit to this function.
![[Developing a Network Scanner for Cybersecurity-5.png]]
- `get_mac_vendor(mac_address)`: This function sends a request to an external API to find the vendor information for a given MAC address. It returns the vendor name so that the scan results will show which company made the detected device. This can help us identify what devices are currently running present and may help detect unwanted devices on the network.
---
### 6. Network Scanning
Network scanning helps discover devices on a local network by sending ARP requests and listening for responses.
ARP operates at Layer 2 ([Data Link Layer](https://www.geeksforgeeks.org/computer-networks/data-link-layer/)) of the [OSI model](https://www.geeksforgeeks.org/computer-networks/open-systems-interconnection-model-osi/), using the broadcast MAC address `ff:ff:ff:ff:ff:ff` to reach all devices on the local segment. This scanner uses that behaviour by crafting a packet with the destination broadcast address above.
In comparison, this differs from a Layer 3 ([Network Layer](https://www.geeksforgeeks.org/computer-networks/network-layer-in-osi-model/)) broadcast addresses like `192.168.1.255`, which target all IPs in the IP range `192.168.1.0/24`.
This broadcast approach is what makes ARP effective for quickly mapping all connected devices in a subnet.
![[Developing a Network Scanner for Cybersecurity-6.png]]
`scan_network(target_ip)`: This function creates and sends ARP requests to the specified IP range to find all active devices. It then collects their IP address and their MAC addresses, looks up the associated vendor information, updates the progress bar as it scans, and then finally returns a list of discovered devices.
---
### 7. Save Results to Files
Saving scan results in different file formats improves accessibility for different peoples use cases as well as my own.
![[Developing a Network Scanner for Cybersecurity-7.png]]
- `save_to_pcap(clients, filename)`: Saves the captured network packets in PCAP format, which can be opened in tools like Wireshark for detailed packet analysis.
- `save_to_csv(clients, filename)`: Saves the scan results in CSV format, making them easy to view in spreadsheets, share with others, or import into other programs.
- `save_to_json(clients, filename)`: Saves the scan results in JSON format, which is well-suited for structured data, automation workflows, and integration with other tools or systems.
---
### 8. Display Results
This is how we display the results. Presenting scan results clearly in the app help the user quickly understand what devices are on the network and review important details like the IPv4 address, the related MAC address, and its vendor information. A formatted display of this information can also help improve readability of the results.
![[Developing a Network Scanner for Cybersecurity-8.png]]
`print_scan_results(clients)`: This function formats the scan results into a readable table with columns for IP address, MAC address, and the vendor. It then displays the results in the application's text box so that the user can easily review the results.
---
### 9. Scan Execution and Threading
Running long or network-heavy tasks in the main thread can make a GUI freeze and become unresponsive. Using threading allows these tasks to run in the background while keeping the interface smooth for the user.
Although Python has a [Global Interpreter Lock (GIL)](https://realpython.com/python-gil/) that limits true parallel CPU-bound tasks, threading is necessary here because network scanning is I/O-bound and can benefit from running separately from the GUI. Without it, the GUI would freeze or become unresponsive during scanning.
![[Developing a Network Scanner for Cybersecurity-9.png]]
- `start_scan()`: Handles the scanning process from start to finish. It validates the entered IP address, runs the network scan, updates the progress bar, displays the results, and enables the save button once scanning is complete.
- `start_scan_thread()`: Starts the `start_scan()` function in a separate thread so that the GUI remains responsive during the network scan.
### 10. Save Results Function
![[Developing a Network Scanner for Cybersecurity-10.png]]
`save_results()`: Opens a file dialogue box that lets the user choose the file name, location, and format for saving the results. Depending on the selected file type (_PCAP, CSV, or JSON_), it calls the appropriate function to save the scan data in that format.
### 11. Running the Application
To make the app work as intended, it needs to start its main event loop and respond to user interactions like button clicks and text entry. This ensures the GUI remains active and usable.
![[Developing a Network Scanner for Cybersecurity-11.png]]
- `run()`: Starts the `Tkinter` event loop, displaying the application window and handling all user interactions until the app is closed.
- `if __name__ == "__main__":`: Ensures that the application only runs when the script is executed directly, not when it is imported as a module in another program.
---
## Network Scanner Full Code:
Available on my GitHub [here](https://github.com/console-tornado/simple-network-scanner).