Paramiko’s host key policy determines what happens when connecting to an SSH server whose host key is not present in the local known_hosts file. Properly configuring MissingHostKeyPolicy balances convenience and security. This article explains built-in policies, risks, and how to implement secure custom policies.
1. Why Host Key Policies Matter
SSH host keys verify server identity. If a key is unknown, you risk connecting to a malicious host. MissingHostKeyPolicy handles unknown keys on initial connections.
2. Built-In Host Key Policies
| Policy | Behavior | Use Case |
|---|---|---|
RejectPolicy |
Refuses connection if key is unknown | Highest security; manual key management |
AutoAddPolicy |
Adds unknown key to host keys and connects | Convenience; for trusted environments |
WarningPolicy |
Logs warning on unknown key but connects | Development/testing; audit notifications |
3. Selecting a Policy
Balance security vs. automation:
- Production: Use
RejectPolicyand provision keys via secure channels. - Automation: Use
AutoAddPolicyonly within controlled networks. - Development: Use
WarningPolicyto track unexpected hosts.
4. Configuring Host Key Policy in Code
import paramiko
ssh = paramiko.SSHClient()
ssh.load_system_host_keys()
# Example: Auto-add unknown keys
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect('example.com', username='user')
5. Implementing a Custom Policy
Create a policy to validate against a remote key server or fingerprint whitelist:
from paramiko.client import MissingHostKeyPolicy
class CustomPolicy(MissingHostKeyPolicy):
def __init__(self, allowed_fingerprints):
self.allowed = allowed_fingerprints
def missing_host_key(self, client, hostname, key):
fp = key.get_fingerprint().hex()
if fp in self.allowed:
client._host_keys.add(hostname, key.get_name(), key)
else:
raise paramiko.BadHostKeyException(hostname, key, None)
# Usage
allowed = {'3f:2a:...'} # hex-encoded fingerprints
ssh = paramiko.SSHClient()
ssh.load_system_host_keys()
ssh.set_missing_host_key_policy(CustomPolicy(allowed))
ssh.connect('example.com', username='user')
Tip: Obtain fingerprints from out-of-band secure channels to avoid MITM attacks.
6. Summary Checklist
- Always
load_system_host_keys()or manually load a known_hosts file. - Choose
RejectPolicyfor production security. - Use
AutoAddPolicyonly in trusted, internal environments. - Use
WarningPolicyin development to log unknown hosts. - Implement custom policies to enforce fingerprint whitelists or external validation.
