Crafting a Network Port Scanner in Python: A Step-by-Step Guide
Crafting a Network Port Scanner in Python
Understanding the Goal
The goal is to create a Python script that scans a target host for open ports. This script should be capable of scanning specific ports or a predefined list of common ports using multithreading for efficiency.
1. Importing Necessary Modules
To start, import the required modules: socket
, argparse
, threading
, and Queue
. These modules will facilitate socket operations, argument parsing, multithreading, and task management.
1
2
3
4
5
6
7
```
python
import socket
import argparse
import threading
from queue import Queue
```
2. Defining Common Ports
Define a list of common ports to scan. This list serves as the default set of ports to check if the user doesn’t specify a custom range.
1
2
3
```
COMMON_PORTS = [21, 22, 23, 25, 53, 80, 110, 143, 443, 3306, 3389]
```
3. Writing Port Scanning Functions
Write functions to handle port scanning tasks. The scan_port
function attempts to connect to a specified port on the target host and prints whether it’s open or closed. The port_scan_worker
function manages multithreaded scanning by delegating individual port scans to worker threads.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
```
def scan_port(target_host, port, timeout=1):
try:
# Create a socket object
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# Set a timeout for the connection attempt
sock.settimeout(timeout)
# Attempt to connect to the target host and port
result = sock.connect_ex((target_host, port))
# Check if the connection was successful
if result == 0:
print(f"Port {port} is open")
# Attempt to grab the banner
banner = sock.recv(1024).decode().strip()
if banner:
print(f"Banner for port {port}: {banner}")
else:
print(f"Port {port} is closed")
# Close the socket
sock.close()
except KeyboardInterrupt:
print("Scan stopped by user.")
exit()
except socket.gaierror:
print("Hostname could not be resolved.")
exit()
except socket.error:
print("Couldn't connect to server.")
exit()
def port_scan_worker(target_host, port_queue, timeout):
while not port_queue.empty():
port = port_queue.get()
scan_port(target_host, port, timeout)
port_queue.task_done()
```
4. Implementing Multithreading
Utilize the threading
module to implement multithreading for faster scanning. This involves creating a pool of worker threads, each responsible for scanning a subset of ports.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
```
def scan_common_ports(target_host, timeout):
print("Scanning common ports...")
port_queue = Queue()
# Enqueue common ports
for port in COMMON_PORTS:
port_queue.put(port)
# Create and start threads
for _ in range(10): # You can adjust the number of threads here
thread = threading.Thread(target=port_scan_worker, args=(target_host, port_queue, timeout))
thread.start()
# Wait for all threads to finish
port_queue.join()
```
5. Parsing Command-Line Arguments
Use the argparse
module to parse command-line arguments. This allows users to specify the target host, port range, connection timeout, and output file for scan results.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
```
def main():
parser = argparse.ArgumentParser(description="Network port scanner")
parser.add_argument("host", help="Target host IP address")
parser.add_argument("-r", "--range", help="Port range to scan (e.g., '1-1000')")
parser.add_argument("-t", "--timeout", type=float, default=1, help="Connection timeout in seconds (default: 1)")
parser.add_argument("-o", "--output", help="Output file to save scan results")
args = parser.parse_args()
target_host = args.host
timeout = args.timeout
if args.range:
start_port, end_port = map(int, args.range.split('-'))
for port in range(start_port, end_port + 1):
scan_port(target_host, port, timeout)
else:
scan_common_ports(target_host, timeout)
if args.output:
with open(args.output, "w") as f:
f.write("Scan results:\n")
# Redirecting stdout to the file
import sys
sys.stdout = f
main()
# Reset stdout
sys.stdout = sys.__stdout__
print(f"Scan results saved to {args.output}")
if __name__ == "__main__":
main()
```
6. Executing the Scans
In the main
function, orchestrate the scanning process based on the provided command-line arguments. Determine whether to scan a specific port range or the predefined common ports. If an output file is specified, redirect the scan results to that file.
Learning Points
Socket Programming: Gain insights into socket programming by understanding how to create socket objects, set timeouts, and establish connections for port scanning tasks.
Multithreading Techniques: Learn about multithreading in Python and how to implement it for concurrent port scanning. Understand concepts like thread synchronization and task delegation.
Command-Line Argument Parsing: Enhance your skills in parsing command-line arguments using the
argparse
module. Learn how to handle user input effectively for versatile script functionality.Efficient Port Scanning: Explore strategies for efficient port scanning, such as multithreading and predefined port lists. Understand the importance of optimizing scan processes for speed and accuracy.
Conclusion: Empowering Cybersecurity Exploration
By crafting this network port scanner in Python, you’ve embarked on a journey of exploration and learning in the realm of cybersecurity. Armed with newfound knowledge in socket programming, multithreading, and command-line argument parsing, you’re better equipped to tackle real-world challenges in network security assessment and defense. Keep exploring, keep learning, and let your curiosity drive you to new heights in the ever-evolving landscape of cybersecurity.