Multi-Threaded TCP/IP Port Scanner in Python

Majority of communication over Internet happens using TCP. For instance, the web server normally resides on TCP port 80, email server on port 25, and FTP server on port 21.

Here’s the code for conducting a TCP full connect scan.

 
from socket import *
from threading import *

def connect_to_host(host, port):
    lock_object = Semaphore(value=1)
    try:
        sckt = socket(AF_INET, SOCK_STREAM)
        sckt.connect((host, port))
        sckt.send('Hello\r\n')
        results = sckt.recv(100)
        lock_object.acquire()
        print 'Port %d open'% port
        print str(results)
    except:
        lock_object.acquire()
        print 'Port %d closed'% port
    finally:
        lock_object.release()
        sckt.close()

def scan_ports(host, ports):
    try:
        tgtIP = gethostbyname(host)
    except:
        print "Could not resolve host:'%s'"%host
        return
    try:
        tgtName = gethostbyaddr(tgtIP)
        print '\nScanning: ' + tgtName[0]
    except:
        print '\n Scanning: ' + tgtIP
    setdefaulttimeout(1)
    for port in ports:
        t = Thread(target=connect_to_host, args=(host, int(port)))
        t.start()



def main():
    ports = range(77,81)
    ports= map(str, ports)
    scan_ports('google.com', ports)

if __name__ == '__main__':
    main()

Code Description

  • We use the BSD socket API feature of Python to communicate with other hosts on the network and to create, bind, listen, connect and send traffic on TCP/IP sockets for a given IP address.
  • The connect_to_host method translates hostname into equivalent IPv4 address and tries to open a socket connection on the given IP address and port.
  • If successful it sends some text data and read the results sent back by the host. If a result is received it prints a ‘Port Open message’ else it prints a ‘Port closed method’
  • We use python threading module to scan sockets simultaneously.
  • However be do not want to print output from multiple threads all at one time. For an orderly printing of results we use a semaphore lock using acquire(). If a thread acquires a lock other threads wait until the current thread holding the lock releases it.

And here’s the sample output:

Scanning: maa03s05-in-f4.1e100.net
Port 80 open
HTTP/1.0 400 Bad Request
Content-Type: text/html; charset=UTF-8
Content-Length: 925
Date: Sat, 05
Port 77 closed
Port 79 closed
Port 78 closed