我试图paramiko通过netcat来弹回SSH会话:
MyLocalMachine ----||----> MiddleMachine --(netcat)--> AnotherMachine
('localhost') (firewall) ('1.1.1.1') ('2.2.2.2')
Run Code Online (Sandbox Code Playgroud)
MyLocalMachine到的
直接连接AnotherMachineMiddleMachine将不接受任何尝试打开与之连接的Direct-tcpip通道的尝试AnotherMachinesshpassPExpect我可以使用以下代码部分实现此目的:
cli = paramiko.SSHClient()
cli.set_missing_host_key_policy(paramiko.AutoAddPolicy())
proxy = paramiko.ProxyCommand('ssh user@1.1.1.1 nc 2.2.2.2 22')
cli.connect(hostname='2.2.2.2', username='user', password='pass', sock=proxy)
Run Code Online (Sandbox Code Playgroud)
问题是,因为ProxyCommand使用subprocess.Popen运行给定的命令,它要求我给密码“特设”,从用户输入(也,它需要在操作系统MyLocalMachine已ssh安装-这是情况并非总是如此)。
由于ProxyCommand的方法(recv,send)是对适当POpen方法的简单绑定,我想知道是否有可能欺骗paramiko客户端使用另一个客户端的会话作为代理?
更新15.05.18:添加了丢失的代码(复制粘贴的上帝对我不利)。
TL; DR:我设法通过简单的exec_command调用和一个伪装成a的类来做到这一点sock。
总结一下:
nc在代理主机上安装netcat() -尽管可以提供基本netcat功能(在套接字和stdin / stdout之间移动数据)的任何设备都可以使用。因此,这里是解决方案:
以下代码定义了一个可以代替的类paramiko.ProxyCommand。它提供了标准socket对象执行的所有方法。此类的init方法采用exec_command()通常返回的3-tupple :
注意:它已经由我进行了广泛的测试,但是您不应将任何事情视为理所当然。这是一个hack。
import paramiko
import time
import socket
from select import select
class ParaProxy(paramiko.proxy.ProxyCommand):
def __init__(self, stdin, stdout, stderr):
self.stdin = stdin
self.stdout = stdout
self.stderr = stderr
self.timeout = None
self.channel = stdin.channel
def send(self, content):
try:
self.stdin.write(content)
except IOError as exc:
raise socket.error("Error: {}".format(exc))
return len(content)
def recv(self, size):
try:
buffer = b''
start = time.time()
while len(buffer) < size:
select_timeout = self._calculate_remaining_time(start)
ready, _, _ = select([self.stdout.channel], [], [],
select_timeout)
if ready and self.stdout.channel is ready[0]:
buffer += self.stdout.read(size - len(buffer))
except socket.timeout:
if not buffer:
raise
except IOError as e:
return ""
return buffer
def _calculate_remaining_time(self, start):
if self.timeout is not None:
elapsed = time.time() - start
if elapsed >= self.timeout:
raise socket.timeout()
return self.timeout - elapsed
return None
def close(self):
self.stdin.close()
self.stdout.close()
self.stderr.close()
self.channel.close()
Run Code Online (Sandbox Code Playgroud)
下面显示了如何使用上述类解决问题:
# Connecting to MiddleMachine and executing netcat
mid_cli = paramiko.SSHClient()
mid_cli.set_missing_host_key_policy(paramiko.AutoAddPolicy())
mid_cli.connect(hostname='1.1.1.1', username='user', password='pass')
io_tupple = mid_cli.exec_command('nc 2.2.2.2 22')
# Instantiate the 'masquerader' class
proxy = ParaProxy(*io_tupple)
# Connecting to AnotherMachine and executing... anything...
end_cli = paramiko.SSHClient()
end_cli.set_missing_host_key_policy(paramiko.AutoAddPolicy())
end_cli.connect(hostname='2.2.2.2', username='user', password='pass', sock=proxy)
end_cli.exec_command('echo THANK GOD FINALLY')
Run Code Online (Sandbox Code Playgroud)
等等。
| 归档时间: |
|
| 查看次数: |
1512 次 |
| 最近记录: |