Too fast checking local ports with python socket

42 Views Asked by At

This code example is given in the book "CPython Internals".

from queue import Queue
import socket
import time
timeout = 1.0

def check_port(host: str, port: int, results: Queue):
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.settimeout(timeout)
    result = sock.connect_ex((host, port))
    if result == 0:
        results.put(port)
    sock.close()

if __name__ == '__main__':
    start = time.time()
    host = "localhost"
    results = Queue()
    for port in range(80, 100):
        check_port(host, port, results)
    while not results.empty():
        print("Port {0} is open".format(results.get()))
    print("Completed scan in {0} seconds".format(time.time() - start))

If host == 'localhost', then this script works very quickly (all ports (form 1 to 65535) checked for about 1.5 secs!), moreover, the duration of the timeout does not play any role.

If I set the host "8.8.8.8" or some other external one, then the script execution time looks correct. For example, checking ports from 440 to 444 with timeout == 1 on 8.8.8.8 takes about 4 secs.

Why is checking the availability of local ports so fast? (I use Ubuntu if it's important)

1

There are 1 best solutions below

0
Steffen Ullrich On

In case of localhost the connection attempt gets immediately rejected, so timeout is not reached. In the case of the remote host it probably just drops the packets instead of rejecting (depends on firewall and host configuration), so it will run into timeout.