RED HAT ENTERPRISE LINUX

SSH Security

Key-Based Authentication and Secure Configuration

CIS126RH | RHEL System Administration 1
Mesa Community College

Learning Objectives

1
Understand SSH host key verification

Know how SSH verifies server identity and protects against MITM attacks

2
Generate and deploy SSH key pairs

Create Ed25519/RSA keys and deploy public keys to remote systems

3
Use SSH agent for passphrase caching

Avoid repeated passphrase entry while maintaining security

4
Harden SSH server configuration

Disable password auth, restrict access, configure client shortcuts

Why SSH Security Matters

Threats

  • Brute-force password attacks
  • Man-in-the-middle (MITM) attacks
  • Credential theft
  • Unauthorized access

Protections

  • Host key verification
  • Key-based authentication
  • Disabled password auth
  • Access restrictions
Reality: SSH servers face continuous automated brute-force attacks. Disabling password authentication eliminates this entire attack vector.

SSH Architecture

SSH creates an encrypted tunnel between client and server. Authentication and all data transfer happen inside this encrypted channel.

ComponentLocationPurpose
sshClientClient program — connects to remote servers
sshdServerSSH daemon — listens for connections (port 22)
~/.ssh/ClientClient configuration, keys, known hosts
/etc/ssh/ServerServer configuration and host keys

SSH Key Types

TypeKey FileNotes
Ed25519id_ed25519Recommended — fast, secure, modern
RSAid_rsaLegacy — use 4096-bit minimum
ECDSAid_ecdsaElliptic curve — widely supported
Recommendation: Use Ed25519 for all new keys. It offers excellent security with shorter keys and faster operations. RSA remains compatible with older systems.

Authentication flow: Client presents public key → Server checks authorized_keys → Server sends a challenge → Client signs it with private key → Server verifies signature

Host Keys Explained

Every SSH server has host keys — unique key pairs that identify the server. These prevent man-in-the-middle attacks by verifying you are connecting to the real server.

# Server host keys stored in /etc/ssh/
[root@server ~]# ls /etc/ssh/ssh_host_*
/etc/ssh/ssh_host_ed25519_key      (private)
/etc/ssh/ssh_host_ed25519_key.pub  (public)
/etc/ssh/ssh_host_rsa_key          (private)
/etc/ssh/ssh_host_rsa_key.pub      (public)

# View server's fingerprint
[root@server ~]# ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub
256 SHA256:XYZ123... root@server (ED25519)

First Connection

[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:AbCdEfGhIjKlMnOpQrStUv1234567890.
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' to the list of known hosts.
[user@server ~]$
Security practice: Before typing "yes", verify the fingerprint through a separate channel (console, documentation, phone). Once accepted, future connections are automatic and protected.

The known_hosts File

# 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 for entries 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)
# 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.

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

Host Key Changed Warning

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@    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)!
The fingerprint for the ED25519 key sent by the remote host is
SHA256:NewFingerprint1234567890abcdef.
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 verification failed.
Take seriously: This warning can mean: (a) the server was rebuilt or reinstalled, (b) virtualization changed the host, or (c) a real man-in-the-middle attack. Verify through a separate channel before proceeding.

Resolving Host Key Issues

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

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

# Also remove by IP if you connected by IP
[user@client ~]$ ssh-keygen -R 192.168.1.100
# Step 3: Reconnect and verify new fingerprint
[user@client ~]$ ssh user@server.example.com
The authenticity of host 'server.example.com (192.168.1.100)' cannot be established.
ED25519 key fingerprint is SHA256:NewFingerprint1234567890abcdef.
Are you sure you want to continue connecting (yes/no)? yes

# Or manually edit known_hosts to remove the offending line
[user@client ~]$ vim ~/.ssh/known_hosts

Key-Based Authentication

Key-based authentication replaces passwords with a cryptographic key pair. The private key stays on your client (never shared). The public key is placed on servers you want to access.

Private Key

~/.ssh/id_ed25519

Keep secret. Password-protected. Never leave your client.

Public Key

~/.ssh/id_ed25519.pub

Safe to share. Goes into server's authorized_keys.

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]
Created directory '/home/user/.ssh'.
Enter passphrase (empty for no passphrase): [Enter passphrase]
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
Always use a passphrase! If someone steals your private key file, the passphrase prevents them from using it. Use SSH agent to cache the passphrase so you only type it once per session.

Examining Your Keys

# View your .ssh directory — check permissions!
[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 your private key! The private key (id_ed25519) must be 600 (rw-------). SSH will refuse to use keys with too-permissive permissions.

Deploying Public Keys

# Method 1: ssh-copy-id (recommended)
[user@client ~]$ ssh-copy-id user@server.example.com
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "~/.ssh/id_ed25519.pub"
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s)
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 && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"
Tip: ssh-copy-id automatically sets correct permissions on the server. Always prefer it over manual copying.

Using Key-Based Auth

# Connect — key used automatically, passphrase prompted
[user@client ~]$ ssh user@server.example.com
Enter passphrase for key '/home/user/.ssh/id_ed25519':
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
# Verbose mode to troubleshoot authentication
[user@client ~]$ ssh -v user@server
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).

SSH Agent

ssh-agent caches your decrypted private key in memory. You type the passphrase once; subsequent connections use the cached key automatically.

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

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

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

# Remove all keys from agent
[user@client ~]$ ssh-add -D

The authorized_keys File

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

# Add restrictions to limit a key's use
from="192.168.1.*",no-port-forwarding ssh-ed25519 AAAAC3... backup@client
# Common restrictions:
# from="pattern"      — Only allow from specific IPs/hosts
# command="cmd"       — Only run this one command when used
# no-port-forwarding  — Disable port forwarding
# no-X11-forwarding   — Disable X11 forwarding
# no-pty              — Disable terminal allocation
Format: Each line is one authorized public key. Prepend optional restrictions followed by a space before the key type.

SSH Server Configuration

[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
# Restrict who can SSH in
AllowUsers alice bob             # Only these users can SSH
AllowGroups sshusers             # Or only this group

# Other hardening
X11Forwarding no                 # Disable X11 forwarding
MaxAuthTries 3                   # Limit auth attempts
ClientAliveInterval 300          # Timeout idle connections (seconds)
ClientAliveCountMax 2            # Disconnect after 2 missed keepalives

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

Disabling Password Auth

# Step 1: Verify key-based auth works FIRST
[user@client ~]$ ssh -o PasswordAuthentication=no user@server
# If this succeeds, you are 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 a NEW terminal — do not close current one yet
[user@client ~]$ ssh user@server
If locked out with console access:
vim /etc/ssh/sshd_config → set PasswordAuthentication yessystemctl restart sshd

SSH Client Config

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

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

# Named shortcut for production server
Host prod
    HostName production.example.com
    User admin
    IdentityFile ~/.ssh/prod_key
    Port 2222
# Jump through a bastion host
Host internal
    HostName 10.0.0.50
    User developer
    ProxyJump bastion.example.com

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

Best Practices

Do

  • Use Ed25519 keys
  • Always use a passphrase
  • Verify host fingerprints
  • Use ssh-agent for convenience
  • Disable password auth on servers
  • Disable root login
  • Use AllowUsers/AllowGroups

Avoid

  • Keys without passphrases
  • Ignoring MITM warnings
  • Sharing private keys
  • Disabling password auth without testing keys first
  • Using RSA without 4096-bit minimum
  • Allowing direct root login

Key Takeaways

1

SSH host keys verify server identity. The first connection fingerprint must be verified out-of-band. Stored in ~/.ssh/known_hosts.

2

Generate keys with ssh-keygen -t ed25519. Deploy with ssh-copy-id. Private key stays local; public key goes to server's authorized_keys.

3

Use ssh-agent + ssh-add to cache passphrases. Type once per session, connect without prompts.

4

Harden servers: PermitRootLogin no, PasswordAuthentication no. Always test key auth before disabling passwords.

Graded Lab

  • Generate an Ed25519 key pair with a passphrase
  • Deploy your public key to a remote host with ssh-copy-id
  • Use ssh-agent to cache your passphrase
  • 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