Парамико "Неизвестный сервер"
Я пытаюсь начать работу с библиотекой Paramiko, но библиотека выдает исключение, как только я пытаюсь подключиться с помощью следующей простой программы:
import paramiko
ssh = paramiko.SSHClient()
ssh.connect('127.0.0.1', username='boatzart', password='mypassword')
Я получаю ошибку:
Traceback (most recent call last):
File "test.py", line 6, in <module>
ssh.connect('127.0.0.1')
File "build/bdist.macosx-10.7-intel/egg/paramiko/client.py", line 316, in connect
File "build/bdist.macosx-10.7-intel/egg/paramiko/client.py", line 85, in missing_host_key
paramiko.SSHException: Unknown server 127.0.0.1
Это происходит независимо от того, какой сервер я пытаюсь.
6 ответов
Исключение было вызвано тем, что вы пропустили ключ хоста, довольно загадочный "Неизвестный сервер" является ключом - поскольку исключение было вызвано из missing_host_key
Попробуйте это вместо этого:
import paramiko
paramiko.util.log_to_file('ssh.log') # sets up logging
client = paramiko.SSHClient()
client.load_system_host_keys()
client.connect('127.0.0.1', username=username, password=password)
stdin, stdout, stderr = client.exec_command('ls -l')
Я столкнулся с той же проблемой, и вот решение, которое сработало для меня:
import paramiko
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect('127.0.0.1', username=username, password=password)
stdin, stdout, stderr = client.exec_command('ls -l')
Это необходимо для установки политики, используемой при подключении к серверу, у которого нет ключа хоста ни в системном, ни в локальном объекте HostKeys. Политика по умолчанию - отклонять все неизвестные серверы (используя RejectPolicy). Вы можете заменить AutoAddPolicy или написать свой собственный класс политики.
Более подробная информация на paramiko api doc. Надеюсь это поможет.
Правильный путь:
Позвоните
HostKeys.add
в случае, возвращенномSSHClient.get_host_keys
перед вызовомconnect
Передав ему доверенный ключ.keydata = b"""AAAAB3NzaC1yc2EAAAADAQAB...""" key = paramiko.RSAKey(data=decodebytes(keydata)) client.get_host_keys().add('example.com', 'ssh-rsa', key)
Или загрузите уже кэшированный хост-ключ (например, из командной строки
ssh
) с помощьюclient.load_system_host_keys()
,Или вы можете, по крайней мере, кэшировать хост-ключ с первой попытки, чтобы убедиться, что он не изменится в будущем.
Для этого использования
SSHClient.load_host_keys
доconnect
, Это заставляет Paramiko автоматически добавлять новый ключ хоста в файл (в сочетании сAutoAddPolicy
).
Я столкнулся с этой проблемой и хотел опубликовать решение здесь. Проблема была в том, что ssh-сервер отправлял ключи ecdsa, которые не поддерживаются (пока) с paramiko. В моей системе Debian Wheezy я отключил ecdsa, закомментировав одну строку в / etc / ssh / sshd_config:
# HostKey / etc / ssh / ssh_host_ecdsa_key
Перезапустил sshd, и он вернулся к использованию RSA. В моем файле known_hosts было несколько ключей ecdsa, поэтому я просто удалил их для сброса и вошел в систему вручную, чтобы воссоздать ключи. Оттуда Paramiko работал отлично, как и ожидалось, с проверкой ключа хоста RSA.
У меня была эта ошибка: я могу подключиться из оболочки, но paramiko говорит: "Неизвестный сервер workdevel114".
В известном_хосте было две похожих записи:
user@host> grep workdevel114 ~/.ssh/known_hosts
workdevel114 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC8qGbuI1BaBodi7sKWLfV8Eh+De80Th7HFLD4WiJWo57THl0Q+QcopUaU3pF....
user@host> grep I1BaBodi7sKWLfV8Eh+De80Th7HFLD4WiJWo57THl0Q+QcopUaU3pF ~/.ssh/known_hosts
workdevel114 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC8qGbuI1BaBodi7sK...
|1|f/auQ9nY5dFbVtOdY3ocjtVO9dM=|esvazUDTT3VIcLk9DxmPI6FZt1s= ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC8qGbuI1BaBodi7sKWLfV8Eh+De80Th7HFLD4...
Запись секунд (|1|....), кажется, сбивает с толку paramiko. Я думаю, это связано с этим билетом: https://github.com/paramiko/paramiko/issues/67
Я решил это, добавив эту строку:
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
Но это отключает проверку хоста протокола ssh в этом случае: Paramiko считает, что ключ хоста неизвестен, но он известен. Известный Ключ игнорируется. Мне все равно, потому что атаки "человек посередине" очень маловероятны в моей среде.
параико-версия: 1.7.7.1-1ubuntu1
Я попытался включить часть ответа Мартина Прикрыла в один класс с помощью менеджера контекста.
Или вы можете хотя бы кэшировать ключ хоста с первой попытки, чтобы убедиться, что он не изменится в будущем. Для этого использования
SSHClient
.load_host_keys перед подключением. Это заставляет Paramiko автоматически добавлять новый ключ хоста в файл (в сочетании сAutoAddPolicy
).
import paramiko
from paramiko import client, sftp_client
class SFTP:
sftp: sftp_client.SFTPClient
ssh: client.SSHClient
host: str
user: str
password: str
def __init__(self, host: str, user: str, password: str):
self.host = host
self.user = user
self.password = password
def __enter__(self) -> sftp_client.SFTPClient:
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.load_system_host_keys()
ssh.connect(self.host, username=self.user, password=self.password)
self.ssh = ssh
sftp = ssh.open_sftp()
self.sftp = sftp
return sftp
def __exit__(self, exc, _, __) -> bool:
if exc is None:
self.sftp.close()
self.ssh.close()
return True
raise exc
Пример:
with SFTP('host', 'user', 'password') as sftp:
...