The HashKnownHosts
directive in SSH configuration determines whether hostnames and addresses in ~/.ssh/known_hosts
are stored in hashed form. When enabled (HashKnownHosts yes
), it provides an important security layer by obfuscating sensitive connection information.
Consider this real-world scenario: if an attacker gains access to your system, an unhashed known_hosts file reveals:
- All servers you regularly connect to
- Their IP addresses or domain names
- Potential network topology information
With hashing enabled, this reconnaissance becomes significantly harder as host identifiers are stored as SHA-1 hashes.
While the security benefits are clear, there are practical tradeoffs:
# Example known_hosts entry (unhashed):
example.com ssh-rsa AAAAB3...
# Hashed equivalent:
|1|F1E9Ke...=|k5DZP3... ecdsa-sha2-nistp256 AAAAB3...
The hashing process:
- Adds minimal overhead during connection establishment
- Makes manual file maintenance more challenging
- Requires using
ssh-keygen -H -F hostname
for lookups
For most environments, I recommend enabling hashing while maintaining these practices:
# In /etc/ssh/ssh_config or ~/.ssh/config
Host *
HashKnownHosts yes
IdentitiesOnly yes
When you need to verify a hashed entry:
ssh-keygen -H -F example.com
For teams managing multiple systems, consider these approaches:
- Maintain a master unhashed known_hosts in version control
- Deploy with hashing enabled via configuration management:
# Ansible example
- name: Configure SSH to hash known hosts
lineinfile:
path: /etc/ssh/ssh_config
line: "HashKnownHosts yes"
state: present
If you encounter problems after enabling hashing:
- Verify file permissions (
chmod 644 ~/.ssh/known_hosts
) - Check for duplicate entries (
sort -u ~/.ssh/known_hosts
) - Remember hostnames are case-sensitive in hashed form
While reviewing SSH configurations across multiple servers, I noticed an interesting divergence: some systems had HashKnownHosts yes
while others kept it disabled. This discovery prompted me to dig deeper into the actual security implications of this setting.
When enabled, HashKnownHosts
transforms entries in ~/.ssh/known_hosts
from:
server1.example.com ssh-rsa AAAAB3Nz...
To something like:
|1|JfKT7h6F3+9Pxw3p3OL4iQ==|k5D8L9z2aXvG...= ssh-rsa AAAAB3Nz...
The primary security benefits include:
- Prevents hostname harvesting: Even if an attacker gains access to your known_hosts file, they can't see which systems you connect to
- Reduces reconnaissance value for attackers who compromise your account
- Protects internal network topology from being exposed through the hostnames
To enable globally (affects all users):
# /etc/ssh/ssh_config
HashKnownHosts yes
For per-user configuration:
# ~/.ssh/config
Host *
HashKnownHosts yes
Legitimate cases for HashKnownHosts no
include:
- When manually managing known_hosts files across multiple systems
- For troubleshooting SSH connection issues
- In development environments where hostnames need to be human-readable
You can still verify hashed entries using:
ssh-keygen -H -F example.com
To temporarily disable hashing for a specific connection:
ssh -o HashKnownHosts=no user@host
If switching existing systems to hashed mode:
- Back up your current known_hosts file
- Run
ssh-keygen -H
to convert existing entries - Verify connections to critical systems
- Update any automation that parses known_hosts