Paramiko 和 ssh2-python3 在高线程中无法按预期工作

Paramiko and ssh2-python3 not working as expected in high threads

提问人:D3F4U1T 提问时间:9/26/2023 最后编辑:D3F4U1T 更新时间:10/6/2023 访问量:123

问:

我想创建一个SSH检查器,它使用Python检查某些服务器的用户密码。
我知道将它用于邪恶工具是非法的,但我创建它是为了研究和学习目的。(主要学习线程和安全性的细节)。

让我非常好奇的是,它对连接数量施加了限制,我想知道原因和方式。

我使用过 paramiko 和 ssh2-python3,它们在高线程执行时都无法正常工作。(我说的是 200、500 甚至 1000)

我尝试了什么?

对于 paramiko,我在 20 个线程中使用它,对于 ssh2-python3,我在 50/60 ish 线程中使用它。

发生了什么事?

使用paramiko时,我遇到了一些与SSH Banner相关的错误(即使我的计算机在我的本地网络中)。

问题主要从 12 个线程开始。
似乎 paramiko 不喜欢多线程。

paramiko.ssh_exception.SSHException: Error reading SSH protocol banner

这是例外情况的一部分

Exception (client): Error reading SSH protocol banner
Traceback (most recent call last):
File "/home/d3f4u1t/Work/Programming_2/Python/Labs/Lab10_SSH/.venv/lib/python3.11/site-packages/paramiko/transport.py", line 2292, in \_check_banner
buf = self.packetizer.readline(timeout)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/d3f4u1t/Work/Programming_2/Python/Labs/Lab10_SSH/.venv/lib/python3.11/site-packages/paramiko/packet.py", line 374, in readline
buf += self.\_read_timeout(timeout)
^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/d3f4u1t/Work/Programming_2/Python/Labs/Lab10_SSH/.venv/lib/python3.11/site-packages/paramiko/packet.py", line 603, in \_read_timeout
raise EOFError()
EOFError

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "/home/d3f4u1t/Work/Programming_2/Python/Labs/Lab10_SSH/.venv/lib/python3.11/site-packages/paramiko/transport.py", line 2113, in run
self.\_check_banner()
File "/home/d3f4u1t/Work/Programming_2/Python/Labs/Lab10_SSH/.venv/lib/python3.11/site-packages/paramiko/transport.py", line 2296, in \_check_banner
raise SSHException(
paramiko.ssh_exception.SSHException: Error reading SSH protocol banner

and the exception goes on and on, repeating as it checks more and more...

尽管这些异常正在发生,但我还是获得了一些成功的匹配,这是不可靠的,我高度怀疑这是因为线程。

对于 ssh2-python3,它会在 50/60 ish 线程后停止报告成功的匹配。

我期待什么?

我希望它们在高线程中按预期工作,但事实并非如此。

主要问题

  1. 这里发生了什么问题?
  2. 有什么方法可以解决这个问题?

编辑1:

下面是一个最小的可重现示例:

帕拉米科

我在这里有很多例外......

  • 编辑 2:更改了代码,使其随机连接到多个 ip,但横幅错误不会停止
import random
from concurrent.futures import ThreadPoolExecutor
from itertools import product

import paramiko


def paramiko_core(server, port, username, password):
    cli = paramiko.SSHClient()
    cli.set_missing_host_key_policy(paramiko.AutoAddPolicy())

    try:
        cli.connect(
            server,
            port,
            username,
            password,
            banner_timeout=150,
        )
        cli.close()
    except paramiko.SSHException:
        ...


# Put some dummy or safe ips in the file (I put about 40 or so)
with open("sv_list.txt") as f:
    list_ips = f.readlines()
# And put a valid ip address here
list_ips.insert(20, "127.0.0.1")
# Replace a valid username here...
list_username = ["user1", "user2", "real_user", "user3", "user4", "user5"]
# Replace a valid password here...
list_password = ["pass1", "pass2", "real_pass", "pass3", "pass4", "pass5"]

with ThreadPoolExecutor(max_workers=16) as executor:
    comb_list = list(product(list_ips, list_username, list_password))
    random.shuffle(comb_list)
    for ip, username, password in comb_list:
        executor.submit(paramiko_core, ip.strip(), 22, username, password)

ssh2-python3

无论max_worker是高还是低,我得到的结果都不一致。
虽然我设置得越高,它就越不一致。

  • 编辑 2:我更改为连接到多个 ip,它确实有所改善,但不是 100% 可靠。10 次中有 8 次正确报告。
  • 因此,这可能与与单个服务器的连接过多有关。
import random
import socket
from concurrent.futures import ThreadPoolExecutor
from itertools import product

from ssh2.exceptions import (
    AuthenticationError,
    SocketDisconnectError,
    SocketRecvError,
    Timeout,
)
from ssh2.session import Session


def ssh2_core(server, port, username, password):
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.settimeout(4)

    try:
        sock.connect((server, port))
    except OSError:
        return False

    session = Session()
    session.set_timeout(1000)

    try:
        session.handshake(sock)
        session.userauth_password(username, password)
        session.open_session()
    except Timeout:
        return False
    except SocketRecvError:
        return False
    except SocketDisconnectError:
        return False
    except AuthenticationError:
        return False

    return True


# Put some dummy or safe ips in the file (I put about 40 or so)
with open("sv_list.txt") as f:
    list_ips = f.readlines()
# And put a valid ip address here
list_ips.insert(20, "127.0.0.1")

list_username = [
    *[f"user{i}" for i in range(3)],
    "real_user",  # Replace a valid username here...
    *[f"user{i}" for i in range(3)],
]

list_password = [
    *[f"pass{i}" for i in range(3)],
    "real_pass",  # Replace a valid password here...
    *[f"pass{i}" for i in range(3)],
]

result = []
with ThreadPoolExecutor(max_workers=120) as executor:
    comb_list = list(product(list_ips, list_username, list_password))
    random.shuffle(comb_list)
    for ip, username, password in comb_list:
        result.append(executor.submit(ssh2_core, ip.strip(), 22, username, password))

if True in [rslt.result() for rslt in result]:
    print("This time it worked!")
else:
    print("This time it failed!")
python 安全 ssh python-multithreading paramiko

评论

0赞 Martin Prikryl 9/26/2023
我们需要最少的可重复示例
0赞 D3F4U1T 9/27/2023
@MartinPrikryl +1。我添加了一个最小的可重现示例。
0赞 Martin Prikryl 9/27/2023
这难道不是关于您的服务器无法(或拒绝)处理几乎同时打开的这么多连接吗?
0赞 D3F4U1T 10/6/2023
@MartinPrikryl 感谢您指出这个问题。它以某种方式提高了成功率,但 paramiko 仍然抱怨 SSH 协议横幅。我不知道如何修复它,或者它是否是一个无害的错误。

答: 暂无答案