22

I am trying to use Paramiko to make an SSH communication between 2 servers on a private network. The client server is a web server and the host server is going to be a "worker" server. The idea was to not open up the worker server to HTTP connections. The only communication that needs to happen, is the web server needs to pass strings to a script on the worker server. For this I was hoping to use Paramiko and pass the information to the script via SSH.

I set up a new user and created a test script in Python 3, which works when I run it from the command line from my own user's SSH session. I put the same code into my Django web app, thinking that it should work, since it tests OK from the command line, and I get the following error:

Server 'worker-server' not found in known_hosts

Now, I think I understand this error. When performing the test script, I was using a certain user to access the server, and the known hosts information is saved to ~/.ssh/known_hosts even though the user is actually a 3rd party user created just for this one job. So the Django app is running under a different user who doesn't find the saved known hosts info because it doesn't have access to that folder. As far as I can tell the user which Apache uses to execute the Django scripts doesn't have a home directory.

Is there a way I can add this known host in a way that the Django process can see it?

Script:

import paramiko

client = paramiko.SSHClient()
client.load_system_host_keys()
client.connect('worker-server', 22, 'workeruser', 'workerpass')

code = "123wfdv"
survey_id = 111
stdin, stdout, stderr =
    client.exec_command('python3 /path/to/test_script/test.py %s %s' % ( code, survey_id ))

print( "ssh successful. Closing connection" )

stdout = stdout.readlines()
client.close()
print ( "Connection closed" )

output = ""
for line in stdout:
    output = output + line
if output!="":
    print ( output )
else:
    print ( "There was no output for this command" )
Psionman
  • 3,084
  • 1
  • 32
  • 65
jeffery_the_wind
  • 17,048
  • 34
  • 98
  • 160

2 Answers2

42

You can hard-code the host key in your Python code, using HostKeys.add:

import paramiko
from base64 import decodebytes

keydata = b"""AAAAB3NzaC1yc2EAAAABIwAAAQEA0hV..."""
key = paramiko.RSAKey(data=decodebytes(keydata))
 
client = paramiko.SSHClient()
client.get_host_keys().add('example.com', 'ssh-rsa', key)
client.connect(...)

Or, as you are connecting within a private network, you can give up on verifying host key altogether, using AutoAddPolicy:

client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect(...)

(This can be done only if you really do not need the connection to be secure)

Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992
  • I know this post is ~5 years old... but it just saved me a huge amount of work! Thanks for posting!!! – Pete Apr 24 '23 at 18:31
0

In addition to Martin Prikryl answer, maybe you're coding for a dynamic environment where you don't know this information, then you could validate de host by yourself and then add to know_hosts file. This answer is oriented to sys admins.

Direct add:

$ ssh-keyscan sample.host.com >> ~/.ssh/known_hosts
o
$ ssh-keyscan 192.168.1.20 >> ~/.ssh/known_hosts

Need user input:

$ ssh sample.host.com
o
$ ssh 192.168.1.20

Keep in mind that you must have the correct credentials to successfully connect.

Luis Carlos
  • 345
  • 3
  • 10