Download as pdf or txt
Download as pdf or txt
You are on page 1of 8

People who code: we want your input.

Take the Survey

Making a Fast Port Scanner


Asked
6 years, 8 months ago Active
1 year, 8 months ago Viewed
48k times

So I'm making a port scanner in python...

8 import socket

ip = "External IP"

s = socket.socket(2, 1) #socket.AF_INET, socket.SOCK_STREAM

def porttry(ip, port):

try:

7 s.connect((ip, port))

return True

except:

return None

for port in range(0, 10000):

value = porttry(ip, port)

if value == None:

print("Port not opened on %d" % port)

else:

print("Port opened on %d" % port)

break

raw_input()

But this is too slow, I want to somehow be able to some how close or break code after a
period of time of not returning anything.

python sockets port port-scanning

Share Improve this question edited Mar 13 '18 at 21:02 asked Oct 3 '14 at 7:16
Follow Drise Shane
4,006 4 34 61 257 1 3 13

9 Answers Active Oldest Votes

In addition to setting socket timeout, you can also apply multi-threading technique to turbo
boost the process. It will be, at best, N times faster when you have N ports to scan.
19
# This script runs on Python 3

import socket, threading

def TCP_connect(ip, port_number, delay, output):

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

TCPsock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

TCPsock.settimeout(delay)

try:

TCPsock.connect((ip, port_number))

output[port_number] = 'Listening'

except:

output[port_number] = ''

def scan_ports(host_ip, delay):

threads = [] # To run TCP_connect concurrently

output = {} # For printing purposes

# Spawning threads to scan ports

for i in range(10000):

t = threading.Thread(target=TCP_connect, args=(host_ip, i, delay, output))


threads.append(t)

# Starting threads

for i in range(10000):

threads[i].start()

# Locking the main thread until all threads complete

for i in range(10000):

threads[i].join()

# Printing listening ports from small to large

for i in range(10000):

if output[i] == 'Listening':

print(str(i) + ': ' + output[i])

def main():

host_ip = input("Enter host IP: ")

delay = int(input("How many seconds the socket is going to wait until timeout: "))

scan_ports(host_ip, delay)

if __name__ == "__main__":

main()

Share Improve this answer Follow edited Jan 25 '19 at 19:15 answered Jul 5 '16 at 18:15
Billy T
206 2 5

SO_REUSEADDR is only useful when listening on socket. Only creates confusion in this example
– Alex
Sep 13 '19 at 12:36

10000 was causing the error - too many open files, so reducing the range(1000) worked for me.
– 
Vikram Ray
Aug 25 '20 at 17:36

Consider setting a timeout instead of a for loop by using socket.setdefaulttimeout(timeout) .

4 Share Improve this answer Follow answered Oct 3 '14 at 7:34


Dataman
2,626 2 15 29

here is a quick and simple port scanner, it scans 100000 ports in 180 sec:
3 import threading

import socket

target = 'pythonprogramming.net'

#ip = socket.gethostbyname(target)

def portscan(port):

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

s.settimeout(0.5)#

try:

con = s.connect((target,port))

print('Port :',port,"is open.")

con.close()

except:

pass

r = 1

for x in range(1,100):

t = threading.Thread(target=portscan,kwargs={'port':r})

r += 1

t.start()

Share Improve this answer Follow edited Mar 13 '18 at 20:58 answered Mar 13 '18 at 20:53
Gysi Rrjolli
51 3

1 Why do you use r variable if you have x , that starts from 1 and increments every iteration?
– 
diduk001
Jul 24 '20 at 18:38

This should be a bit faster.

1 #-*-coding:utf8;-*-

#qpy:3

#qpy:console

import socket

import os

# This is used to set a default timeout on socket

# objects.

DEFAULT_TIMEOUT = 0.5

# This is used for checking if a call to socket.connect_ex

# was successful.

SUCCESS = 0

def check_port(*host_port, timeout=DEFAULT_TIMEOUT):

''' Try to connect to a specified host on a specified port.

If the connection takes longer then the TIMEOUT we set we assume

the host is down. If the connection is a success we can safely assume

the host is up and listing on port x. If the connection fails for any

other reason we assume the host is down and the port is closed.'''

# Create and configure the socket.

sock = socket.socket()

sock.settimeout(timeout)

# the SO_REUSEADDR flag tells the kernel to reuse a local

# socket in TIME_WAIT state, without waiting for its natural

# timeout to expire.

sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

# Like connect(address), but return an error indicator instead

# of raising an exception for errors returned by the C-level connect() 

# call (other problems, such as “host not found,” can still raise exceptions).

# The error indicator is 0 if the operation succeeded, otherwise the value of
# the errnovariable. This is useful to support, for example, asynchronous connects.

connected = sock.connect_ex(host_port) is SUCCESS

# Mark the socket closed.

# The underlying system resource (e.g. a file descriptor)

# is also closed when all file objects from makefile() are closed.

# Once that happens, all future operations on the socket object will fail.

# The remote end will receive no more data (after queued data is flushed).

sock.close()

# return True if port is open or False if port is closed.

return connected

con = check_port('www.google.com', 83)

print(con)

Share Improve this answer Follow answered Dec 11 '17 at 19:54


Ricky Wilson
2,715 3 19 28

One can use threading.Thread and threading.Condition to synchronize port check and
spawning new threads.
1
Script example usage:

python port_scan.py google.com 70 90

Checking 70 - 80

Checking 80 - 84

Checking 84 - 90

Found active port 80

Checking 90 - 91

Checking 91 - 94

All threads started ...

port_scan.py:

# import pdb

import socket, threading

from traceback import print_exc

class AllThreadsStarted(Exception): pass

class IPv4PortScanner(object):

def __init__(self, domain, timeout=2.0, port_range=(1024, 65535), threadcount=10):

self.domain = domain

self.timeout = timeout

self.port_range = port_range

self.threadcount = threadcount

self._lock = threading.Lock()

self._condition = threading.Condition(self._lock)

self._ports_active = []

self._ports_being_checked = []

self._next_port = self.port_range[0]

def check_port_(self, port):

"If connects then port is active"

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

sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

sock.settimeout(self.timeout)

try:

sock.connect((self.domain, port))

with self._lock:

self._ports_active.append(port)

print ("Found active port {}".format(port))

sock.close()

except socket.timeout, ex:

return

except:

print_exc()

# pdb.set_trace()

def check_port(self, port):

"updates self._ports_being_checked list on exit of this method"

try:

self.check_port_(port)

finally:

self._condition.acquire()

self._ports_being_checked.remove(port)

self._condition.notifyAll()

self._condition.release()

def start_another_thread(self):

if self._next_port > self.port_range[1]:

raise AllThreadsStarted()

port = self._next_port

self._next_port += 1

t = threading.Thread(target=self.check_port, args=(port,))

# update books

with self._lock:

self._ports_being_checked.append(port)

t.start()

def run(self):

try:

while True:

self._condition.acquire()

while len(self._ports_being_checked) >= self.threadcount:

# we wait for some threads to complete the task

self._condition.wait()

slots_available = self.threadcount - len(self._ports_being_checked)

self._condition.release()

print ("Checking {} - {}".format(self._next_port,


self._next_port+slots_available))

for i in xrange(slots_available):

self.start_another_thread()

except AllThreadsStarted, ex:

print ("All threads started ...")

except:

print_exc()

if __name__ == "__main__":

import sys

domain = sys.argv[1]

port_s = int(sys.argv[2])

port_e = int(sys.argv[3])

scanner = IPv4PortScanner(domain=domain, port_range=(port_s, port_e))

scanner.run()

Share Improve this answer Follow answered Sep 13 '19 at 14:49


Alex
2,043 3 21 27

I think that this one snippet could help you : http://www.coderholic.com/python-port-scanner/

0 Share Improve this answer Follow answered Oct 3 '14 at 7:24


Lukasz Ciesluk
698 1 16 29

socket.setdefaulttimeout(0.5)
This will make the program faster!

0 Share Improve this answer Follow answered Nov 28 '14 at 18:46


Muhammad Suleman
627 4 11 24

This answer is a good start, but I think it would be useful to explain why it will speed up the program,
perhaps with some references.
– Shepmaster
Dec 27 '14 at 3:10

socket.setdefualttimeout (time)

0 is used to keep trying to connect with port for perticular time...when you send request and
there is timeout set for 2 seconds so it will try to connect with port for 2 seconds....if there will
be no response from that port in 2 seconds....it will be count as a dead port

Share Improve this answer Follow answered Jul 16 '15 at 15:11


Nisarg
403 7 23

The following port scanner has a few constants defined at the top that you can modify as
needed:
0
PURPOSE -- help message for the command line

PORTS -- range of ports you would like scanned

POOL_SIZE -- number of processes to scan with


TIMEOUT -- how long to wait for server connection
Feel free to adapt this according to your requirements. Maybe add some command line
arguments?

#! /usr/bin/env python3

import argparse

import collections

import itertools

import multiprocessing

import operator

import socket

PURPOSE = 'Scan for open ports on a computer.'

PORTS = range(1 << 16)

POOL_SIZE = 1 << 8

TIMEOUT = 0.01

def main():

"""Get computer to scan, connect with process pool, and show open ports."""

parser = argparse.ArgumentParser(description=PURPOSE)

parser.add_argument('host', type=str, help='computer you want to scan')

host = parser.parse_args().host

with multiprocessing.Pool(POOL_SIZE, socket.setdefaulttimeout, [TIMEOUT]) \

as pool:

results = pool.imap_unordered(test, ((host, port) for port in PORTS))

servers = filter(operator.itemgetter(0), results)

numbers = map(operator.itemgetter(1), servers)

ordered = sorted(numbers)

print(f'Ports open on {host}:', *format_ports(ordered), sep='\n ')

field_names = 'family', 'socket_type', 'protocol', 'canon_name', 'address'

AddressInfo = collections.namedtuple('AddressInfo', field_names)

del field_names

def test(address):

"""Try connecting to the server and return whether or not it succeeded."""

host, port = address

for info in itertools.starmap(AddressInfo, socket.getaddrinfo(host, port)):

try:

probe = socket.socket(info.family, info.socket_type, info.protocol)

except OSError:

pass

else:

try:

probe.connect(info.address)

except OSError:

pass

else:

probe.shutdown(socket.SHUT_RDWR)

return True, port

finally:

probe.close()

return False, port

def format_ports(ports):

"""Convert port numbers into strings and show all associated services."""

if ports:

for port in ports:

try:

service = socket.getservbyport(port)

except OSError:

service = '?'

yield f'{port:<5} = {service}'

else:

yield 'None'

if __name__ == '__main__':

main()

Share Improve this answer Follow answered Mar 22 '19 at 13:22


Noctis Skytower
19.3k 15 73 104

You might also like