Tell us what’s happening:
My code is not finding any open ports and returning them all as “closed”. What am I missing? Is there something I need to do specifically when running the code in my terminal?
Your code so far
import socket
def get_open_ports(target, port_range, verbose=None):
open_ports = []
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
start, end = port_range
def port_scan(port):
try:
s.connect((target, port))
return True
except:
return False
for i in range(start, (end+1)):
port = i
if port_scan(port):
print(f"The port {port} is Open.")
open_ports.append(port)
else:
print(f'The port {port} is Closed.')
return(open_ports)
Your browser information:
User Agent is: Mozilla/5.0 (Macintosh; Intel Mac OS X 11_2_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.152 Safari/537.36.
You really need to look at the python documentation for the socket library, especially comparing the connect() and connect_ex(), settimeout(), and especially close(). You only need to make the connection to the point of determining the connection can be made and then you need to close it. You can use the return status of connect()/connect_ex() to determine if the port is open or not and you can set the timeout to a value long enough for your network speed but short enough your scan doesn’t take forever.
Looking at your code I think that since you are not closing your socket after every connection attempt and since most port ranges start on a closed port, your socket starts closed and reports closed every time. You should be able to verify this if you scan a range with a known open port on your local machine (it’s much faster), both with the range starting with a closed port and with the open port (like 70-90 or 80-90 for http port 80).
Dang I still cannot figure this out, but I am much closer. There are two tests related to returning an invalid hostname that I cannot pass.
1) test_port_scanner_invalid_hostname expecting "Error: Invalid hostname"
2) test_port_scanner_verbose_ip_no_hostname_returned_single_port is returning 'Invalid hostname' but should actually return a normal answer
There’s something wrong with my error return statements at the end but I cannot figure out what to do. Any Ideas? Thanks!
def get_open_ports(target, port_range, Verbose=None):
open_ports = []
start, end = port_range
if target[0].isdigit():
ip = True
else:
ip = False
try:
for i in range(start, (end + 1)):
port = i
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.settimeout(0.5)
result = s.connect_ex((target, port))
if result == 0:
open_ports.append(port)
s.close()
if Verbose:
if ip:
url = socket.gethostbyaddr(target)[0]
string = f"Open ports for {url} ({target})\nPORT SERVICE\n"
else:
ip_address = str(socket.gethostbyname(target))
string = f"Open ports for {target} ({ip_address})\nPORT SERVICE\n"
port_arr = []
for port in open_ports:
space_length = 9 - len(str(port))
common_port = common_ports.ports_and_services
port_arr.append(f"{port}{space_length * ' '}{common_port[port]}")
return string + '\n'.join(port_arr)
else:
return open_ports
except socket.gaierror:
return "Error: Invalid IP address"
except socket.herror:
return "Error: Invalid hostname"
You can’t always just catch socket.herror because an IP address does not have to have a hostname. You have three cases to handle: an IP with no hostname (valid or not), an IP with a hostname (valid or not), and a hostname without an IP. I think handling the IP without a hostname will solve most of your problem.