简体   繁体   中英

Python3.5 Asyncio TCP Scanner

I am new to Python3.5, and Async in general with the exception of minor use of Twisted in Python 2.7. I'm building this into a larger application and I need a small portion, as opposed to a monolithic framework, to perform TCP port scanning.

import asyncio
from random import SystemRandom

def run(task, *, loop=None):
    if loop is None:
        loop = asyncio.get_event_loop()
    return loop.run_until_complete(asyncio.ensure_future(task, loop=loop))

async def scanner(ip, port, loop=None):
    fut = asyncio.open_connection(ip, port, loop=loop)
    try:
        reader, writer = await asyncio.wait_for(fut, timeout=0.5) # This is where it is blocking?
        print("{}:{} Connected".format(ip, port))
    except asyncio.TimeoutError:
        pass

def scan(ips, ports, randomize=False):
    if randomize:
        rdev = SystemRandom()
        ips = rdev.shuffle(ips)
        ports = rdev.shuffle(ports)
    for port in ports:
        for ips in ips:
            run(scanner(ip, port))

 ips = ["192.168.0.{}".format(i) for i in range(1, 255)]
 ports = [22, 80, 443, 8080]
 scan(ips, ports)

This is still taking as long as a single thread would take. How can I turn this into an async TCP scanner?

run_until_complete is blocking, the execution stops there and waits until the one scan ends, then the next one...

You should schedule all (or some part) of tasks and wait for all of them with wait .

import asyncio
from random import SystemRandom

def run(tasks, *, loop=None):
    if loop is None:
        loop = asyncio.get_event_loop()
    # waiting for all tasks
    return loop.run_until_complete(asyncio.wait(tasks))

async def scanner(ip, port, loop=None):
    fut = asyncio.open_connection(ip, port, loop=loop)
    try:
        reader, writer = await asyncio.wait_for(fut, timeout=0.5) # This is where it is blocking?
        print("{}:{} Connected".format(ip, port))
    except asyncio.TimeoutError:
        pass
    # handle connection refused and bunch of others
    except Exception as exc:
        print('Error {}:{} {}'.format(ip, port, exc))

def scan(ips, ports, randomize=False):
    loop = asyncio.get_event_loop()
    if randomize:
        rdev = SystemRandom()
        ips = rdev.shuffle(ips)
        ports = rdev.shuffle(ports)

    # let's pass list of task, not only one
    run([scanner(ip, port) for port in ports for ip in ips])

ips = ["192.168.0.{}".format(i) for i in range(1, 255)]
ports = [22, 80, 443, 8080]
scan(ips, ports)

I've also added except block to catch rest of exceptions, including most common connection refused.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM