I tried your code on jupyter notebook and I always get the same set of ports:
get_open_ports('127.0.0.1')
Output:
[133, 200, 144...60700]
Could it be possible that a different number of ports are open at a particular time for the host being queried?
To verify for a small set of ports, I reduced max_port
to 10000
and I still get the same set of ports every time:
def get_open_ports(host, max_port=10000):
open_ports = []
def worker(port):
if check_open_port(host, port):
open_ports.append(port)
with ThreadPoolExecutor(max_workers=10000) as executor:
[executor.submit(worker, port) for port in range(1, max_port + 1)]
executor.shutdown(wait=True)
return open_ports
get_open_ports('127.0.0.1')
Output: [150, 900, 1035, 7789]
Note: I've changed the port numbers for security sake.
EDIT:
def get_open_ports(host, max_port=65535):
open_ports = []
def worker(port):
if check_open_port(host, port):
open_ports.append(port)
# We can use a with statement to ensure threads are cleaned up promptly
with ThreadPoolExecutor(max_workers=100) as executor:
print('main:starting')
wait_for=[executor.submit(worker,port) for port in range(1, max_port + 1)]
for f in as_completed(wait_for):
print('main: result: {}'.format(f.result())) #check result on each thread execution
# executor.shutdown(wait=True) #not required when using the 'with' statement
return len(open_ports)
test = get_open_ports('45.60.112.163') #hostname for www.indracompany.com
#max_workers not defined & max_port=10000
# len(test) #test1: 148
# len(test) #test 2: 79
#max_workers = 10000 & max_port=65535
# len(test) #test1: 1
# len(test) #test2:1
# len(test) #test3:1
#max_workers = 20000 & max_port=65535
# len(test) #test1: 14
# len(test) #test2:1
# len(test) #test3: 1
# len(test) #test4:1
#max_workers not defined & max_port=65535 #quite time-consuming
# len(test) #test1: 63
EDIT 2: A more reliable solution
As suggested by @Tarun, Python's python-nmap library does a better job at scanning hosts.
The below solution gives an accurate result, however, I observed a significant compromise on performance as the range of port discovery increases. Perhaps, threading could be incorporated into the code to improve performance. I've also imported the time library to get the program execution time in the end. This can be used for comparison purposes when testing for performance.
# The python-nmap library helps to programmatically manipulate scanned results of nmap to automate port scanning tasks.
# To use this library you must have the Nmap software installed. This can be installed from https://nmap.org/download.html.
# Network Mapper (Nmap) is a free and open-source tool used for network discovery and security auditing.
# It runs on all major computer operating systems, and official binary packages are available for Linux, Windows, and Mac OS X.
# For Windows 7 and later, you must also upgrade 'NCap' from https://nmap.org/npcap/
# For Windows, make sure nmap.exe is added to PATH.
# When you're ready, pip install python-nmap
import time
import nmap
nm = nmap.PortScanner() #initialize PortScanner object
host = '45.60.112.163' #specify host
nm.scan(host, '1-100') #run the scan, specify host and range of ports to scan
#Optional steps for verification:
#Output: nmap -oX - -p 1-100 -sV 45.60.112.163
print(nm.command_line()) #command_line command to execute on nmap command prompt
#Output: {'tcp': {'method': 'syn', 'services': '1-100'}}
print(nm.scaninfo()) #nmap scan information
#Now we can scan all hosts
#From Official documentation at https://xael.org/pages/python-nmap-en.html
start_time = time.time() #To get program execution time
for host in nm.all_hosts():
print('----------------------------------------------------')
print('Host : %s (%s)' % (host, nm[host].hostname()))
print('State : %s' % nm[host].state())
for proto in nm[host].all_protocols():
print('----------')
print('Protocol : %s' % proto)
lport = nm[host][proto].keys()
for key in sorted(lport):
for port in lport:
print ('port : %s\tstate : %s' % (port, nm[host][proto][port]['state']))
print('Execution time: %s seconds' % (time.time() - start_time))
#Output:
----------------------------------------------------
Host : 45.60.112.163 ()
State : up
----------
Protocol : tcp
port : 25 state : open
port : 51 state : open
port : 53 state : open
port : 80 state : open
port : 81 state : open
port : 85 state : open
port : 91 state : open
port : 25 state : open
port : 51 state : open
port : 53 state : open
port : 80 state : open
port : 81 state : open
port : 85 state : open
port : 91 state : open
port : 25 state : open
port : 51 state : open
port : 53 state : open
port : 80 state : open
port : 81 state : open
port : 85 state : open
port : 91 state : open
port : 25 state : open
port : 51 state : open
port : 53 state : open
port : 80 state : open
port : 81 state : open
port : 85 state : open
port : 91 state : open
port : 25 state : open
port : 51 state : open
port : 53 state : open
port : 80 state : open
port : 81 state : open
port : 85 state : open
port : 91 state : open
port : 25 state : open
port : 51 state : open
port : 53 state : open
port : 80 state : open
port : 81 state : open
port : 85 state : open
port : 91 state : open
port : 25 state : open
port : 51 state : open
port : 53 state : open
port : 80 state : open
port : 81 state : open
port : 85 state : open
port : 91 state : open
Execution time: 0.015624761581420898 seconds
To convert output to csv, use:
print(nm.csv())
As a result of this investigation, Nmap was now installed on my computer. Just for fun, I also ran a scan on the command prompt using the below command. This scan ran for range '1-1000' and took more than 15 minutes(I didn't sit through the whole session!).
