Paramiko: Using paramiko as ssh implementation for ProxyCommand.

Created on 21 Feb 2017  路  5Comments  路  Source: paramiko/paramiko

Recently I had to implement an automation script in python, that would crawl over a wide range of machines not necessarily reachable from the machine that the script would run on. Most functionalities presented in paramiko couldn't really make it, as I couldn't use SSHKeys, password prompts were out of the question, and the firewall between me and the other machines would block any attempt of utilizing any port forwarding scheme.

When it came to ProxyCommand, I found out that it only used a simple popen() to do it's job. So using ProxyCommand('ssh x.x.x.x nc y.y.y.y') was no good, because of the password prompt that blocked the automation.

After some research, I came up with something that looked similarly to the code presented here:
https://stackoverflow.com/questions/42208655/paramiko-nest-ssh-session-to-another-machine-while-preserving-paramiko-function/42209376

I was wondering since, are there any reasons behind not implementing it in paramiko? I would love to have something like this inside the library, instead of trying to hack my way through.

Most helpful comment

If I'm reading you correctly, this is already natively possible in Paramiko by just handing an initialized Transport (eg created by hand or via SSHClient) to another Transport as its socket argument; it's effectively implementing the equivalent of ProxyJump in newer OpenSSH versions. Leverages the direct-tcpip SSH session/request type.

I have some code in Fabric 2 which will be public soon that leverages exactly this and lets you infinitely nest gateway/jump hosts, but at heart all it's doing is the abovementioned Transport-in-Transport stuff (because Transport acts socket-like).

If I'm missing something, let me know.

All 5 comments

If I'm reading you correctly, this is already natively possible in Paramiko by just handing an initialized Transport (eg created by hand or via SSHClient) to another Transport as its socket argument; it's effectively implementing the equivalent of ProxyJump in newer OpenSSH versions. Leverages the direct-tcpip SSH session/request type.

I have some code in Fabric 2 which will be public soon that leverages exactly this and lets you infinitely nest gateway/jump hosts, but at heart all it's doing is the abovementioned Transport-in-Transport stuff (because Transport acts socket-like).

If I'm missing something, let me know.

@bitprophet Did this code example ever make it out into the public? I am trying to find a way to do exactly this right now and would love to see the best practice for doing it.

The example I Was talking about is in the answer to the SO question (I am the author of both the question and the answer). I updated it recently, so it is now working with a full support of timeouts.

guys i need help not working for me i am using python 3

error
File "c:\Users\Humberto.Perez\Desktop\Exercise Files\Ch2\example paramiko1.py", line 28
print stdout.read() #edited#
^
SyntaxError: invalid syntax

-===code -===

!/usr/bin/python

#

Paramiko

#
import paramiko
import sys
import subprocess
#

we instantiate a new object referencing paramiko's SSHClient class

#
vm=paramiko.SSHClient()
vm.set_missing_host_key_policy(paramiko.AutoAddPolicy())
vm.connect('172.19.11.27',username='hperez',password='pass1')
#
vmtransport = vm.get_transport()
dest_addr = (' 2.2.2.2', 22) #edited#
local_addr = ('172.19.11.27', 22) #edited#
vmchannel = vmtransport.open_channel("direct-tcpip", dest_addr, local_addr)

#
jhost=paramiko.SSHClient()
jhost.set_missing_host_key_policy(paramiko.AutoAddPolicy())

jhost.load_host_keys('/home/osmanl/.ssh/known_hosts') #disabled

jhost.connect('2.2.2.2', username='hperez', password='pass2', sock=vmchannel)
#
stdin, stdout, stderr = jhost.exec_command("show version ") #edited#
#
print stdout.read() #edited#
#
jhost.close()
vm.close()

End

-===if i put

print ( stdout.read() )

more errors compare to before

File "c:\Users\Humberto.Perez\Desktop\Exercise Files\Ch2\example paramiko1.py", line 13, in
vm.connect('172.19.11.27',username='hperez',password='pass1')
File "C:\Users\Humberto.Perez\AppData\Local\Programs\Python\Python37\lib\site-packages\paramiko\client.py", line 424, in connect
passphrase,
File "C:\Users\Humberto.Perez\AppData\Local\Programs\Python\Python37\lib\site-packages\paramiko\client.py", line 714, in _auth
raise saved_exception
File "C:\Users\Humberto.Perez\AppData\Local\Programs\Python\Python37\lib\site-packages\paramiko\client.py", line 701, in _auth
self._transport.auth_password(username, password)
File "C:\Users\Humberto.Perez\AppData\Local\Programs\Python\Python37\lib\site-packages\paramiko\transport.py", line 1381, in auth_password
return self.auth_handler.wait_for_response(my_event)
File "C:\Users\Humberto.Perez\AppData\Local\Programs\Python\Python37\lib\site-packages\paramiko\auth_handler.py", line 226, in wait_for_response
raise e
paramiko.ssh_exception.AuthenticationException: Authentication failed.
PS C:\Users\Humberto.Perez\Desktop\Exercise Files>

Hi MrMino,

I tried your script but got below error ->

PS C:\Users\cbqz9250\Downloads\Script> python Jump.py
Traceback (most recent call last):
File "Jump.py", line 7, in
vm.connect('130.140.173.76',username='MHATRE.Pranav',password='K[!Spz2A')
File "C:\Python27\lib\site-packages\paramiko\client.py", line 343, in connect
retry_on_signal(lambda: sock.connect(addr))
File "C:\Python27\lib\site-packages\paramiko\util.py", line 280, in retry_on_signal
return function()
File "C:\Python27\lib\site-packages\paramiko\client.py", line 343, in
retry_on_signal(lambda: sock.connect(addr))
File "C:\Python27\libsocket.py", line 228, in meth
return getattr(self._sock,name)(*args)
socket.error: [Errno 10060] A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond
PS C:\Users\cbqz9250\Downloads\Script>

Can you please share your expertise.

Was this page helpful?
0 / 5 - 0 ratings