I have executed commands on server using ssh. Now I have to do another ssh to different IP while keeping old ssh active.
This new IP is port forward which will then used to do SFTP.
Issue I am facing is both ssh connections are on same port so not able to do second ssh.
Which is failing the SFTP.
Any support for same will be helpful.
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(ip, username=username, password=password, port=22)
time.sleep(3)
#Invoke shell to open multiple channel with in one SSH
chan = ssh.invoke_shell()
chan.send(ip1+'\n')
time.sleep(5)
chan.send(pass1+'\n')
time.sleep(10)
chan.send("ssh "+ip2+'\n')
time.sleep(10)
chan.send(pass2+'\n')
time.sleep(5)
#Execute command
chan.send(cmd)
#connect to another ip to do sftp
ssh1 = paramiko.SSHClient()
ssh1.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect("127.0.0.4", username=usr2, password=pass2, port=22)
sftp=ssh.open_sftp()
It looks like misunderstanding. Your code does not do any port forwarding.
For the correct code, see Nested SSH using Python Paramiko.
If you need SFTP, not shell, just do:
jhost.open_sftp()
instead of
jhost.exec_command(command)
Obligatory warning: Do not use AutoAddPolicy – You are losing a protection against MITM attacks by doing so. For a correct solution, see Paramiko "Unknown Server".
Related
I am trying to connect to a server using SSH protocol through a jump server. When I connect through a terminal using a protocol, the jump server opens a shell and asks for a server number from the list of available servers provided, followed by a user or password. Using the library Paramiko.
My code:
import paramiko
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect(
hostname="server_ip",
username="user",
password="pass",
look_for_keys=False,
allow_agent=False
)
com='1'
stdin, stdout, stderr = client.exec_command(com)
data = stdout.read() + stderr.read()
print(data.decode('utf-8'))
I get message:
Invalid target.
My shell on the jump server looks like this:
Your jump server probably shows the selection in an interactive shell session only. So you will have to use SSHClient.invoke_shell, what is otherwise not good thing to do when automating a connection.
See also What is the difference between exec_command and send with invoke_shell() on Paramiko?
I am writing a Python code to SSH or Telnet remote hosts, execute some commands and get the result output. Here we have a jump server, so the code must be "connected" with this server and from it, Telnet or SSH the remote hosts.
All my approaches work fine within the jump server, for example I can get the output of commands inside it. The problem is when I try to remote connect to hosts from it.
import paramiko
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect('IP', 22, username="user", password="pass")
stdin, stdout, stderr = client.exec_command("command")
for line in stdout:
print('... ' + line.strip('\n'))
client.close()
Using the library jumpssh get same results, and I am not will able to Telnet hosts. I tried the follow approach, but get the error
Administratively prohibited.
from jumpssh import SSHSession
gateway_session = SSHSession('jumpserver','user', password='pass').open()
remote_session = gateway_session.get_remote_session('IP',password='pass')
print(gateway_session.get_cmd_output('command'))
In the last company i worked we had a license from an SSH client that supports Python scripts, and worked fine in a more "textual" treatment.
There is any way of accomplish same task natively in Python?
SSHSession is trying to open direct-tcpip port forwarding channel over the gateway_session.
"administratively prohibited" is OpenSSH sshd server message indicating that direct-tcpip port forwarding is disabled.
To enable port forwarding, set AllowTcpForwarding and DisableForwarding directives in sshd_config appropriately.
If you cannot enable the port forwarding on the server, you cannot use jumpssh library.
If you have a shell access to the server, you can use ProxyCommand-like approach instead.
See Paramiko: nest ssh session to another machine while preserving paramiko functionality (ProxyCommand).
This works:
cnopts = pysftp.CnOpts()
cnopts.hostkeys = None
with pysftp.Connection('ftpsite.com', username='xxx', password='xxx', cnopts=cnopts) as sftp:
with sftp.cd('inbox'):
sftp.get('WinSCP.ini')
But now i want to test straight ftp (port 21), so i add the port attribute:
with pysftp.Connection('ftpsite.com', port=21 , username='xxx', password='xxx', cnopts=cnopts) as sftp:
and now i get this:
Exception: paramiko.ssh_exception.SSHException
Message: Error reading SSH protocol banner
I am confused...
SFTP use SSH so its PORT 22, not 21
FTP use port 21
Like the error said, ssh exception. Try with 'port=22'
source:
port 21 Yes, and SCTP Assigned Official File Transfer Protocol (FTP) control (command)
port 22 Yes, and SCTP Assigned Official Secure Shell (SSH), secure logins, file transfers (scp, sftp) and port forwarding
wikipedia
The pysftp library only talks using the SFTP protocol, which is different from the 'normal' FTP protocol. So what you are seeing is the error when your program tries to talk in SFTP to an FTP server, and doesn't understand the response it gets back.
Moin!
Situation: connect to the destination.host over the jump.host and run a command on the destination.host, which connects in the background to the another.host (on this host my ssh key is needed).
Scheme: client --> jump.host --> destination.host --- remote_command with ssh key needed on the other host --> another.host
#!/usr/bin/python
import paramiko
jumpHost=paramiko.SSHClient()
sshKey = paramiko.RSAKey.from_private_key_file('path.to.key/file', password = 'the.passphrase')
jumpHost.set_missing_host_key_policy(paramiko.AutoAddPolicy())
jumpHost.connect('jump.hostname',username='foo', pkey = sshKey)
jumpHostTransport = jumpHost.get_transport()
dest_addr = ('destination.hostname', 22)
local_addr = ('jump.hostname', 22)
jumpHostChannel = jumpHostTransport.open_channel("direct-tcpip", dest_addr, local_addr)
destHost=paramiko.SSHClient()
destHost.set_missing_host_key_policy(paramiko.AutoAddPolicy())
destHost.connect('destination.hostname', username='foo', sock=jumpHostChannel, pkey=sshKey)
destHostAgentSession = destHost.get_transport().open_session()
paramiko.agent.AgentRequestHandler(destHostAgentSession)
stdin, stderr, stdout = destHost.exec_command("my.command.which.connects.to.another.host")
print(stdout.read())
print(stderr.read())
destHost.close()
jumpHost.close()
The above code works well, if run "local" commands on the destination.host - e.g. uname, whoami, hostname, ls and so on... But if i run a command, which connects in the background to another host where my ssh key is needed, the code raised in the error:
raise AuthenticationException("Unable to connect to SSH agent")
paramiko.ssh_exception.AuthenticationException: Unable to connect to SSH agent
If i connect via Putty at the same chain, it works well.
Can anyone give me a hint to resolve my problem?
Thx in advance.
Assumption: Your keys work across jump host and destination host.
Creating a local agent in that case will work. You could manually create it via shell first and test it via iPython.
eval `ssh-agent`; ssh-add <my-key-file-path>
Programmatically this can be done -
# Using shell=True is not a great idea because it is a security risk.
# Refer this post - https://security.openstack.org/guidelines/dg_avoid-shell-true.html
subprocess.check_output("eval `ssh-agent`; ssh-add <my-key-file-path>", shell=True)
I am trying to do something similar and came across this post, I will update if I find a better solution.
EDIT: I have posted the implementation over here - https://adikrishnan.in/2018/10/25/agent-forwarding-with-paramiko/
I am trying to use paramiko to connect to a remote host. However, in order to connect, I need to specify a bind address, which you can do with OpenSSH via:
ssh -o BindAddress=x.x.x.x user#host
I've been searching high and low for an equivalent option in the paramiko SSHClient docs, but I can't seem to find it. It seems like this would be a standard option to have. Can someone point me in the right direction? Do I need to create a separate socket connection and use that?
From ssh_config manual:
BindAddress
Use the specified address on the local machine as the source address of the connection.
You might provide a socket to client's connect function, so you might bind the source address in the socket.
Example:
import socket
import paramiko
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(('192.168.223.21', 0)) # set source address
sock.connect(('192.168.223.23', 22)) # connect to the destination address
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect('192.168.223.23',
username=username,
password=password,
sock=sock) # pass socket to Paramiko
Documentation: http://docs.paramiko.org/en/2.4/api/client.html).
connect(hostname, port=22, username=None, password=None, pkey=None,
key_filename=None, timeout=None, allow_agent=True, look_for_keys=True,
compress=False, sock=None, gss_auth=False, gss_kex=False,
gss_deleg_creds=True, gss_host=None, banner_timeout=None,
auth_timeout=None, gss_trust_dns=True, passphrase=None)
sock (socket) – an open socket or socket-like object (such as a
Channel) to use for communication to the target host