RED HAT ENTERPRISE LINUX

Securing SSH Communication

Host Keys and Key-Based Authentication

CIS126RH | RHEL System Administration 1
Mesa Community College

Learning Objectives

1
Understand SSH host keys

Explain how host keys verify server identity and prevent MITM attacks

2
Manage known hosts

Handle host key verification, updates, and the known_hosts file

3
Generate SSH key pairs

Create secure RSA and Ed25519 keys with appropriate passphrases

4
Configure key-based authentication

Deploy public keys and optionally disable password authentication

SSH Security Overview

SSH (Secure Shell) provides encrypted communication between systems. Security depends on verifying both the server (host keys) and the user (authentication).

Encryption

All traffic is encrypted, protecting data from eavesdropping

Host Verification

Host keys prove server identity, preventing MITM attacks

User Authentication

Passwords or keys verify the user's identity

Integrity

MACs detect any tampering with transmitted data

⚠ Critical: Encryption alone isn't enough. Without host verification, an attacker could intercept your connection and decrypt everything.

Understanding Host Keys

Every SSH server has host key pairs that uniquely identify it. When you connect, the server proves its identity using these keys.

# Server's host keys are stored in /etc/ssh/
[root@server ~]# ls -la /etc/ssh/ssh_host_*
-rw-r-----. 1 root ssh_keys  480 Jan 15 10:30 /etc/ssh/ssh_host_ecdsa_key
-rw-r--r--. 1 root root      162 Jan 15 10:30 /etc/ssh/ssh_host_ecdsa_key.pub
-rw-r-----. 1 root ssh_keys  387 Jan 15 10:30 /etc/ssh/ssh_host_ed25519_key
-rw-r--r--. 1 root root       82 Jan 15 10:30 /etc/ssh/ssh_host_ed25519_key.pub
-rw-r-----. 1 root ssh_keys 2578 Jan 15 10:30 /etc/ssh/ssh_host_rsa_key
-rw-r--r--. 1 root root      550 Jan 15 10:30 /etc/ssh/ssh_host_rsa_key.pub
Key Type Files Notes
Ed25519 ssh_host_ed25519_key[.pub] Modern, fast, recommended
ECDSA ssh_host_ecdsa_key[.pub] Elliptic curve, widely supported
RSA ssh_host_rsa_key[.pub] Legacy compatibility, use 3072+ bits

First Connection: Verification

[student@workstation ~]$ ssh student@server.example.com
The authenticity of host 'server.example.com (192.168.1.100)' can't be established.
ED25519 key fingerprint is SHA256:xH7vK9mPqL2nR4wY8sT6uB3fJ5aD1eG9hC0iZ2kM7nQ.
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.
student@server.example.com's password:
The fingerprint is a hash of the public key:
SHA256:xH7vK9mPqL2nR4wY8sT6uB3fJ5aD1eG9hC0iZ2kM7nQ
⚠ Security Decision: Don't blindly type "yes"! In secure environments, verify the fingerprint through an out-of-band channel (phone call, secure document, physical access).

The known_hosts File

# Client stores known host keys in ~/.ssh/known_hosts
[student@workstation ~]$ cat ~/.ssh/known_hosts
server.example.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI...
192.168.1.100 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI...
webserver.lab.local ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNo...

# View fingerprints of known hosts
[student@workstation ~]$ ssh-keygen -l -f ~/.ssh/known_hosts
256 SHA256:xH7vK9mPqL2nR4wY8sT6uB3fJ5aD1eG9hC0iZ2kM7nQ server.example.com (ED25519)
256 SHA256:xH7vK9mPqL2nR4wY8sT6uB3fJ5aD1eG9hC0iZ2kM7nQ 192.168.1.100 (ED25519)
256 SHA256:aB3cD4eF5gH6iJ7kL8mN9oP0qR1sT2uV3wX4yZ5aB6c webserver.lab.local (ECDSA)

# Remove a specific host entry
[student@workstation ~]$ ssh-keygen -R server.example.com
Host server.example.com found: line 1
/home/student/.ssh/known_hosts updated.
Format: Each line contains: hostname[,IP] key-type public-key. A host may have multiple entries for different key types or names.

Host Key Changed Warning

[student@workstation ~]$ ssh student@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:nEwKeY9fInGeRpRiNt8xYz7AbCdEfGhIjKlMnOpQrSt.
Please contact your system administrator.
Add correct host key in /home/student/.ssh/known_hosts to get rid of this message.
Offending key in /home/student/.ssh/known_hosts:1
Host key for server.example.com has changed and you have requested strict checking.
Host key verification failed.
STOP! This warning means the server's key doesn't match what you expect. Either the server was reinstalled/changed, or you're being attacked.

Verifying Host Key Fingerprints

# On the SERVER, view host key fingerprints
[root@server ~]# ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub
256 SHA256:xH7vK9mPqL2nR4wY8sT6uB3fJ5aD1eG9hC0iZ2kM7nQ root@server (ED25519)

# View all host key fingerprints
[root@server ~]# for key in /etc/ssh/ssh_host_*_key.pub; do ssh-keygen -lf "$key"; done
256 SHA256:eC2dSa... root@server (ECDSA)
256 SHA256:xH7vK9... root@server (ED25519)
3072 SHA256:rS4aKe... root@server (RSA)

# Show fingerprint in different format (legacy MD5)
[root@server ~]# ssh-keygen -E md5 -lf /etc/ssh/ssh_host_ed25519_key.pub
256 MD5:a1:b2:c3:d4:e5:f6:a7:b8:c9:d0:e1:f2:a3:b4:c5:d6 root@server (ED25519)

# On the CLIENT, compare when connecting
[student@workstation ~]$ ssh -o FingerprintHash=sha256 server.example.com
Verification Process: Get the fingerprint from the server through a trusted channel (console, documentation, phone) and compare it with what SSH displays when connecting.

Public Key Cryptography

🔐
Private Key
id_ed25519

Secret! Never share.
Used to prove identity.

🔓
Public Key
id_ed25519.pub

Safe to share.
Place on servers.

How it works: Data encrypted with the public key can only be decrypted with the private key. The server sends a challenge encrypted with your public key. Only you can decrypt it with your private key, proving your identity without transmitting secrets.

Generating SSH Key Pairs

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

# Generate RSA key (for legacy compatibility, use 4096 bits)
[student@workstation ~]$ ssh-keygen -t rsa -b 4096

# Generate with specific filename and comment
[student@workstation ~]$ ssh-keygen -t ed25519 -f ~/.ssh/work_key -C "work laptop 2024"

SSH Key Permissions

~/.ssh/
700
drwx------
~/.ssh/id_ed25519
600
-rw-------
~/.ssh/id_ed25519.pub
644
-rw-r--r--
~/.ssh/authorized_keys
600
-rw-------
~/.ssh/known_hosts
644
-rw-r--r--
~/.ssh/config
600
-rw-------
# Fix permissions if needed
[student@workstation ~]$ chmod 700 ~/.ssh
[student@workstation ~]$ chmod 600 ~/.ssh/id_ed25519
[student@workstation ~]$ chmod 644 ~/.ssh/id_ed25519.pub

# Check permissions
[student@workstation ~]$ ls -la ~/.ssh/
SSH will refuse to use keys with wrong permissions! Private keys must be readable only by the owner. This prevents other users from stealing your keys.

Deploying Public Keys: ssh-copy-id

# Copy public key to remote server (easiest method)
[student@workstation ~]$ ssh-copy-id student@server.example.com
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/home/student/.ssh/id_ed25519.pub"
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
student@server.example.com's password: [Enter password]

Number of key(s) added: 1

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

# Test key-based authentication
[student@workstation ~]$ ssh student@server.example.com
Enter passphrase for key '/home/student/.ssh/id_ed25519': [Key passphrase, not password]
[student@server ~]$

# Copy specific key file
[student@workstation ~]$ ssh-copy-id -i ~/.ssh/work_key.pub student@server.example.com

Manual Key Deployment

# View your public key
[student@workstation ~]$ cat ~/.ssh/id_ed25519.pub
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI... student@workstation

# Method 1: Pipe through SSH
[student@workstation ~]$ cat ~/.ssh/id_ed25519.pub | ssh student@server \
    "mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"

# Method 2: Copy and paste manually
# 1. Display the public key
[student@workstation ~]$ cat ~/.ssh/id_ed25519.pub
# 2. On the server, create the authorized_keys file
[student@server ~]$ mkdir -p ~/.ssh
[student@server ~]$ chmod 700 ~/.ssh
[student@server ~]$ vim ~/.ssh/authorized_keys   # Paste the key
[student@server ~]$ chmod 600 ~/.ssh/authorized_keys

# Verify the authorized_keys file
[student@server ~]$ cat ~/.ssh/authorized_keys
⚠ Key Format: Each key must be on a single line. Don't add line breaks! The entire key from "ssh-ed25519" to the comment is one line.

The authorized_keys File

# Located at ~/.ssh/authorized_keys on the SERVER
[student@server ~]$ cat ~/.ssh/authorized_keys
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI... student@workstation
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAB... student@laptop
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI... admin@management

# Keys can have options prepended
from="192.168.1.*" ssh-ed25519 AAAAC3... restricted-user
command="/usr/bin/backup.sh" ssh-ed25519 AAAAC3... backup-key
no-pty,no-port-forwarding ssh-ed25519 AAAAC3... limited-key
Option Purpose
from="pattern" Only allow connections from matching hosts
command="cmd" Force specific command, ignore client request
no-pty Prevent terminal allocation
no-port-forwarding Disable port forwarding
no-agent-forwarding Disable agent forwarding

SSH Authentication Flow

1
Client connects - TCP connection to server port 22
2
Key exchange - Establish encrypted channel, verify host key
3
Client offers public key - "I want to authenticate with this key"
4
Server checks authorized_keys - Is this key allowed?
5
Server sends challenge - Random data encrypted with public key
6
Client decrypts and responds - Using private key (may need passphrase)
7
Server verifies response - Correct? Grant access!
Key Point: The private key never leaves the client. The server verifies identity through challenge-response, not by receiving the private key.

SSH Agent: Passphrase Caching

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

# Start ssh-agent (usually automatic in desktop environments)
[student@workstation ~]$ eval $(ssh-agent)
Agent pid 12345

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

# List keys in agent
[student@workstation ~]$ ssh-add -l
256 SHA256:yOuRkEyFiNgErPrInT... student@workstation (ED25519)

# Now connections don't prompt for passphrase
[student@workstation ~]$ ssh server.example.com
[student@server ~]$    # Connected without passphrase prompt!

# Remove all keys from agent (security)
[student@workstation ~]$ ssh-add -D

Configuring sshd for Security

# /etc/ssh/sshd_config - Server configuration # Disable root login (recommended) PermitRootLogin no # Disable password authentication (keys only) PasswordAuthentication no # Enable public key authentication (usually default) PubkeyAuthentication yes # Specify allowed users or groups AllowUsers student admin AllowGroups sshusers wheel # Disable empty passwords PermitEmptyPasswords no # Use only SSH protocol 2 Protocol 2
# After editing, validate and restart
[root@server ~]# sshd -t                          # Test config syntax
[root@server ~]# systemctl restart sshd

Disabling Password Authentication

  1. Generate keys on your workstation: ssh-keygen -t ed25519
  2. Deploy public key to server: ssh-copy-id user@server
  3. Test key authentication - Verify you can connect without password
  4. Keep current session open - Your safety net!
  5. Edit sshd_config: Set PasswordAuthentication no
  6. Test and restart: sshd -t && systemctl restart sshd
  7. Test from new terminal - Verify key auth still works
  8. ⚠ CRITICAL: Do NOT close your existing session until you've verified key authentication works after the change. If something goes wrong, you need that session to fix it!

SSH Client Configuration

# ~/.ssh/config - Per-user client configuration
Host webserver
    HostName webserver.example.com
    User admin
    Port 22
    IdentityFile ~/.ssh/work_key

Host database
    HostName 192.168.1.50
    User dbadmin
    IdentityFile ~/.ssh/db_key
    
Host *.internal.example.com
    User developer
    IdentityFile ~/.ssh/internal_key
    StrictHostKeyChecking yes

Host *
    ServerAliveInterval 60
    ServerAliveCountMax 3
# Now connect using the alias
[student@workstation ~]$ ssh webserver       # Expands to full connection
[student@workstation ~]$ ssh database        # Uses the defined settings
Benefit: Define complex connection settings once, then use simple aliases. Different keys for different purposes, different usernames per host.