简体   繁体   中英

Nested SSH using Python Paramiko

I have this scenario:

Local-host --------- jump-host ------- target-machine

I am trying to write a code in Python using Paramiko to first SSH from local-host to jump-host and then SSH from jump-host to the target-machine. From the target-machine, I want to capture some outputs and store them locally either as a variable or as a file (haven't got to that point yet). I found an example from Stack Overflow where they talk about using nested SSH with Paramiko, and I follow it but I get stuck here:

My code:

enter code here

#!/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('192.168.115.103',username='osmanl',password='xxxxxx')
#
vmtransport = vm.get_transport()
dest_addr = ('192.168.115.103', 22)
local_addr = ('127.0.0.1', 22)
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')
jhost.connect('10.103.53.26', username='latiu', password='xxxx', sock=vmchannel)
#
stdin, stdout, stderr = rtr.exec_command("show version | no-more")
#
print stdout.readline()
#
jhost.close()
vm.close()
# End

When I run the above, I get this error:

$ python sshvm.py
Traceback (most recent call last):
  File "sshvm.py", line 28, in <module>
    jhost.load_host_keys('/home/osmanl/.ssh/known_hosts')
  File "/usr/lib/python2.7/site-packages/paramiko-1.15.2-py2.7.egg/paramiko/client.py", line 121, in load_host_keys
    self._host_keys.load(filename)
  File "/usr/lib/python2.7/site-packages/paramiko-1.15.2-py2.7.egg/paramiko/hostkeys.py", line 94, in load
    with open(filename, 'r') as f:
IOError: [Errno 2] No such file or directory: '/home/osmanl/.ssh/known_hosts'

Try the following edited code, it should work:

#!/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('192.168.115.103', username='osmanl', password='xxxxxx')
#
vmtransport = vm.get_transport()
dest_addr = ('10.103.53.26', 22) #edited#
local_addr = ('192.168.115.103', 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('10.103.53.26', username='latiu', password='xxxx', sock=vmchannel)
#
stdin, stdout, stderr = jhost.exec_command("show version | no-more") #edited#
#
print stdout.read() #edited#
#
jhost.close()
vm.close()
# End

I know OP has specifically asked for Paramiko but i can do this very easily with fabric . Here is my solution

from fabric import Connection

out = Connection('host1').run('host2 uptime')
print(out.stdout.strip())

This works just fine for me, and i have the output stored in a variable as well.

I found this easiest route to login to remote server via jumphost.This works amazing!

    link :https://pypi.org/project/jumpssh/
    import jumpssh

After reading accepted answer got bit confused about source and destintation addresses https://stackoverflow.com/a/36096801/1303321 , so refering to https://www.programcreek.com/python/?code=grycap%2Fim%2Fim-master%2FIM%2FSSH.py here is what I ended up with working solution:

def __run_remote_command(self, command: str) -> Tuple[str, str]:
        """
        Private method to run a command in the remote machine via SSH.
        This method establishes the connection; fires the command; collects the output then closes the connection
        :param command: command which needs to be invoked in the remote machine
        :return (stdout, stderr) : Tuple of string containing the standard output and error of the command execution
        """
        stdout, stderr = '', ''
        with paramiko.SSHClient() as jhost:
            jhost.set_missing_host_key_policy(paramiko.AutoAddPolicy())
            private_key = paramiko.RSAKey.from_private_key_file(filename=RESOURCES_SERVER_SSH_KEY)
            try:
                jhost.connect(hostname=JUMPHOST_SERVER_URL, username=RESOURCES_SERVER_SSH_USERNAME, pkey=private_key)
                jhost_transport = jhost.get_transport()
                dest_addr = (RESOURCES_SERVER_URL, 22)
                local_addr = (JUMPHOST_SERVER_URL, 22)
                jhost_channel = jhost_transport.open_channel("direct-tcpip", dest_addr, local_addr)

                with paramiko.SSHClient() as target_server:
                    target_server.set_missing_host_key_policy(paramiko.AutoAddPolicy())
                    target_server_private_key = paramiko.RSAKey.from_private_key_file(filename=RESOURCES_SERVER_SSH_KEY)
                    target_server.connect(hostname=RESOURCES_SERVER_URL, username=RESOURCES_SERVER_SSH_USERNAME, pkey=target_server_private_key, sock=jhost_channel)

                    self.logger.info(f"Invoking {command} on remote host {RESOURCES_SERVER_URL} over SSH")
                    _, stdout, stderr = target_server.exec_command(command)
                    stdout = stdout.read().decode('utf-8')
                    stderr = stderr.read().decode('utf-8')
            except SSHException as ssh_ex:
                self.logger.error(f"Failed to connect to {RESOURCES_SERVER_URL} ")
                self.logger.exception(ssh_ex, exc_info=True)
                raise BaseException()
        return (stdout, stderr)

I get an "everything in one line " output on this code and not sure why . Any ideas? Here is an example :

The use of this system may be monitored and recorded for *\r\n* security, administrative or other purposes. By proceeding to log on, you expressly consent to such    *\r\n* monitoring and/or recording.                                                                          *\r\n*********************************************************************************************************\r\nCisco IOS Software, C3750 Software (C3750-IPSERVICESK9-M), Version 15.0(2)SE11, RELEASE SOFTWARE (fc3)\r\nTechnical Support: http://www.cisco.com/techsupport\r\nCopyright (c) 1986-2017 by Cisco Systems, Inc.\r\nCompiled Sat 19-Aug-17 09:28 by prod_rel_team\r\n\r\nROM: Bootstrap program is C3750 boot loader

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM