RED HAT ENTERPRISE LINUX

SSH Security

Host Keys and Key-Based Authentication

College-Level Course Module | RHEL System Administration

Learning Objectives

1
Understand SSH security concepts

Encryption, authentication, and the SSH protocol

2
Manage host keys

Verify server identity and handle host key changes

3
Generate SSH key pairs

Create public/private key pairs with ssh-keygen

4
Configure key-based authentication

Deploy public keys and authenticate without passwords

5
Harden SSH configuration

Secure SSH server settings and best practices

Why SSH Security Matters

SSH (Secure Shell) provides encrypted communication between systems. It protects against eavesdropping, connection hijacking, and other attacks on remote sessions.

Without SSH (Telnet, rsh):
  • Passwords sent in clear text
  • Data visible to network sniffers
  • No server verification
  • Vulnerable to man-in-the-middle
With SSH:
  • All traffic encrypted
  • Server identity verified
  • Strong authentication options
  • Protection from interception
SSH uses: Remote shell access, secure file transfer (scp, sftp), tunneling, port forwarding, and Git operations.

SSH Architecture

SSH Client
(your machine)
Encrypted
Connection
SSH Server
(sshd daemon)
ComponentLocationPurpose
sshClientConnect to remote servers
sshdServerAccept incoming connections
Host keysServer (/etc/ssh/)Prove server identity
User keysClient (~/.ssh/)Prove user identity
known_hostsClient (~/.ssh/)Remember trusted servers
authorized_keysServer (~/.ssh/)Accepted public keys for login
# SSH client connects to SSH server (sshd)
[user@client ~]$ ssh user@server.example.com

Host Keys Explained

Host keys are cryptographic keys that identify an SSH server. They prove you are connecting to the real server, not an imposter.

# Server's host keys (on the server)
[root@server ~]# ls -la /etc/ssh/ssh_host_*
-rw-r-----. 1 root ssh_keys  480 Jan 15 ssh_host_ecdsa_key
-rw-r--r--. 1 root root      162 Jan 15 ssh_host_ecdsa_key.pub
-rw-r-----. 1 root ssh_keys  387 Jan 15 ssh_host_ed25519_key
-rw-r--r--. 1 root root       82 Jan 15 ssh_host_ed25519_key.pub
-rw-r-----. 1 root ssh_keys 2590 Jan 15 ssh_host_rsa_key
-rw-r--r--. 1 root root      554 Jan 15 ssh_host_rsa_key.pub
Key Types:
  • ed25519 - Modern, fast, secure (preferred)
  • ecdsa - Elliptic curve (good)
  • rsa - Traditional (3072+ bits recommended)
Files:
  • Private key: ssh_host_*_key (secret!)
  • Public key: ssh_host_*_key.pub
  • Permissions must be restrictive

First Connection

# First time connecting to a server
[user@client ~]$ ssh user@server.example.com
The authenticity of host 'server.example.com (192.168.1.100)' can't be established.
ED25519 key fingerprint is SHA256:AbCdEf1234567890xYzAbCdEf1234567890xYz.
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added 'server.example.com' (ED25519) to the list of known hosts.
Security moment: This prompt is asking "Do you trust this server?" You should verify the fingerprint through a separate channel before typing "yes".
# On the server: get the fingerprint to verify
[root@server ~]# ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub
256 SHA256:AbCdEf1234567890xYzAbCdEf1234567890xYz root@server (ED25519)
Verification methods: Console access, phone call to admin, published fingerprints, configuration management

The known_hosts File

~/.ssh/known_hosts stores public keys of servers you have connected to. SSH uses this to detect if a server's identity changes.

# View known_hosts
[user@client ~]$ cat ~/.ssh/known_hosts
server.example.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBcd...
192.168.1.100 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBcd...
webserver.lab ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC...

# Show fingerprints in known_hosts
[user@client ~]$ ssh-keygen -lf ~/.ssh/known_hosts
256 SHA256:AbCdEf... server.example.com (ED25519)
256 SHA256:AbCdEf... 192.168.1.100 (ED25519)
3072 SHA256:XyZabc... webserver.lab (RSA)

# System-wide known hosts (all users)
/etc/ssh/ssh_known_hosts

# Remove a specific host entry
[user@client ~]$ ssh-keygen -R server.example.com
# Host server.example.com found: line 1
/home/user/.ssh/known_hosts updated.

Host Key Changed Warning

[user@client ~]$ ssh user@server.example.com
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
It is also possible that a host key has just been changed.
The fingerprint for the ED25519 key sent by the remote host is
SHA256:NewFingerprint1234567890abcdef.
Please contact your system administrator.
Add correct host key in /home/user/.ssh/known_hosts to get rid of this message.
Offending key in /home/user/.ssh/known_hosts:1
Host key for server.example.com has changed and you have requested strict checking.
Host key verification failed.
This warning means: The server's key is different from what you previously accepted. This could be an attack OR a legitimate change (server rebuild, key rotation).

Resolving Host Key Issues

# Step 1: Verify the key change is legitimate
# (Contact admin, check console, verify through secure channel)

# Step 2: Remove the old key
[user@client ~]$ ssh-keygen -R server.example.com
# Host server.example.com found: line 1
/home/user/.ssh/known_hosts updated.
Original contents retained as /home/user/.ssh/known_hosts.old

# Also remove by IP if you used that
[user@client ~]$ ssh-keygen -R 192.168.1.100

# Step 3: Connect again and verify new fingerprint
[user@client ~]$ ssh user@server.example.com
The authenticity of host 'server.example.com (192.168.1.100)' can't be established.
ED25519 key fingerprint is SHA256:NewFingerprint1234567890abcdef.
Are you sure you want to continue connecting (yes/no)? yes

# Alternative: manually edit known_hosts
[user@client ~]$ vim ~/.ssh/known_hosts
# Delete the offending line, save, reconnect

Key-Based Authentication

Key-based authentication uses cryptographic key pairs instead of passwords. It is more secure and enables passwordless login.

🔐
Private Key
~/.ssh/id_ed25519
KEEP SECRET!
🔓
Public Key
~/.ssh/id_ed25519.pub
Share freely
How it works: Your private key proves your identity. The server has your public key and challenges you to prove you have the matching private key - without ever transmitting it.

Generating Key Pairs

# Generate an Ed25519 key (recommended)
[user@client ~]$ ssh-keygen -t ed25519
Generating public/private ed25519 key pair.
Enter file in which to save the key (/home/user/.ssh/id_ed25519): [Enter for default]
Created directory '/home/user/.ssh'.
Enter passphrase (empty for no passphrase): [Enter strong passphrase]
Enter same passphrase again:
Your identification has been saved in /home/user/.ssh/id_ed25519
Your public key has been saved in /home/user/.ssh/id_ed25519.pub
The key fingerprint is:
SHA256:YourKeyFingerprint1234567890 user@client
The key's randomart image is:
+--[ED25519 256]--+
|     .o+*O=+o    |
|     ..oB+*.     |
...

# Generate RSA key (if Ed25519 not supported)
[user@client ~]$ ssh-keygen -t rsa -b 4096

# Generate with specific filename
[user@client ~]$ ssh-keygen -t ed25519 -f ~/.ssh/work_key

Examining Your Keys

# View files in .ssh directory
[user@client ~]$ ls -la ~/.ssh/
drwx------. 2 user user   80 Jan 20 10:00 .
-rw-------. 1 user user  419 Jan 20 10:00 id_ed25519
-rw-r--r--. 1 user user   96 Jan 20 10:00 id_ed25519.pub
-rw-r--r--. 1 user user  442 Jan 20 10:00 known_hosts

# View public key (this is what you share)
[user@client ~]$ cat ~/.ssh/id_ed25519.pub
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBcd... user@client

# View key fingerprint
[user@client ~]$ ssh-keygen -lf ~/.ssh/id_ed25519.pub
256 SHA256:YourKeyFingerprint1234567890 user@client (ED25519)

# NEVER share or display your private key!
# Private key should only be readable by you (mode 600)
Permissions are critical: Private key must be mode 600 (owner read/write only). SSH refuses to use keys with wrong permissions.

Deploying Public Keys

Copy your public key to the server's ~/.ssh/authorized_keys file to enable key-based login.

# Method 1: ssh-copy-id (easiest, recommended)
[user@client ~]$ ssh-copy-id user@server.example.com
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/home/user/.ssh/id_ed25519.pub"
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s)
user@server.example.com's password: [enter password]
Number of key(s) added: 1

Now try logging into the machine, with:   "ssh 'user@server.example.com'"
and check to make sure that only the key(s) you wanted were added.

# Method 2: Manual copy (if ssh-copy-id unavailable)
[user@client ~]$ cat ~/.ssh/id_ed25519.pub | ssh user@server 'mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys'

# Method 3: Copy and paste manually
# 1. cat ~/.ssh/id_ed25519.pub (copy output)
# 2. SSH to server with password
# 3. Paste into ~/.ssh/authorized_keys

Using Key-Based Auth

# Connect using your key (key is used automatically)
[user@client ~]$ ssh user@server.example.com
Enter passphrase for key '/home/user/.ssh/id_ed25519': [passphrase if set]
Last login: Mon Jan 20 10:30:00 2024
[user@server ~]$

# Specify a different key file
[user@client ~]$ ssh -i ~/.ssh/work_key user@server.example.com

# Verbose mode to troubleshoot authentication
[user@client ~]$ ssh -v user@server.example.com
...
debug1: Authentications that can continue: publickey,password
debug1: Offering public key: /home/user/.ssh/id_ed25519 ED25519 SHA256:abc...
debug1: Server accepts key: /home/user/.ssh/id_ed25519 ED25519 SHA256:abc...
debug1: Authentication succeeded (publickey).
...

# If key auth fails, SSH falls back to password
Success! If you set a passphrase, you enter it locally - it is never transmitted. If no passphrase, login is completely passwordless.

SSH Agent

ssh-agent caches your private keys in memory, so you only enter the passphrase once per session instead of every connection.

# Start ssh-agent (often already running in desktop environments)
[user@client ~]$ eval $(ssh-agent)
Agent pid 12345

# Add your key to the agent
[user@client ~]$ ssh-add
Enter passphrase for /home/user/.ssh/id_ed25519: [passphrase]
Identity added: /home/user/.ssh/id_ed25519 (user@client)

# Add a specific key
[user@client ~]$ ssh-add ~/.ssh/work_key

# List loaded keys
[user@client ~]$ ssh-add -l
256 SHA256:YourFingerprint user@client (ED25519)

# Remove all keys from agent
[user@client ~]$ ssh-add -D
All identities removed.
Agent forwarding: ssh -A forwards your agent to the remote server, allowing onward SSH connections using your local keys.

The authorized_keys File

# View authorized_keys on server
[user@server ~]$ cat ~/.ssh/authorized_keys
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBcd... user@client
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIXyz... user@laptop
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAB... admin@workstation

# Each line is one authorized public key
# Format: key-type key-data comment

# Add restrictions to a key
from="192.168.1.*",no-port-forwarding ssh-ed25519 AAAAC3... user@client

# Common restrictions:
# from="pattern"      - Only allow from specific hosts/IPs
# command="cmd"       - Only run this command
# no-port-forwarding  - Disable port forwarding
# no-X11-forwarding   - Disable X11 forwarding
# no-pty              - Disable terminal allocation
Permissions: authorized_keys must be mode 600 (rw-------) and owned by the user. SSH ignores it if permissions are wrong.

SSH Server Configuration

The SSH server (sshd) is configured in /etc/ssh/sshd_config. Adjust settings to harden security.

[root@server ~]# vim /etc/ssh/sshd_config

# Key security settings:
PermitRootLogin no              # Disable direct root login
PasswordAuthentication no        # Require key-based auth only
PubkeyAuthentication yes         # Enable key-based auth
AuthorizedKeysFile .ssh/authorized_keys  # Key file location

# Limit access
AllowUsers alice bob             # Only these users can SSH
AllowGroups sshusers             # Or only members of this group

# Other hardening
X11Forwarding no                 # Disable X11 forwarding
MaxAuthTries 3                   # Limit auth attempts
ClientAliveInterval 300          # Timeout idle connections
ClientAliveCountMax 2

# After changes, restart sshd
[root@server ~]# systemctl restart sshd

Disabling Password Auth

Warning: Only disable password authentication AFTER verifying key-based auth works! Otherwise you will lock yourself out.
# Step 1: Verify key-based auth works
[user@client ~]$ ssh -o PasswordAuthentication=no user@server
# If this works, you're safe to proceed

# Step 2: Edit sshd_config on server
[root@server ~]# vim /etc/ssh/sshd_config
PasswordAuthentication no

# Step 3: Restart sshd (keep current session open!)
[root@server ~]# systemctl restart sshd

# Step 4: Test from another terminal
[user@client ~]$ ssh user@server
# Should connect using key, no password prompt

# If locked out and have console access:
[root@server ~]# vim /etc/ssh/sshd_config
# Change back to: PasswordAuthentication yes
[root@server ~]# systemctl restart sshd

SSH Client Config

~/.ssh/config stores client-side settings for SSH connections. Define aliases, specify keys, and set options per host.

[user@client ~]$ cat ~/.ssh/config

# Default settings for all hosts
Host *
    ServerAliveInterval 60
    ServerAliveCountMax 3

# Shortcut for production server
Host prod
    HostName production.example.com
    User admin
    IdentityFile ~/.ssh/prod_key
    Port 2222

# Jump through bastion host
Host internal
    HostName 10.0.0.50
    User developer
    ProxyJump bastion.example.com

# Now you can simply type:
[user@client ~]$ ssh prod
# Instead of: ssh -i ~/.ssh/prod_key -p 2222 admin@production.example.com

Best Practices

Do

  • Verify host key fingerprints
  • Use Ed25519 keys when possible
  • Set passphrases on private keys
  • Use ssh-agent to cache keys
  • Disable password auth after key setup
  • Disable direct root login
  • Keep an open session during config changes
  • Restrict SSH access with AllowUsers

Do Not

  • Ignore host key warnings
  • Share private keys
  • Use weak or no passphrases
  • Store private keys on shared systems
  • Disable password auth before testing keys
  • Use RSA keys smaller than 3072 bits
  • Forward agent to untrusted servers
  • Leave default SSH port if targeted
Recovery plan: Always have console access or out-of-band management before making SSH changes that could lock you out.

Key Takeaways

1

Host Keys: Verify server identity. Check fingerprints on first connect. Investigate changed keys - could be attack or legitimate change.

2

Key Pairs: Generate with ssh-keygen -t ed25519. Private key stays secret, public key goes to servers.

3

Key Auth: Deploy with ssh-copy-id. Keys go in ~/.ssh/authorized_keys. More secure than passwords.

4

Hardening: Disable password auth, disable root login, use AllowUsers. Configure in /etc/ssh/sshd_config.

LAB EXERCISES

  • Generate an Ed25519 key pair with a passphrase
  • Deploy your public key to a remote server
  • Verify key-based authentication works
  • Use ssh-agent to cache your key
  • Examine and modify known_hosts
  • Disable password authentication on a test server
  • Create SSH client config shortcuts

Next: Secure File Transfer with scp and sftp