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?
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")