提问人:D3F4U1T 提问时间:9/26/2023 最后编辑:D3F4U1T 更新时间:10/6/2023 访问量:123
Paramiko 和 ssh2-python3 在高线程中无法按预期工作
Paramiko and ssh2-python3 not working as expected in high threads
问:
我想创建一个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:更改了代码,使其随机连接到多个 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!")
答: 暂无答案
评论