I need to write a python script which connects to the host over SSH and then somehow connects to a service sitting on localhost and performs a little interactive session.
What first came to mind is to use Paramiko to do a local port forwarding and then use Pythons's sockets library to communicate with the service.
But working with Paramiko was quite a challenge and I haven't figured out how to fix some issues.
So I switched to pxssh and used just simple scenario:
conn.sendline('telnet {} {}'.format('localhost', port)
conn.expect('PASSWORD:')
conn.sendline(password)
...
But that telnet thing really bothers me.
And I think it's possible to establish SSH connection in such a manner that from Python's code prospective I just do data = open('somefile').read() which actually opens a somefile on a remote host and all traffic is being encrypted because of SSH.
Related
Imagine that you have a client and a server and that the client connects to the server using SSH (with or without Paramiko). Is it possible for Paramiko to utilize the already open SSH connection instead of creating a new one, so that another script can be ran on the server (and transfer a file back to the client for example) using the same existing connection? The goal is to avoid establishing multiple connections.
This is not really a programming/Python/Paramiko question. It's not possible with SSH at all. So it's not possible with Python/Paramiko either.
See
Transfer files to/from session I'm logged in with PuTTY or
Can you use SFTP to transfer files "backwards" to client during SSH on host?
Though if you connect with a (Python or whatever) script from the client machine, the remote script can talk to the local script to exchange the data (and the local script can save the data to a file).
I'm using Paramiko interactive shell (invoke_shell() method) for opening session between my local host and remote host and sending commands to it.
Sometimes I need to open from my remote host an ssh connection to another remote host (this is like a bridge or SSH via SSH from local host to remote_host_2 via remote_host_1).
For better understanding this is a picture how it should behave:
| local host | -(1)-> | remote host | -(2)-> | destination host |
1: is open using invoke_shell() paramiko method so it will create some paramiko.Channel obj.
2: is open using Linux command i.e. ssh remote_user#remote_ip
This is done this way because sometimes I have no direct connection to destination host and in case you are opening it via remote host then user decision should be made (entering another password, answering yes/no on some questions etc..)
Now my question is regarding keeping my connection alive.
I read on keep_alive mechanism that paramiko has but it doesn't do what I want because paramiko knows my connection ends in remote_host and not in destination host so in case destination host is dead I will not receive any notification regarding it and commands execution will fail.
The only solution that came to my mind is sending empty command on this channel (\n) and trying to read the output from the channel before executing the desirable command on it. but this means that I can affect my channel on one hand and my command execution time is now twice longer.
Now my question is, is there another way to perform this connection so this keep alive mechanism will work?
p.s. I read that there exists some ServerAliveInterval=30 flag that can help me to keep my ssh interactive connection alive but I don't understand how can I use it to validate it doesn't became dead.
The correct way is to implement the jump using port forwarding.
See Connecting to a server via another server using Paramiko
Then you will have a complete control over both connections and you will be able to use native Paramiko features to keep the connection alive and to check its status.
I wonder and i've been trying everything to get my program with python sockets to work remotely. When I say remotely is like, I run the server in my computer and my friend at his house can run the client and connect to my server. Is this possible without using Hamachi? Pls let me know, because I'm already dying by trying so many things and installing and uninstalling programs.
You have to activate port forwarding on your router so that everything that comes on the specific port is forwarded to your local IP (and the port should be open).
I've been trying to connect to first an out-of-band management server (in my case, since I'm connecting to DELL-servers, an iDRAC) and through that connect to the main server itself. I've got it to work when I do it manually, using, in the (windows) terminal:
putty.exe -ssh 'username'#'iDRAC-IP'
followed by PuTTY window opening where I type in the password, followed by
connect
which connects to the server itself, and then I type in the username and password for the server, completing the process.
When I've been writing my script in python, I'm using paramiko, http://www.paramiko.org/, suggested here on stackoverflow, and following this example: https://www.ivankrizsan.se/2016/04/24/execute-shell-commands-over-ssh-using-python-and-paramiko/, and it works just splendid for the iDRAC (the first server I connect to). It also works when I type in
stdin, stdout, stderr = ssh_client.exec_command('connect')
because I am still in my first server (ssh_client) (I can tell this is working because when I try to connect to the server manually afterwards, it is occupied). But after that it stops working, since when doing 'connect' I am no longer in ssh_client, but in a different server.
So my question is - how do I connect to a server from another server (in this case being the out-of-band management server) and log in to this one?
You can use ssh tunnel to do so.
this post may resolve your problem:
PyCharm: Configuring multi-hop remote Interpreters via SSH
Overview:
I have a device sitting on a local network to a computer that is sitting on an outside network. I would like to create a software program that allows me to seamlessly connect to the device from a computer on a different network. For purposes of this question, I've created a picture to help describe the network flow. What I need help with is what python packages I would need to develop the solution for this problem.
Details:
I have a computer MYPC (IP address 192.168.0.168) that is attached to the internet running through a proxy server (ROUTER1). I have full control over MYPC's environment, which is running Linux.
I have a second computer SOMESERVER (IP address 192.168.1.168) that is attached to the internet running through a proxy server (ROUTER2). In addition, SOMESERVER (IP address 10.0.0.159) is also attached to a local network (LOCAL). SOMESERVER is running windows. I have very limited control with SOMESERVER: I am able to send an executable to SOMESERVER that can run once before it is removed. I do not know the internet/world IP address of the ROUTER2 initially.
I have a device (DEVICE1) attached to SOMESERVER through LOCAL (IP address: 10.0.0.157).
I have another device (DEVICE2) attached to SOMESERVER through LOCAL (IP address: 10.0.0.158). DEVICE(x) runs linux. I have python on DEVICE(x) and I could install a pure python package if I needed to. However, I do not have the ability to compile for DEVICE(x).
I can connect between SOMESERVER and MYPC through the internet using SSH over ROUTER1 and ROUTER2. I can connect between SOMESERVER and DEVICE1 through the local network (LOCAL) using Telnet. I can connect between SOMESERVER and DEVICE2 through the local network (LOCAL) using Telnet.
I want to send a program to SOMESERVER that allows me seamless access over SSH and Telnet to DEVICE1 and DEVICE2 from MYPC. In addition, I want that program to be running python.
Here's a picture that helps explain the above problem:
Solution:
What I think I want is as follows. I need help with the details and what packages I might need to make it happen.
Part 1: The Dial Home Client and Server
Create a "dial home" server program (DIAL_HOME_SERVER) for MYPC which listens for any one dialing home and then will "dial into" any SOMESERVER that "dials home" using SSH.
Create a "dial home" client program (DIAL_HOME_CLIENT) for SOMESERVER which is downloaded as part of a package
Part 2: The Proxy Server
Create a ssh to telnet proxy server program (PROXY_SERVER) for SOMESERVER which listens for connections from MYPC and funnels them into a telnet connection to DEVICE(x).
Thanks to Greg Hewgill, it sounds like I can use Paramiko to pull together the PROXY_SERVER code on SOMESERVER. It appears that Paramiko also requires PyCryto, and the Windows binary for it can be found here.
Future Robustness
At a future date, the telnet connection will be replaced with an SSH client (dropbox on DEVICE(x)).
In Closing
I think the above will allow MYPC to connect "seamlessly", but the details of how to put together these programs is unknown to me. I already know how to package up a python program using Innosetup and/or py2exe. What I'd love to see is links pointing to different pieces of the solution so I can pull it all together. And then I can post it.
Thanks in advance!
I have to admit that I didn't quite follow all of your description, especially the "dial home" client/server part. However, your diagram seems sufficient for understanding.
Set up port forwarding on "router2" that forwards the incoming SSH port to your Windows server.
Write a Python program (you will probably find paramiko helpful) that runs on your Windows server, listens for SSH connections, and opens a telnet connection to one of your devices on the back end.
That seems sufficient to me. If you've got weird restrictions on the Windows server about only being able to run an executable once before it is deleted, that seems like another problem to solve that doesn't really relate to this tunnelling problem.