Python Pysftp Error - python

My code:
import pysftp
s = pysftp.Connection(host='test.rebex.net', username='demo', password='password')
data = s.listdir()
s.close()
for i in data:
print i
I'm getting an error trying to connect to a SFTP server using pysftp.
This should be straight forward enough but I get the error below:
Traceback (most recent call last):
File "/Users/gavinhinfey/Documents/Python Files/sftp_test.py", line 3, in <module>
s = pysftp.Connection(host='test.rebex.net', username='demo', password='password')
File "build/bdist.macosx-10.6-intel/egg/pysftp.py", line 55, in __init__
File "build/bdist.macosx-10.5-intel/egg/paramiko/transport.py", line 303, in __init__
paramiko.SSHException: Unable to connect to test.rebex.net: [Errno 60] Operation timed out
Exception AttributeError: "'Connection' object has no attribute '_tranport_live'" in <bound method Connection.__del__ of <pysftp.Connection object at 0x101a5a810>> ignored
I've tried using different versions of python (mostly 2.7), I have all dependencies installed and I tried numerous sftp connections.
I'm using OS X 10.9.1.

updating the package didn't work for me, as it was already up-to-date (latest for python 2.7 at least)
Found a better aproach here.
1) You can manualy add the ssh key to the known_hosts file
ssh test.rebex.net
2) Or you can set a flag to ignore it
import pysftp
cnopts = pysftp.CnOpts()
cnopts.hostkeys = None # disable host key checking.
with pysftp.Connection('host', username='me',private_key=private_key,
private_key_pass=private_key_password,
cnopts=cnopts) as sftp
# do stuff here

That initial error appears to be a problem connecting with the remote server (SSHException). The second (AttributeError), is from a bug in the code that occurs when the connection fails. It is fixed in the latest version of pysftp
https://pypi.python.org/pypi/pysftp
pip install -U pysftp
is your friend.

#Martin.Prikryl: setting hostkeys = None is very useful in the initial stage of coding with pysftp. Debugging a program that keeps failing for a known exception hides other problems that need attention--like making an actual connection. I can deal with the 'man in the middle' problem later once I know my code is actually working correctly.
#All: The current pysftp.CnOpts() object appears to have a bug:
cnopts = pysftp.CnOpts()
cnopts.hostkeys = None
The above code does not prevent host key checking.
python getfile_v3.py --help
Traceback (most recent call last):
File "getfile_v3.py", line 9, in
cnopts = pysftp.CnOpts()
File "c:\Program Files\Python\Python38\lib\site-packages\pysftp_init_.py", line 64, in init
raise HostKeysException('No Host Keys Found')
pysftp.exceptions.HostKeysException: No Host Keys Found
The second line doesn't get executed because the first does the host key check by default. If I set the key with:
cnopts = pysftp.CnOpts(hostkeys=None)
the same error results.
It appears that 'hostkeys' has been deprecated, and there is no way to disable the host key check.
Joe White

Workaround for SSHException: No hostkey for host test.rebex.net found
just to add it manually via ssh
ssh demo#test.rebex.net
it will ask for password, you need to enter "password"
it will show you the message
The authenticity of host 'test.rebex.net (ip-adress)' can't be established.
ECDSA key fingerprint is SHA256:OzvpQxxxV9F/ECMXbQ7B7zbKxxxxUno65c.
Are you sure you want to continue connecting (yes/no/[fingerprint])?
confirm action -> type "yes"
done, you will get a message, since now your sftp connection to 'test.rebex.net' should work
Warning: Permanently added 'test.rebex.net,ip' (ECDSA) to the list of known hosts.

Related

How to add ssh key correctly [duplicate]

I am writing a program using pysftp, and it wants to verify the SSH host Key against C:\Users\JohnCalvin\.ssh\known_hosts.
Using PuTTY, the terminal program is saving it to the Registry [HKEY_CURRENT_USER\Software\SimonTatham\PuTTY\SshHostKeys].
How do I reconcile the difference between pysftp and PuTTY?
My code is:
import pysftp as sftp
def push_file_to_server():
s = sftp.Connection(host='138.99.99.129', username='root', password='*********')
local_path = "testme.txt"
remote_path = "/home/testme.txt"
s.put(local_path, remote_path)
s.close()
push_file_to_server()
The error response I am receiving is:
E:\Program Files (x86)\Anaconda3\lib\site-packages\pysftp\__init__.py:61:
UserWarning: Failed to load HostKeys from C:\Users\JohnCalvin\.ssh\known_hosts. You will need to explicitly load HostKeys (cnopts.hostkeys.load(filename)) or disableHostKey checking (cnopts.hostkeys = None).
warnings.warn(wmsg, UserWarning)
Traceback (most recent call last):
File "E:\OneDrive\Python\GIT\DigitalCloud\pysftp_tutorial.py", line 14, in <module>
push_file_to_server()
File "E:\OneDrive\Python\GIT\DigitalCloud\pysftp_tutorial.py", line 7, in push_file_to_server
s = sftp.Connection(host='138.99.99.129', username='root', password='********')
File "E:\Program Files (x86)\Anaconda3\lib\site-packages\pysftp\__init__.py", line 132, in __init__
self._tconnect['hostkey'] = self._cnopts.get_hostkey(host)
File "E:\Program Files (x86)\Anaconda3\lib\site-packages\pysftp\__init__.py", line 71, in get_hostkey
raise SSHException("No hostkey for host %s found." % host) paramiko.ssh_exception.SSHException: No hostkey for host 138.99.99.129 found.
Exception ignored in: <bound method Connection.__del__ of <pysftp.Connection object at 0x00000222FF3A6BE0>>
Traceback (most recent call last):
File "E:\Program Files (x86)\Anaconda3\lib\site-packages\pysftp\__init__.py", line 1013, in __del__
self.close()
File "E:\Program Files (x86)\Anaconda3\lib\site-packages\pysftp\__init__.py", line 784, in close
if self._sftp_live:
AttributeError: 'Connection' object has no attribute '_sftp_live'
The pysftp has some bugs regarding host key handling, as described below. It also seems that the pysftp project was abandoned. Consider using Paramiko directly instead. The pysftp is just a wrapper on top of Paramiko and it does not add anything really significant. See pysftp vs. Paramiko.
For handling of host keys in Paramiko, see:
Paramiko "Unknown Server"
If you want to keep using pysftp, do not set cnopts.hostkeys = None (as the second most upvoted answer shows), unless you do not care about security. You lose a protection against Man-in-the-middle attacks by doing so.
Use CnOpts.hostkeys (returns HostKeys) to manage trusted host keys.
cnopts = pysftp.CnOpts(knownhosts='known_hosts')
with pysftp.Connection(host, username, password, cnopts=cnopts) as sftp:
where the known_hosts contains a server public key(s)] in a format like:
example.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQAB...
If you do not want to use an external file, you can also use
from base64 import decodebytes
# ...
keydata = b"""AAAAB3NzaC1yc2EAAAADAQAB..."""
key = paramiko.RSAKey(data=decodebytes(keydata))
cnopts = pysftp.CnOpts()
cnopts.hostkeys.add('example.com', 'ssh-rsa', key)
with pysftp.Connection(host, username, password, cnopts=cnopts) as sftp:
Though as of pysftp 0.2.9, this approach will issue a warning, what seems like a bug:
"Failed to load HostKeys" warning while connecting to SFTP server with pysftp
An easy way to retrieve the host key in the needed format is using OpenSSH ssh-keyscan:
$ ssh-keyscan example.com
# example.com SSH-2.0-OpenSSH_5.3
example.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQAB...
(due to a bug in pysftp, this does not work, if the server uses non-standard port – the entry starts with [example.com]:port + beware of redirecting ssh-keyscan to a file in PowerShell)
You can also make the application do the same automatically:
Use Paramiko AutoAddPolicy with pysftp
(It will automatically add host keys of new hosts to known_hosts, but for known host keys, it will not accept a changed key)
Though for an absolute security, you should not retrieve the host key remotely, as you cannot be sure, if you are not being attacked already.
See my article Where do I get SSH host key fingerprint to authorize the server?
It's for my WinSCP SFTP client, but most information there is valid in general.
If you need to verify the host key using its fingerprint only, see Python - pysftp / paramiko - Verify host key using its fingerprint.
One option is to disable the host key requirement:
import pysftp
cnopts = pysftp.CnOpts()
cnopts.hostkeys = None
with pysftp.Connection(host, username, password, cnopts=cnopts) as sftp:
sftp.put(local_path, remote_path)
You can find more info about that here:
https://stackoverflow.com/a/38355117/1060738
Important note:
By setting cnopts.hostkeys=None you'll lose the protection against Man-in-the-middle attacks by doing so. Use #martin-prikryl answer to avoid that.
Try to use the 0.2.8 version of pysftp library.
$ pip uninstall pysftp && pip install pysftp==0.2.8
And try with this:
try:
ftp = pysftp.Connection(host, username=user, password=password)
except:
print("Couldn't connect to ftp")
return False
Why this?
Basically is a bug with the 0.2.9 of pysftp
here all details
https://github.com/Yenthe666/auto_backup/issues/47
Cook book to use different ways of pysftp.CnOpts() and hostkeys options.
Source : https://pysftp.readthedocs.io/en/release_0.2.9/cookbook.html
Host Key checking is enabled by default. It will use ~/.ssh/known_hosts by default. If you wish to disable host key checking (NOT ADVISED) you will need to modify the default CnOpts and set the .hostkeys to None.
import pysftp
cnopts = pysftp.CnOpts()
cnopts.hostkeys = None
with pysftp.Connection('host', username='me', password='pass', cnopts=cnopts):
# do stuff here
To use a completely different known_hosts file, you can override CnOpts looking for ~/.ssh/known_hosts by specifying the file when instantiating.
import pysftp
cnopts = pysftp.CnOpts(knownhosts='path/to/your/knownhostsfile')
with pysftp.Connection('host', username='me', password='pass', cnopts=cnopts):
# do stuff here
If you wish to use ~/.ssh/known_hosts but add additional known host keys you can merge with update additional known_host format files by using .load method.
import pysftp
cnopts = pysftp.CnOpts()
cnopts.hostkeys.load('path/to/your/extra_knownhosts')
with pysftp.Connection('host', username='me', password='pass', cnopts=cnopts):
# do stuff here
If You try to connect by pysftp to "normal" FTP You have to set hostkey to None.
import pysftp
cnopts = pysftp.CnOpts()
cnopts.hostkeys = None
with pysftp.Connection(host='****',username='****',password='***',port=22,cnopts=cnopts) as sftp:
print('DO SOMETHING')
Connect to the server first with a Windows ssh client that uses the known_hosts file.
PuTTy stores the data in the windows registry,however OpenSSH uses the known_hosts file, and will add entries in there after you connect.
Default location for the file is %USERPROFILE%.ssh. I hope this helps
I've implemented auto_add_key in my pysftp github fork.
auto_add_key will add the key to known_hosts if auto_add_key=True
Once a key is present for a host in known_hosts this key will be checked.
Please reffer Martin Prikryl -> answer about security concerns.
Though for an absolute security, you should not retrieve the host key remotely, as you cannot be sure, if you are not being attacked already.
import pysftp as sftp
def push_file_to_server():
s = sftp.Connection(host='138.99.99.129', username='root', password='pass', auto_add_key=True)
local_path = "testme.txt"
remote_path = "/home/testme.txt"
s.put(local_path, remote_path)
s.close()
push_file_to_server()
Note: Why using context manager
import pysftp
with pysftp.Connection(host, username="whatever", password="whatever", auto_add_key=True) as sftp:
#do your stuff here
#connection closed
Hi We sort of had the same problem if I understand you well. So check what pysftp version you're using. If it's the latest one which is 0.2.9 downgrade to 0.2.8.
Check this out. https://github.com/Yenthe666/auto_backup/issues/47
FWIR, if authentication is only username & pw, add remote server ip address to known_hosts like ssh-keyscan -H 192.168.1.162 >> ~/.ssh/known_hosts for ref https://www.techrepublic.com/article/how-to-easily-add-an-ssh-fingerprint-to-your-knownhosts-file-in-linux/

Paramiko SSH command execution failing with `ValueError: [digital envelope routines: EVP_DigestInit_ex] disabled for FIPS`

Executing a command on remote machine using SSH is failing with the below error:
Traceback (most recent call last):
File "ssh.py", line 4, in <module>
ssh_client.connect(hostname='10.x.x.x', username='admin', password='password')
File "/usr/lib/python3.6/site-packages/paramiko/client.py", line 407, in connect
self, server_hostkey_name, server_key
File "/usr/lib/python3.6/site-packages/paramiko/client.py", line 790, in missing_host_key
key.get_name(), hostname, hexlify(key.get_fingerprint())
File "/usr/lib/python3.6/site-packages/paramiko/pkey.py", line 151, in get_fingerprint
return md5(self.asbytes()).digest()
ValueError: [digital envelope routines: EVP_DigestInit_ex] disabled for FIPS
The code snippet I'm using is as follows:
import paramiko
ssh_client = paramiko.SSHClient()
ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh_client.connect(hostname='10.x.x.x', username='admin', password='password')
command = "sudo sh ~/script.sh"
ssh_client.exec_command(command)
I was facing this error too.
This is because Paramiko uses MD5 encryption and the machine you want to connect to use FIPS, FIPS not allowed MD5 anymore.
So there is open PR in the Paramiko project.
In this issue above someone named neutronscott suggested editing the Pkey.py file.
Instead
return md5(self.asbytes()).digest()
Change to
return md5(self.asbytes(), usedforsecurity=False).digest()
So we can do something called 'Monkey patching'
Monkey patching is a technique to add, modify, or suppress the default behavior of a piece of code at runtime without changing its original source code.
This is worked for me:
class _PkeyChild(paramiko.PKey):
def get_fingerprint_improved(self):
"""
Declare that the use of MD5 encryption is not for security purposes.
This declaration is to overcome connection to servers with FIPS security standards.
"""
return md5(self.asbytes(), usedforsecurity=False).digest()
...
paramiko.PKey.get_fingerprint = _PkeyChild.get_fingerprint_improved
connection = paramiko.SSHClient()
connection.set_missing_host_key_policy(paramiko.AutoAddPolicy())
connection.connect(hostname="host_name", username="username", password="password")

SFTP hang and authentication failure with paramiko

I'm trying to connect via SFTP with paramiko and Python 2.7, to eventually get a file from remote server and put to my server. (Note it uses a non-standard port too)
But when I try to connect - it takes a really long time and then I get an authentication error. Have you have this issue have suggestions for fixing?
I don't have a key, it just uses a username/password. I can connect with a graphical SSH program without issues, so the credentials seem correct.
Here is code:
hostname = 'remotehostname.com'
username= 'AB1239'
password= ‘password’
port = 10022
import paramiko
c = paramiko.SSHClient()
c.set_missing_host_key_policy(paramiko.AutoAddPolicy())
c.connect(hostname=hostname, username=username, password=password,port=port)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python2.7/site-packages/paramiko/client.py", line 380, in connect
look_for_keys, gss_auth, gss_kex, gss_deleg_creds, gss_host)
File "/usr/lib/python2.7/site-packages/paramiko/client.py", line 597, in _auth
raise saved_exception
paramiko.ssh_exception.AuthenticationException: Authentication failed.
I am using:
>>> print paramiko.__version__
1.16.1
and python Python 2.7.5 (on linux)
http://docs.paramiko.org/en/2.4/api/transport.html# (these are for version 2.4, but note I'm using earlier version)
http://docs.paramiko.org/en/2.4/api/client.html
I also looked at this : Why does Paramiko hang if you use it while loading a module?
but still having connection issues.
I'm not quite sure if that answers your question 100 percent, but I thought better than no answer at all, especially since I'm pretty sure it can solve your problem, even though I haven't tested it in this release (no default port).
# coding: utf-8
from fabric.api import env, execute # hosts
from fabric.network import ssh
from fabric.operations import get, run, sudo # put
ssh.util.log_to_file("paramiko.log", 10)
env.host_string = 'remotehostname.com'
env.port = 10022
env.user = 'AB1239'
env.password = 'password'
# Attention: "rm -r" won't ask for password anymore!
env.warn_only = True
def blah():
sudo('ls')
get('/tmp/lolo*.xml', '/tmp', use_sudo=True) # from remote to local
# sudo('rm -r /tmp/what/no/')
execute(blah)

can't login with Paramiko ssh client

local-host --->Aterm server (security server ) -----> target-machine(
I am trying to write a code in Python using Paramiko to first SSH from local-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 (havent got to that point yet). I found an example from stackoverflow where they talk about using nested SSH with paramiko, and I follow it but I get stuck here:
i need just reaching the target-machine
My code:
import paramiko
import sys
import subprocess
hostname = '10.10.10.1'
port = 22
username = 'mohamed.hosseny'
password ='Pass#1'
client = paramiko.Transport((hostname, port))
client.connect(username=username, password=password)
client.close()
but i found the below error message :
Traceback (most recent call last):
File "C:/Users/mohamed.hosseny/Desktop/Paramiko.py", line 13, in <module>
client = paramiko.Transport((hostname, port))
File "C:\Python27\lib\site-packages\paramiko\transport.py", line 332, in
__init__
'Unable to connect to {}: {}'.format(hostname, reason))
SSHException: Unable to connect to 10.10.10.1: [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
paramiko.Transport is a lower level API. Don't use it unless you have a good reason. Instead, you can use paramiko.SSHClient.

PYSFTP script to Upload and Download

I need some help I'm getting below message when i try to connect. The script Im executing is below. Any suggestions as to how I can fix this issue?
Also, once I get this issue fixed Im looking to add to this script the ability to listen until the result file is available and to download it from a different remote directory.
Thank you, in advance
No hostkey for host mysftpserver.com found.
Exception AttributeError: "'Connection' object has no attribute
'_sftp_live'" in <bound method Connection.__del__ of <pysftp.Connection
object at 0x101d8cd50>> ignored
Process finished with exit code 0
Script
import pysftp as sftp
def sftpExample():
try:
s = sftp.Connection(host='mysftpserver', port=1211, username='myusername', password='mypassword')
remotepath='/Orders/incoming/myfile.csv'
localpath='/Users/myusername/projects/order88.csv'
s.put(localpath,remotepath)
s.close()
except Exception, e:
print str(e)
sftpExample()
The pysftp documentation and other answers on Stack Overflow also seem to suggest that the error can be resolved by setting cnopts.hostkeys = None.
So the full code would be something like:
import pysftp
def sftpExample():
cnopts = pysftp.CnOpts()
cnopts.hostkeys = None
with pysftp.Connection('hostname', username='me', password='secret', cnopts=cnopts) as sftp:
sftp.put('/Users/myusername/projects/order88.csv','/Orders/incoming/myfile.csv') # upload file to public/ on remote
sftp.close()
sftpExample()
Hope it helps!
Per the pysftp documentation you need to have the remote host key in your ~/.ssh/known_hosts. You can do this by connecting to the server via the ssh command (it will ask you if you want to add a new key to your hosts file; simply type yes if you trust the remote host's fingerprint).
The official documentation also points out how to disable host checking entirely, but this is NOT recommended as it would defeat critical security features for SSH identification.

Categories

Resources