Verificar la clave de host con pysftp

Resuelto Gabriel Theodoulos asked hace 8 años • 0 respuestas

Estoy escribiendo un programa usando pysftp y quiero verificar la clave del host SSH con C:\Users\JohnCalvin\.ssh\known_hosts.

Usando PuTTY, el programa terminal lo guarda en el Registro [HKEY_CURRENT_USER\Software\SimonTatham\PuTTY\SshHostKeys].

¿Cómo concilio la diferencia entre pysftp y PuTTY?

Mi código es:

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()

La respuesta de error que estoy recibiendo es:

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'
Gabriel Theodoulos avatar Aug 14 '16 12:08 Gabriel Theodoulos
Aceptado

Pysftp tiene algunos errores relacionados con el manejo de claves de host, como se describe a continuación. También parece que el proyecto pysftp fue abandonado. Considere usar Paramiko directamente en su lugar. Pysftp es solo un contenedor encima de Paramiko y no agrega nada realmente significativo. Consulte pysftp frente a Paramiko .

Para el manejo de claves de host en Paramiko, consulte:
Paramiko "Servidor desconocido"


Si desea seguir usando pysftp, no lo configure cnopts.hostkeys = None(como muestra la segunda respuesta más votada), a menos que no le importe la seguridad. Al hacerlo, pierdes la protección contra los ataques de intermediario .

Utilice CnOpts.hostkeys(devuelve HostKeys) para administrar claves de host confiables.

cnopts = pysftp.CnOpts(knownhosts='known_hosts')

with pysftp.Connection(host, username, password, cnopts=cnopts) as sftp:

donde known_hostscontiene una clave pública del servidor en un formato como:

example.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQAB...

Si no desea utilizar un archivo externo, también puede utilizar

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:

Aunque a partir de pysftp 0.2.9, este enfoque emitirá una advertencia, lo que parece ser un error:
Advertencia "Error al cargar HostKeys" al conectarse al servidor SFTP con pysftp


Una forma sencilla de recuperar la clave de host en el formato necesario es utilizar OpenSSH ssh-keyscan:

$ ssh-keyscan example.com
# example.com SSH-2.0-OpenSSH_5.3
example.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQAB...

(debido a un error en pysftp, esto no funciona si el servidor usa un puerto no estándar ; la entrada comienza con [example.com]:port+ tenga cuidado con la redirección ssh-keyscana un archivo en PowerShell )

También puede hacer que la aplicación haga lo mismo automáticamente:
use Paramiko AutoAddPolicy con pysftp
(agregará automáticamente claves de host de nuevos hosts known_hosts, pero para claves de host conocidas, no aceptará una clave modificada)


Aunque para una seguridad absoluta, no debe recuperar la clave del host de forma remota, ya que no puede estar seguro si aún no está siendo atacado.

Consulte mi artículo ¿Dónde obtengo la huella digital de la clave del host SSH para autorizar el servidor?
Es para mi cliente WinSCP SFTP, pero la mayor parte de la información que contiene es válida en general.


Si necesita verificar la clave del host usando solo su huella digital, consulte Python - pysftp / paramiko - Verificar la clave del host usando su huella digital .

Martin Prikryl avatar Apr 13 '2017 10:04 Martin Prikryl

Una opción es desactivar el requisito de clave de host:

import pysftp
cnopts = pysftp.CnOpts()
cnopts.hostkeys = None   
with pysftp.Connection(host, username, password, cnopts=cnopts) as sftp:
    sftp.put(local_path, remote_path)

Puede encontrar más información al respecto aquí: https://stackoverflow.com/a/38355117/1060738

Nota IMPORTANTE:

Al configurarlo, cnopts.hostkeys=Noneperderá la protección contra ataques de intermediario. Utilice la respuesta @ martin-prikryl para evitar eso.

Noam Peled avatar Aug 18 '2016 13:08 Noam Peled