python 我试图使一个端口扫描仪,但它的极端缓慢和无效,由于我的条件

aor9mmx1  于 2022-12-28  发布在  Python
关注(0)|答案(3)|浏览(121)

细节是,我相信有很多事情在我的for循环中进行,我想知道是否有一个更有效的方法来处理这个任务
我希望使用大量的if/elif语句将端口Map到服务,但是速度很慢。我如何在for循环之外将端口Map到服务以获得更快的速度

import socket
import pyfiglet
from colorama import Fore
ascii_banner = pyfiglet.figlet_format("Port Scanner")
print(ascii_banner)
remoteserver = input('please enter your target:')
remoteserverIP = socket.gethostbyname(remoteserver) # name resoultion
sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
for port in range(1,22):
    result = sock.connect_ex((remoteserverIP,port))
    if result == 0:
        result = port
        print(f"{result} is open")
        if result == 80:
            print(' Service:http')
        elif result == 21:
            print('Service:ftp')
        elif result == 22:
            print('Service:ssh')
        elif result == 23:
            print('Service:telnet')
        elif result == 554:
            print('Service:RTSP')
        elif result == 5432:
            print('Service:PostgreSQL')
        elif result == 3306:
            print('Service:MySQL')
carvr3hs

carvr3hs1#

我只需要将它们Map到{ port: service, }的dict中,您可以使用内置方法创建dict中的键列表,然后根据字典中是否存在端口Map来输出。

import socket

common_services = {
  80: "Service:http",
  21: "Service:ftp",
  22: "Service:ssh",
  12: "Service:telnet",
  554: "Service:RTSP",
  5432: "Service:PostgreSQL",
  3306: "Service:MySQL",
}

known_ports = list(common_services.keys())
sock = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

for port in range(1,22):
    result = sock.connect_ex((ip,port))
    if result == 0:
        msg = f"{port} is open, {common_services[port]}" if port in known_ports else f"{port} is open"
        print(msg)
a7qyws3x

a7qyws3x2#

除了@rzz的回答之外,谁说的服务可以配置在不同的端口上是正确的:你可以使用socket.getservbyport()函数来确定端口的服务名,而不需要使用手工的if语句链,它不一定包含你想要的所有服务,所以你需要捕获OSError,并使用其他人建议的字典。
但是,我不确定您遇到的主要速度瓶颈是if语句的序列,您这么说是因为您分析了应用程序,还是仅仅是一种直觉?
最有可能的原因是您正在按顺序执行所有这些请求。您可能希望同时触发尽可能多的请求,然后在它们到来时打印结果。或者,您将它们添加到一个结构中,并在最后按您希望的排序打印它们。
您可以使用system threads或async/await来实现这一点。我更喜欢第二种方法,因为您基本上只受I/O约束,并且可以避免上下文切换开销。
下面是一个工作示例:

import asyncio
import socket

async def scan(host, port, timeout, results):
    try:
        await asyncio.wait_for(asyncio.open_connection(host, port), timeout=timeout)
        results[port] = "open"
    except TimeoutError:
        results[port] = "timeout"
    except Exception as e:  # you will want to better catch this and differentiate accordingly
        results[port] = str(e)

async def main():
    hostname = 'www.google.com'
    results = {}
    ports = [21, 80, 554]
    host = socket.gethostbyname(hostname)

    await asyncio.gather(*[scan(host, port, 2, results) for port in ports])

    for port in ports:
        print(f"Port {port} of service {socket.getservbyport(port)} result: {results[port]}.")

asyncio.run(main())
x6yk4ghg

x6yk4ghg3#

要减少循环中if和else的数量,可以使用字典。
然而,在开发端口扫描程序时,需要记住的一点是,服务可以配置在不同的端口上。因此,端口可能不是正在运行的服务的有效引用,从而使代码和结果/输出不太一致。
您可以尝试返回服务的横幅,例如:

s.recv(1024).decode()

套接字将返回1024字节缓冲区大小的横幅,然后我们将其解码为字符串。您需要添加如下内容:

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
banner = s.recv(1024).decode()

版本1:添加对portscanner的引用和使用横幅的示例:reference

相关问题