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)
Component
Location
Purpose
ssh
Client
Connect to remote servers
sshd
Server
Accept incoming connections
Host keys
Server (/etc/ssh/)
Prove server identity
User keys
Client (~/.ssh/)
Prove user identity
known_hosts
Client (~/.ssh/)
Remember trusted servers
authorized_keys
Server (~/.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 keyfrom="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 hostsHost *
ServerAliveInterval 60
ServerAliveCountMax 3# Shortcut for production serverHost prod
HostName production.example.com
User admin
IdentityFile ~/.ssh/prod_key
Port 2222# Jump through bastion hostHost 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.