Verificar la clave de host con pysftp
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'
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_hosts
contiene 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-keyscan
a 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 .
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=None
perderá la protección contra ataques de intermediario. Utilice la respuesta @ martin-prikryl para evitar eso.