Skip to content

Commit 81d3ecd

Browse files
authored
Merge pull request #246 from Nibba2018/async-port-scanner
Multithreaded Port Scanner
2 parents b520d62 + 4e4b861 commit 81d3ecd

File tree

4 files changed

+123
-0
lines changed

4 files changed

+123
-0
lines changed
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Multithreaded Port Scanner
2+
This script scans for open ports using multiple threads in parallel in which each port is checked on a separate thread. It is faster than the usual single threaded application.
3+
4+
## Executing the script
5+
* Run `python scan-ports.py <IP or website name>`
6+
* for e.g the following are valid calls:
7+
* `python scan-ports.py 142.250.67.142`
8+
* `python scan-ports.py www.google.com`
9+
10+
## Output
11+
12+
![output1](images/output1.png)
13+
14+
![output2](images/output2.png)
Loading
Loading
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
import concurrent.futures
2+
import socket
3+
import sys
4+
import ipaddress
5+
6+
# Check if the user has provided commandline arguments.
7+
if len(sys.argv) < 2:
8+
print("Not enough commandline arguments.")
9+
sys.exit()
10+
11+
# Check if the IP address or website is valid or not.
12+
try:
13+
ipaddress.ip_address(sys.argv[1])
14+
except ValueError:
15+
try:
16+
ipaddress.ip_address(socket.gethostbyname(sys.argv[1]))
17+
except (ValueError, socket.gaierror):
18+
print("Invalid IP address or domain name.")
19+
sys.exit()
20+
else:
21+
target_IP = socket.gethostbyname(sys.argv[1])
22+
else:
23+
target_IP = sys.argv[1]
24+
25+
# create a list to store custom ports.
26+
custom_ports = []
27+
if len(sys.argv) > 2:
28+
custom_ports = sys.argv[2:]
29+
30+
# Method to scan a single port
31+
def scan_port(target_IP, port):
32+
# Create a socket object.
33+
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
34+
35+
# Set default timeout to 1 second.
36+
socket.setdefaulttimeout(1)
37+
38+
# Try to connect the target
39+
result = s.connect_ex((target_IP, port))
40+
41+
# Check if connection was successful
42+
if result == 0:
43+
print(f"Port {port}: \033[92mOPEN\033[0m")
44+
return port
45+
46+
return None
47+
48+
49+
def scan_ports(port_range):
50+
51+
if not port_range:
52+
port_range = map(int, input("Enter ports(space separated):").split())
53+
54+
# List to hold open ports.
55+
open_ports = []
56+
57+
# Create a context manager to spawn individual threads for each port.
58+
with concurrent.futures.ThreadPoolExecutor() as executor:
59+
60+
future_to_port = {
61+
executor.submit(scan_port, target_IP, port): port for port in port_range
62+
}
63+
64+
# Run a loop to collect open ports.
65+
for future in concurrent.futures.as_completed(future_to_port):
66+
# Get the selected port
67+
port = future_to_port[future]
68+
try:
69+
# Check if it a valid port.
70+
open_port = future.result()
71+
except Exception as e:
72+
# Print any errors.
73+
print(f"Exception:{e}")
74+
else:
75+
# Add to the list if it's a valid port.
76+
if open_port is not None:
77+
open_ports.append(open_port)
78+
79+
return open_ports
80+
81+
82+
if __name__ == "__main__":
83+
84+
MENU_PROMPT =\
85+
"""[1] Reserved Ports.
86+
[2] All Ports.
87+
[3] Critical Ports.
88+
[4] Manual Ports.
89+
Enter your choice:"""
90+
91+
# Get user choice
92+
choice = int(input(MENU_PROMPT))
93+
94+
# Define switcher
95+
switcher = {
96+
1: range(1024),
97+
2: range(65536),
98+
3: [15, 20, 21, 22, 23, 25, 49, 50, 51, 53, 67, 68, 69, 79, 80, 88,
99+
110, 111, 119, 123, 135, 137, 138, 139, 143, 161, 389, 443, 445,
100+
500, 520, 546, 547, 636, 993, 995, 1512, 1701, 1720, 1723, 1812,
101+
1813, 3306, 3389, 5004, 5005, 5060, 5061, 5900, 8080],
102+
4: []
103+
}
104+
105+
# Call method to scan ports.
106+
open_ports = scan_ports(switcher[choice])
107+
108+
# Finally print all the open ports.
109+
print(f"Open Ports:{open_ports}")

0 commit comments

Comments
 (0)