Search code examples
pythonpython-socketsport-scanning

Python port scanner has unexpected results


I'm trying to develop a simple port scanner in Python. If I run it against one single port the result is correct, but when I try to create a for-loop to test all ports, the result is different from when only one port is tested, but never the same port.

This is the basic program against one port:

#! /usr/bin/python
import socket

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

host = "192.168.1.8"
port = 443

def portscanner():
    if sock.connect_ex((host,port)):
        print ("Port %d is closed" % (port))
    else:
        print("Port %d is open" % (port))

portscanner()

the result is:

Port 443 is open.

If I try instead:

#! /usr/bin/python
    
import socket

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

host = "192.168.1.1"

def portscanner():
    
    closed = 0
    opened  = 0

    for port in range (0, 65535):
    
        if sock.connect_ex((host,port)):
            closed += 1
        else:
            print("Port %d is open" % (port))
            opened += 1

    print_port(closed, opened)

def print_port(closed, opened):
    print ("%d ports are opened" % (opened))
    print ("%d ports are closed" % (closed))

portscanner()

The result is:

Port 34452 is open
1 ports are opened
65534 ports are closed

but if I rerun it the result becomes:

Port 52016 is open
1 ports are opened
65534 ports are closed

If I run it against my router the result is always:

Port 53 is open
1 ports are opened
65534 ports are closed

It seems the code is correct, but maybe I'm wrong, which can be an explanation?


Solution

  • I'm not sure why the results are inconsistent when you run the script multiple times, but there's a bigger problem: You need to create a new socket for each connection attempt. Once the socket has connected, you can't use it to connect again, so it will only report the lowest open port. Move the call to create the socket inside the loop.

    def portscanner(host):
        
        closed = 0
        opened  = 0
    
        for port in range (0, 65535):
            with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
                if sock.connect_ex((host,port)):
                    closed += 1
                else:
                    print("Port %d is open" % (port))
                    opened += 1
    
        print_port(closed, opened)
    
    portscanner("192.168.1.1")