Port scanner returns all closed

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.

Challenge: Port Scanner

Link to the challenge:

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.