ICMP (Internet Control Message Protocol) Echo requests, mostly known as pings, are used to verify the connectivity of devices to a network and their responsiveness to it.
In today’s article, we’re going to perform a ping test using Python that checks the connectivity of our network and measures the response time if there is one.
Let’s get started!
Table of Contents
- Necessary Libraries
- Imports
- Initializing Colorama
- Defining craft_and_send_packet Function
- Defining analyze_response Function
- Display error Function
- Main Function
- Main Block
- Example
- Full Code
Necessary Libraries
To make this code run as intended, it’s necessary to install the Scapy and Colorama libraries via your terminal or command prompt:
$ pip install scapy
$ pip install colorama
Imports
We start by importing sys
module, which we will use to handle information passed to the code. In other words, it informs the code what command-line has been provided.
import sys
Then we import sr1
, IP
, ICMP
from scapy
, which will be used for making packets and analyzing network protocols.
from scapy.all import sr1, IP, ICMP
The third import gonna be Fore
and init
from colorama
, which we will use to make colored and styled text.
from colorama import Fore, init
Our fourth import is the random
module to generate random numbers.
import random
Lastly, we import time
which we will use to calculate the response time.
import time
Initializing Colorama
Next, we initialize this library by the init()
function to distinguish visually between different printed messages when we run the code.
# Initialize colorama for colored console output
init()
Defining craft_and_send_packet Function
After that, We start defining our functions, we begin with this function that crafts and sends an ICMP echo request packet to an IP address that the user will specify, it has a retry count of 3 times if there’s no response, and it waits for a response for a timeout of 5 seconds.
# Function to craft and send an ICMP Echo Request packet with retries
def craft_and_send_packet(dst_ip, retry_count=3, timeout=5):
for i in range(retry_count):
print(f"{Fore.BLUE}[DEBUG] Sending ICMP Echo Request to: {dst_ip}")
start_time = time.time()
response = sr1(IP(dst=dst_ip) / ICMP(), timeout=timeout, verbose=False)
end_time = time.time()
if response:
print(f"{Fore.BLUE}[DEBUG] Received response from {response.src}: {response.summary()}")
return response, end_time - start_time
else:
print(f"{Fore.RED}[DEBUG] No response received, retrying ({i + 1}/{retry_count})...")
time.sleep(1) # Wait for a short time before retrying
return None, timeout
Defining analyze_response Function
Then, we define the analyze_response
function, which prints relevant information retrieved from analyzing the response received from the destination IP address. This includes the source IP address, whether there’s a response or not, and the response time.
# Function to analyze the response
def analyze_response(response, response_time):
if response:
print(f"{Fore.GREEN}[+] Response received from {response.src}: {response.summary()}")
print(f" Response time: {response_time:.5f} seconds")
# Additional analysis can be added here
else:
print(f"{Fore.RED}[-] No response received")
Display error Function
# Function to display an error message
def display_error(message):
print(f"{Fore.RED}[-] Error: {message}")
Following that, we create this one to handle occasions when an error occurs during the execution of the code.
Main Function
Now, we define the main function that begins by verifying if the user has correctly entered both “the name of the script” and “the destination IP address” in the command prompt. If one of them is missing, it will trigger the display_error()
function then an error message will pop up.
Once the user provides the correct inputs, the function retrieves the destination IP address, which is the second input. It then displays a message in yellow, indicating that ‘ICMP Echo Requests are being sent to the destination IP address‘. Following this, the response time is returned to the analyze_response()
function to print the relevant information.
# Main function
def main():
if len(sys.argv) != 2:
display_error("Invalid number of arguments. Please run as: python script.py <destination_ip>")
sys.exit(1)
destination_ip = sys.argv[1]
print(f"{Fore.YELLOW}[+] Sending ICMP Echo Requests to: {destination_ip}\n")
response, response_time = craft_and_send_packet(destination_ip)
analyze_response(response, response_time)
Main Block
Lastly, this block ensures that the code will work only if it is run directly, and in the case it is imported as a module it will not work.
if __name__ == "__main__":
main()
Example
- First, run your command prompt.
- Second, use the
cd
command to navigate to the directory path where you saved this Python code:cd path\to\directory
. - Third, use
pip install
command to install the required libraries,pip3 install
for Linux and macOS. - Fourth and last, type python followed by the name of your script followed by the destination IP, in my case the code is named
main.py
so :
python main.py destination-IP
Full Code
import sys
from scapy.all import sr1, IP, ICMP
from colorama import Fore, init
import random
import time
# Initialize colorama for colored console output
init()
# Function to craft and send an ICMP Echo Request packet with retries
def craft_and_send_packet(dst_ip, retry_count=3, timeout=5):
for i in range(retry_count):
print(f"{Fore.BLUE}[DEBUG] Sending ICMP Echo Request to: {dst_ip}")
start_time = time.time()
response = sr1(IP(dst=dst_ip) / ICMP(), timeout=timeout, verbose=False)
end_time = time.time()
if response:
print(f"{Fore.BLUE}[DEBUG] Received response from {response.src}: {response.summary()}")
return response, end_time - start_time
else:
print(f"{Fore.RED}[DEBUG] No response received, retrying ({i + 1}/{retry_count})...")
time.sleep(1) # Wait for a short time before retrying
return None, timeout
# Function to analyze the response
def analyze_response(response, response_time):
if response:
print(f"{Fore.GREEN}[+] Response received from {response.src}: {response.summary()}")
print(f" Response time: {response_time:.5f} seconds")
# Additional analysis can be added here
else:
print(f"{Fore.RED}[-] No response received")
# Function to display an error message
def display_error(message):
print(f"{Fore.RED}[-] Error: {message}")
# Main function
def main():
if len(sys.argv) != 2:
display_error("Invalid number of arguments. Please run as: python script.py <destination_ip>")
sys.exit(1)
destination_ip = sys.argv[1]
print(f"{Fore.YELLOW}[+] Sending ICMP Echo Requests to: {destination_ip}\n")
response, response_time = craft_and_send_packet(destination_ip)
analyze_response(response, response_time)
if __name__ == "__main__":
main()
Happy Coding!