Raghavulu
Raghavulu

Reputation: 31

BadHostKeyException during connection using Paramiko SSH client using private key

I'm trying to upload file from s3 bucket to external SFTP server using paramiko. I've been getting BadHostKeyException: Host key for server 'XXXXXXX' does not match: got 'got_key' expected 'expect_key'. I've checked Automatically updating known_hosts file when host key changes using Paramiko but not sure that the "BadHostKeyException" is a sign of man-in-the-middle-attack. Can someone help?

#Read ssh key
key_obj = boto3.resource('s3').Object(s3_bucket, key_file)
key_str = key_obj.get()['Body'].read().decode('utf-8')
key = paramiko.RSAKey.from_private_key(io.StringIO(key_str), password='XXX') // password is private key password


#Create SSH client for SFTP upload
ssh_client = paramiko.SSHClient()
ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh_client.get_host_keys().add('sftp_host', 'ssh-rsa', key) 
ssh_client.connect('sftp_host', port=22, username='user_name', pkey=key)
ftp_client= ssh_client.open_sftp()

Upvotes: 2

Views: 7339

Answers (2)

Raghavulu
Raghavulu

Reputation: 31

ssh_client.get_host_keys().add('sftp_host', 'ssh-rsa', key) is causing the problem here. Its actually adding my private key as host key and the same is compared with the host key from server, hence I was getting host key doesn't match. I've used key.get_base64() to get the pub key of the host and added it to known hosts which is then used during connect method to authenticate with host key generated during connect method

#Read ssh key
key_obj = boto3.resource('s3').Object(s3_bucket, key_file)
key_str = key_obj.get()['Body'].read().decode('utf-8')
key = paramiko.RSAKey.from_private_key(io.StringIO(key_str), password='XXX') // password is private key password

#Get pub key to add to known hosts
key_pub = paramiko.RSAKey(data=decodebytes(bytes(key.get_base64(), 'utf-8')), password='sftp_key_password')

#Create SSH client for SFTP upload
ssh_client = paramiko.SSHClient()
ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh_client.get_host_keys().add('sftp_host', 'ssh-rsa',  key_pub)
ssh_client.connect('sftp_host', port=22, username='user_name', pkey=key)
ftp_client= ssh_client.open_sftp()

#Upload gz using SFTP    
def upload_file(file_name, pandasdf, sep='|', encoding='utf-8'):
    with gzip.open(ftp_client.open(file_name, "w+", 32768), 'w+') as f:
        f.write(bytes(pandasdf.to_csv(index=False, sep=sep), encoding=encoding))

#Call upload file function
try:
    upload_file(file_name, pandasdf)
except Exception as e:
    print(e)
    print('Error while uploading file to SFTP ' + file_name)
    raise e

#Close SFTP and file resources opened
ftp_client.close()
ssh_client.close() 

Upvotes: 1

Martin Prikryl
Martin Prikryl

Reputation: 202242

Your SSH/SFTP server host key has changed. When that happens, any decent SSH/SFTP library or client will warn you and/or prevent the connections from continuing. Change of the host key is a sign of a man-in-the-middle attack.

When this happens, you should contact your server administrator to ask whether the host key change was legitimate (e.g. the server was reinstalled) or not. If the server key has not changed, you might be under an attack.

If the key changed was legitimate, the administrator should have warned you in advance. Anyway, is this case, update the host key in your code or configuration. In your case, it's the get_host_keys().add call. In other cases, the host key might be cached in .ssh/known_hosts file.


Note that the host key has nothing to do with the "private key" you use to authenticate to your SSH server (RSAKey.from_private_key). You might want to read my article Understanding SSH key pairs.


Related question: Verify host key with pysftp.

Upvotes: 0

Related Questions