Python - Paramiko 客户端通过 SSL 套接字 - 非阻塞问题
Python - Paramiko Client over SSL Socket - Non-Blocking Issue
我写了一些 Python 代码,使用户能够使用编辑后的 HTML 文件更新我的服务器并上传图像。但是我遇到了一些连接问题。
在服务器端,我是 运行 VMware 中的 Ubuntu 虚拟机,位于 pfSense 路由器 运行 HAproxy 后面。该代理使具有正确客户端证书的用户能够通过 SSH 连接到正确的机器。现在这已经运行了很长时间,没有任何问题。
我认为我的问题是在我的 SFTP 代码中,由于 SSL 包装器不是非阻塞的,套接字关闭了。但是我想不出也找不到修复代码的方法。特别是因为我不是使用这些软件包的专家。 Paramiko 客户端和 SFTP 客户端均已在具有 VPN 连接的远程服务器上分别进行了测试,它们在那种情况下运行良好。 SSL 套接字使用的证书也可以正常工作。
版本:
Python: 3.8.3
openssl: 1.1.1.f
参数:2.7.2
import socket
import ssl
import paramiko
class GE_SFTP_Client:
def __init__(self, Username, Password):
self.Username = Username
self.Password = Password
context = ssl.create_default_context(ssl.Purpose.SERVER_AUTH) # Verify Server cert
context.load_cert_chain(certfile=_client_cert, keyfile=_client_key) # Load Client cert
context.set_alpn_protocols(['ssh/2.0'])
self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.conn = context.wrap_socket(self.s, server_side=False, server_hostname=_target_host)
self.conn.connect((_proxy_host, _proxy_port))
self.client = paramiko.SSHClient()
self.client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
self.connected_status = False
SSH_Connection_Tries = 0
while SSH_Connection_Tries < 4: # Try 4 times to connect.
try:
self.client.connect(
hostname=_target_host, username=self.Username, password=self.Password,
sock=self.conn, timeout=200, banner_timeout=200, auth_timeout=200
)
self.connected_status = True
break
except:
SSH_Connection_Tries += 1
pass
if self.connected_status:
self.sftp = self.client.open_sftp()
def GE_SFTP_ClientEnd(self):
try:
self.sftp.close()
except AttributeError:
pass
self.client.close()
self.conn.close()
self.s.close()
使用 paramiko SFTP 客户端 get() 一些图像时的输出示例。
succes! /images/fulls/3.jpg
succes! /images/fulls/2.jpg
succes! /images/fulls/9.jpg
Socket exception: A non-blocking socket operation could not be completed immediately (10035)
谢谢,如有任何建议,我们将不胜感激!
我放弃了使用 SSL 包中的标准 SSL 包装器的想法,而是找到了一种不同的做事方式,即使用 asyncssh 包与 asyncio 相结合。因为他们一起为我提供了解决这个问题所需的工具。
连接现在更加稳定,即使在下载更大的文件时也是如此。我希望这也能帮助其他人! :)
import socket
import ssl
import asyncio
import asyncssh
class SSL_Socket:
async def create_connection(self, protocol_factory, host, port):
loop = asyncio.get_event_loop()
context = ssl.create_default_context(ssl.Purpose.SERVER_AUTH) # Verify Server cert
context.load_cert_chain(certfile=_client_cert, keyfile=_client_key) # Load Client cert
context.set_alpn_protocols(['ssh/2.0'])
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((_proxy_host, _proxy_port))
return (await loop.create_connection(protocol_factory, sock=s, ssl=context, server_hostname=host))
async def WorkingExample():
async with asyncssh.connect(_target_host, tunnel=SSL_Socket(), username=Username, password=Password, known_hosts=_known_hosts) as conn:
async with conn.start_sftp_client() as sftp:
print(await sftp.stat(f'{remote_dir}/index.html'))
我写了一些 Python 代码,使用户能够使用编辑后的 HTML 文件更新我的服务器并上传图像。但是我遇到了一些连接问题。
在服务器端,我是 运行 VMware 中的 Ubuntu 虚拟机,位于 pfSense 路由器 运行 HAproxy 后面。该代理使具有正确客户端证书的用户能够通过 SSH 连接到正确的机器。现在这已经运行了很长时间,没有任何问题。
我认为我的问题是在我的 SFTP 代码中,由于 SSL 包装器不是非阻塞的,套接字关闭了。但是我想不出也找不到修复代码的方法。特别是因为我不是使用这些软件包的专家。 Paramiko 客户端和 SFTP 客户端均已在具有 VPN 连接的远程服务器上分别进行了测试,它们在那种情况下运行良好。 SSL 套接字使用的证书也可以正常工作。
版本:
Python: 3.8.3
openssl: 1.1.1.f
参数:2.7.2
import socket
import ssl
import paramiko
class GE_SFTP_Client:
def __init__(self, Username, Password):
self.Username = Username
self.Password = Password
context = ssl.create_default_context(ssl.Purpose.SERVER_AUTH) # Verify Server cert
context.load_cert_chain(certfile=_client_cert, keyfile=_client_key) # Load Client cert
context.set_alpn_protocols(['ssh/2.0'])
self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.conn = context.wrap_socket(self.s, server_side=False, server_hostname=_target_host)
self.conn.connect((_proxy_host, _proxy_port))
self.client = paramiko.SSHClient()
self.client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
self.connected_status = False
SSH_Connection_Tries = 0
while SSH_Connection_Tries < 4: # Try 4 times to connect.
try:
self.client.connect(
hostname=_target_host, username=self.Username, password=self.Password,
sock=self.conn, timeout=200, banner_timeout=200, auth_timeout=200
)
self.connected_status = True
break
except:
SSH_Connection_Tries += 1
pass
if self.connected_status:
self.sftp = self.client.open_sftp()
def GE_SFTP_ClientEnd(self):
try:
self.sftp.close()
except AttributeError:
pass
self.client.close()
self.conn.close()
self.s.close()
使用 paramiko SFTP 客户端 get() 一些图像时的输出示例。
succes! /images/fulls/3.jpg
succes! /images/fulls/2.jpg
succes! /images/fulls/9.jpg
Socket exception: A non-blocking socket operation could not be completed immediately (10035)
谢谢,如有任何建议,我们将不胜感激!
我放弃了使用 SSL 包中的标准 SSL 包装器的想法,而是找到了一种不同的做事方式,即使用 asyncssh 包与 asyncio 相结合。因为他们一起为我提供了解决这个问题所需的工具。
连接现在更加稳定,即使在下载更大的文件时也是如此。我希望这也能帮助其他人! :)
import socket
import ssl
import asyncio
import asyncssh
class SSL_Socket:
async def create_connection(self, protocol_factory, host, port):
loop = asyncio.get_event_loop()
context = ssl.create_default_context(ssl.Purpose.SERVER_AUTH) # Verify Server cert
context.load_cert_chain(certfile=_client_cert, keyfile=_client_key) # Load Client cert
context.set_alpn_protocols(['ssh/2.0'])
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((_proxy_host, _proxy_port))
return (await loop.create_connection(protocol_factory, sock=s, ssl=context, server_hostname=host))
async def WorkingExample():
async with asyncssh.connect(_target_host, tunnel=SSL_Socket(), username=Username, password=Password, known_hosts=_known_hosts) as conn:
async with conn.start_sftp_client() as sftp:
print(await sftp.stat(f'{remote_dir}/index.html'))