I need to perform on my linux 5.3
ssh [Linux machine red hat 5.3] date
in order to get the date results , during ssh need to answer on the following question
(yes/no)? --> yes
password: --> diana_123
and then I will get the date results
please advice how to do this automated process with python? ( on my Linux I have
Python 2.2.3 )
python script should get the IP address number , and perform automatically ssh to 103.116.140.151 and return the date results
as --> Fri Nov 18 11:25:18 IST 2011
example of manual proccess:
# ssh 103.116.140.151 date
The authenticity of host '103.116.140.151 (103.116.140.151)' can't be established.
RSA key fingerprint is ad:7e:df:9b:53:86:9f:98:17:70:2f:58:c2:5b:e2:e7.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '103.116.140.151' (RSA) to the list of known hosts.
root#10.116.10.151's password:
Fri Nov 18 11:25:18 IST 2011
The easiest way would be to just configure passwordless logins. Basically, create a local ssh key pair with
ssh-keygen -t rsa
and put the public key into $HOME/.ssh/authorized_keys at 103.116.140.151. If you don't care about the key of the remote host, add the -oStrictHostKeyChecking=no ssh option.
Alternatively, use an SSH library such as Paramiko:
import paramiko
ssh = paramiko.SSHClient()
# Uncomment the following line for the equivalent of -oStrictHostKeyChecking=no
#ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect('103.116.140.151', username='user', password='diana_123')
stdin, stdout, stderr = ssh.exec_command("date")
date = stdout.read()
print(date)
You can skip the host key check by passing the StrictHostKeyChecking=no parameter to ssh:
ssh -oStrictHostKeyChecking=no 103.116.140.151 date
I don't think it's possible to do the same for the password. The correct way to bypass SSH's password prompt is with a restricted passphraseless key: see here for details.
If you cannot use key based passwordless login, you can use expect package on Linux. It gives answers you choose to questions.
You can use this package from python with pexpect.
Related
It seems very simple, but I searched multiple resources but could not find an answer on how to change a remote Linux system password using Python and with SFTP.
def changepwd():
sftp_client = ssh.open_sftp()
#change password of root on remote server
Are there any built-in modules that I can use to change the password?
Thanks in advance.
Thanks for all you help. This is how I changed the passwd for 'root'.
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(hostname, username=Name, password=Pwd)
print "Connection succesfully established ...with %s " % hostname
stdin, stdout, stderr = ssh.exec_command('echo -e "newpasswd\newPasswd" | passwd')
print "stderr: ", stderr.readlines()
print "pwd: ", stdout.readlines()
ssh.close()
You cannot change password with SFTP protocol.
You can change password with SSH protocol. But the SSH protocol API for changing a password is not support by the most widespread SSH server – OpenSSH. Nor it is supported by the most widespread Python SSH library – Paramiko. So this most likely won't work for you anyway.
So in the end the only viable option is to execute a relevant shell command (passwd or chpasswd) via SSH (e.g. using Paramiko).
I need to parse the output of a command on a remote machine I have to connect via SSH.
This remote machine runs Ubuntu and I can only access the SSH via a "console wrapper" (sorry don't know the exact term for it) called BOSCLI in which I can only run a set of specific commands.
On connect I get a prompt for sudo password, after entered I'm at the prompt and I do not need to enter it again.
At first I started using exec_command which didn't work, for obvious reasons. I have switched now to invoke_shell() and then using send() but only the password prompt is sent, and not the following command.
Of course I've read a lot of other questions here and other websites with no success...
def conectar(url,user,passw, puerto, sudoPass):
cliente = paramiko.SSHClient()
cliente.set_missing_host_key_policy(paramiko.AutoAddPolicy())
cliente.connect(url,port=puerto, username=user, password=passw)
if cliente.get_transport() is None: raise Exception(paramiko.SSHException)
time.sleep(2)
canal = cliente.invoke_shell()
stdin = canal.makefile('wb')
stdout = canal.makefile('rb')
stderr = canal.makefile_stderr('r')
while not canal.recv_ready():
time.sleep(2)
aux = canal.send(sudoPass+'\n') #sudo pass
out = canal.recv(1024)
print(aux)
time.sleep(1)
aux = canal.send('''dhcp pool status\n''')
print(aux)
out += canal.recv(9999)
#ssh_stdin, ssh_stdout, ssh_stderr = cliente.exec_command('dhcp pool status',get_pty=True)
#ssh_stdout.channel.recv_exit_status()
cliente.close()
print(stdout.read())
print(stderr.read())
print(out.decode('ascii'))
The output should be a long text with all the DHCP statistics on the different pools for the next method to parse, however I'm receiving empty outputs.
There's a thing also that is confusing me the most right now which is that actually 'out' has content (which is the welcome MOTD, etc on the shell), but stdout is empty.
print(aux) returns 9 first
print(aux) returns 17 afterwards.
print(stdout.read()) returns b''
print(stderr.read()) returns b''
out content is the following:
Welcome to Ubuntu 12.04.5 LTS (GNU/Linux 3.13.0-66-generic x86_64)
* Documentation: https://help.ubuntu.com/
System information as of Tue Jul 2 11:34:22 CEST 2019
System load: 0.42 Users logged in: 0
Usage of /: 32.9% of 26.51GB IP address for eth0:
Memory usage: 22% IP address for eth1:
Swap usage: 4% IP address for eth2:
Processes: 194 IP address for docker0:
Graph this data and manage this system at:
https://landscape.canonical.com/
Last login: Tue Jul
[sudo] password for bos:
(pho-xem1) (Nuevo) bcli 0 [] normal>
Which is the command prompt after passing the sudo pass.
You probably send the command too early, before the server (or actually the boscli shell) expects it.
You should wait for the prompt, before you send the command.
Or as a quick and dirty hack, just wait for a short interval.
As for the stdout: stdout is just a wrapper around Channel.recv. As you are already consuming the output in Channel.recv, you won't get anything more in stdout. Either read stdout or use Channel.recv, but not both.
I am trying to perform SSH from one system to another using paramiko in python
import paramiko
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(
paramiko.AutoAddPolicy())
ssh.connect('127.0.0.1', username='jesse',
password='lol')
using this reference (http://jessenoller.com/blog/2009/02/05/ssh-programming-with-paramiko-completely-different )
This is the case when we know the password of the system you want to log-in BUT
if i want to login to a system where my public-key is copied and i dont know the password. Is there a way to do this
Thanks in advance
SSHClient.connect accepts a kwarg key_filename, which is a path to the local private key file (or files, if given a list of paths). See the docs.
key_filename (str) – the filename, or list of filenames, of optional private key(s) to try for authentication
Usage:
ssh.connect('<hostname>', username='<username>', key_filename='<path/to/openssh-private-key-file>')
This code should work:
import paramiko
host = "<your-host>"
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect(host, username='<your-username>', key_filename="/path/to/.ssh/id_rsa" , port=22)
# Just to test a command
stdin, stdout, stderr = client.exec_command('ls')
for line in stdout.readlines():
print line
client.close()
Here is the documentation of SSHClient.connect()
EDIT : /path/to/.ssh/id_rsa is your private key!
Adding the key to a configured SSH agent would make paramiko use it automatically with no changes to your code.
ssh-add <your private key>
Your code will work as is. Alternatively, the private key can be provided programmatically with
key = paramiko.RSAKey.from_private_key_file(<filename>)
SSHClient.connect(pkey=key)
Essentially, I need to access a computer, say machine A, which is only accessible via the internal network of my company. I used to be able to set up tcprelay port forwarding to accomplish this but that pipeline has been disabled due to some potential security flaws.
Let’s say my company general network is at
company#10.0.0.1
and the specific machine i want to work with is at
machine#10.0.0.3
Both accounts have password ‘password’
Via terminal and shell commands, I can just hop there using one single command:
https://askubuntu.com/a/311457
or, in steps, it would be:
[on my account] ssh company#10.0.0.1
[on my account] enter password
[on company network] ssh machine #10.0.0.3
[on company network] enter password again
And I’d be logged into the machine I need to communicate with.
However, after hacking away all afternoon I could not get this working with Paramiko. I tried setting up the connection then issuing a client.exec_command() but just cannot get a handle for the specific machine. The rest of my scripts relies on having a paramiko client that can receive commands and return responses, so it would be a very heavy overhead for me to go propagate all changes were I to switch to say fabric or subprocess.
The closest I got to was:
ssh.connect(’10.0.0.1', username=‘company', password=‘password’)
chan = ssh.get_transport().open_session()
chan.get_pty()
chan.exec_command(‘ssh machine#10.0.0.3’)
print chan.recv(1024)
which returned the ‘enter password’ prompt, but running chan.send(‘password’) just ends with a hang.
I’m pulling my hair out at this point and am just reading through the documentation hoping to find what concept I’m missing.
If anyone can give some advice I’d really appreciate it.
Thanks!
Alternative way is to avoid entering password when login to another machine.
This can be done by using ssh-keygen.
Login to first machine (A) with user 'first':
$ ssh-keygen -t rsa
--> Don't enter any passphrase when requested
--> Note down the line "Your public key has been saved in /home/first/.ssh/"
--> This file is the public key of machine 'A'
Now login to second machine(B) using ssh.
Then check for ~/.ssh folder. If no folder, create one.
Create a file with name 'authorized_keys' under ~/.ssh/authorized_keys
Copy the content of file from 'first' user to the file 'authorized_keys'.
is a file with 'id_rsa.pub' from 'first' user login (under /home/first/.ssh/id_rsa.pub)
Now you can login to second machine from first without entering password thru your script.
I worked on a project where it had to log in using username/password over SSH then do the same thing again to another host. I had no control over networks ACLs and SSH keys were not allowed for some reason. You'll need to add paramiko_expect. Here's how I got it to work:
import paramiko
from paramiko_expect import SSHClientInteraction
user1 = 'admin'
pass1 = 'admin'
user2 = 'root'
pass2 = 'root'
# not needed for this example, but included for reference
user_prompt = '.*\$ '
# will match root user prompt
root_prompt = '.*$ '
# will match Password: or password:
pass_prompt = '.*assword: '
# SSH to host1
ssh_client = paramiko.SSHClient()
ssh_client.set_missing_host_key_policy(
paramiko.AutoAddPolicy())
ssh_client.connect(hostname='host1', username=user1, password=pass1)
# Interact with SSH client
with SSHClientInteraction(ssh_client, display=True) as interact:
# Send the command to SSH as root to the final host
interact.send('ssh {}#host2'.format(user2)
# Expect the password prompt
interact.expect(pass_prompt)
# Send the root password
interact.send(pass2)
# Expect the root prompt
interact.expect(root_prompt)
ssh_client.close()
One caveat: if host1 has never connected to host2 using SSH it'll get a warning about host key checking and timeout. You can change the configuration on host1 or just SSH to host1 then from host1 SSH to host2 and type yes and press enter.
I use Paramiko for establishing SSH connection with some target device and I want to execute reboot command.
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(zip_hostname, username=username, password=password, timeout=1)
try:
stdin, stdout, stderr = ssh.exec_command("/sbin/reboot -f")
# .........
# some code
# .........
except AuthenticationException, e:
print ''
finally:
ssh.close()
But after executing ssh.exec_command("/sbin/reboot -f") "some code" does not execute because program is stuck in exec_command (the disconnection takes place caused by rebooting). What should I do to solve my problem?
Try this:
ssh.exec_command("/sbin/reboot -f > /dev/null 2>&1 &")
All the output of reboot is redirected to /dev/null to make it produce no output and it is started in the background thanks to the '&' sign in the end. Hopefully the program won't hang on that line this way, because the remote shell gives the prompt back.
Get the transport from the ssh and set the keepalive using:
transport = ssh.get_transport()
transport.set_keepalive(5)
This sets the keepalive to 5 seconds; mind you I would have expected the timeout=1 to have achieved the same thing.
All you need to do is to call channel.exec_command() instead of the high-level interface client.exec_command()
# exec fire and forget
timeout=0.5
transport = ssh.get_transport()
chan = ssh.get_transport().open_session(timeout=timeout)
chan.settimeout(timeout)
try:
chan.exec_command(command)
except socket.timeout:
pass
I was having this issue and managed to avoid it by switching to this command:
/sbin/shutdown -r now
Note this command does not result in any STDOUT or STDERR output
In case you or anyone else gets stuck trying to reboot host with sudo using forwarding agents (ssh keys) or in my case (yubikey)
If you look at this as bash you would reboot a host as non root user like this.
ssh -t -A user#hostname sudo /sbin/reboot
For the -A flag, from ssh man page
Enables forwarding of the authentication agent connection. This can also be specified on a per-host basis in a
configuration file.
Agent forwarding should be enabled with caution. Users with the ability to bypass file permissions on the
remote host (for the agent’s Unix-domain socket) can access the local agent through the forwarded connection.
An attacker cannot obtain key material from the agent, however they can perform operations on the keys that
enable them to authenticate using the identities loaded into the agent.*
For the -t flag, from ssh man page
Force pseudo-tty allocation. This can be used to execute arbitrary screen-based programs on a remote machine,
which can be very useful, e.g. when implementing menu services. Multiple -t options force tty allocation, even
if ssh has no local tty.*
So lets break this down into how you would do this in paramiko
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(hostname=host, username=username)
s = ssh.get_transport().open_session()
paramiko.agent.AgentRequestHandler(s)
ssh.exec_command("sudo /sbin/reboot", get_pty=True)
For authentication forwarding (-A flag in bash ssh command) for paramiko
ssh = paramiko.SSHClient() #'ssh' is client variable
s = ssh.get_transport().open_session() #get 'ssh' transport and open sessions assigned to 's' variable
paramiko.agent.AgentRequestHandler(s) #call in 's' to the forwarding agent for current ssh session
Now for force pseudo-tty allocation (-t flag in bash ssh command) for paramiko
ssh.exec_command("sudo /sbin/reboot", get_pty=True)
Adding 'get_pty=True' to exec_command will allow you execute sudo /sbin/reboot
Hope this helps, everyone's environments are different but this should work as it the exact same thing as if you ran it as bash.