Example explore Python's approach to writing high-performance port scanners in parallel

Source: Internet
Author: User
About port Scanners
The Port Scan Tool (ports Scanner) is a tool for probing server or host open ports. is often used by computer administrators to confirm security policies and is used by attackers to identify operational network services on the target host.

A port scan definition is a client that sends a corresponding request to a range of server ports to confirm the ports that can be used. Although it is not a malicious network activity in itself, it is also an important means for network attackers to probe the target host service to exploit known vulnerabilities in the service. The primary use of port scanning is still to confirm the availability of a service for a remote machine.

Scanning multiple hosts to obtain a specific port is called Port Sweep (Portsweep) to obtain a specific service. For example, a computer worm based on a SQL service cleans up the same port on a large number of hosts to establish a TCP connection on port 1433.

Python implementation

The principle of the port scanner is very simple, is nothing more than the operation of the socket, can connect to determine that the port is open.

Import Socket DEF scan (port):   s = socket.socket ()   if s.connect_ex ((' localhost ', port) = = 0:     print port, ' ope N '   s.close () if __name__ = = ' __main__ ':   

So one of the simplest port scanners came out.
Wait, hello, half a day did not respond, that is because the socket is blocked, each connection to wait a long time to timeout.
We add it ourselves to the timeout.

S.settimeout (0.1)

Run again, it feels much faster.

Multi-threaded version

Import Socket Import Threading def scan (port):   s = socket.socket ()   s.settimeout (0.1)   if S.CONNECT_EX (' localhost ', port) = = 0:     print port, ' open '   s.close ()  if __name__ = = ' __main__ ':   threads = [Threading. Thread (Target=scan, args= (i,)) for I in Xrange (1,65536)]   

Run it, whoa, come on, come on, throw the wrong. Thread.error:can ' t start new thread.
Think about it, this process opened 65,535 threads, there are two possible, one is more than the maximum number of threads, one is more than the maximum number of socket handle. Linux can be modified by Ulimit.
If you do not modify the maximum limit, how to use multithreading do not error it?
Add a queue, turn into producer-consumer mode, and open a fixed thread.

Multithreading + Queue version

Import socket import threading from queue import Queue def scan (port):   s = socket.socket ()   s.settimeout (0.1)   If S.CONNECT_EX (' localhost ', port) = = 0:     print port, ' open '   s.close ()  def worker (): While not   Q.empty ():     port = q.get ()     try:       scan (port)     finally:       q.task_done ()  if __name__ = = ' __main__ ':   q = Queue ()   map (Q.put,xrange (1,65535))   threads = [Threading. Thread (Target=worker) for I in xrange (+)]   map (lambda X:x.start (), threads)   

Here, 500 threads are opened, and the task is continuously taken from the queue.

multiprocessing+ Queue version
You can't open 65,535 of processes? Or with the producer-consumer model

Import multiprocessing def scan (port):   s = socket.socket ()   s.settimeout (0.1)   if S.CONNECT_EX (' localhost ', port) = = 0:     print port, ' open '   s.close ()  def worker (Q): While not   Q.empty ():     port = Q.get ()     try:       scan (port)     finally:       q.task_done ()  if __name__ = = ' __main__ ':   q = Multiprocessing. Joinablequeue ()   map (Q.put,xrange (1,65535))   jobs = [multiprocessing. Process (Target=worker, args= (Q,)) for I in Xrange (100)]   

Note here that the queue is passed as a parameter to the worker, because it is the queue of the safe of the process, otherwise it will error.
Also useful is joinablequeue (), as the name implies is can join ().

Gevent version of Spawn

from gevent import Monkey; Monkey.patch_all (); Import gevent Import Socket ... if __name__ = = ' __main__ ':   threads = [Gevent.spawn (scan, i) for I in Xrange (1,65536)]   

Note that the monkey patch must be exception before the patch, or keyerror. For example, you can't import threading first, then monkey patches.

Pool version of Gevent

from gevent import Monkey; Monkey.patch_all (); Import socket from Gevent.pool Import Pool ... if __name__ = = ' __main__ ':   pool = Pool (+)   Pool.map (Scan,xrange (1, 65536))   

Concurrent.futures version

Import socket from queue import queue from Concurrent.futures import Threadpoolexecutor ... if __name__ = = ' __main__ ': 
  
   q = Queue ()   map (Q.put,xrange (1,65536)) with   Threadpoolexecutor (max_workers=500) as executor: for     i in Range (500):       
  
  • Contact Us

    The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

    If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.