Pick a color scheme
ad placeholder image ad placeholder image

SSH: Secure Shell Protocol Complete Guide

SSH (Secure Shell) is a cryptographic network protocol for secure remote access, file transfer, and network services over unsecured networks. SSH has become the standard for secure remote administration, replacing insecure protocols like Telnet and rlogin. This comprehensive guide explains SSH, its features, configuration, and best practices.

What is SSH?

SSH is a protocol that provides secure encrypted communication between two computers over an insecure network. It uses strong cryptography to authenticate users and encrypt all traffic, including passwords, commands, and data.

SSH Basics

Protocol characteristics:

Layer: Application layer (Layer 7)
Transport: TCP
Port: 22 (default)
Encryption: Strong cryptography
Authentication: Multiple methods
Purpose: Remote access, file transfer, tunneling

SSH replaces:

Telnet: Unencrypted remote access
rlogin: Unencrypted remote login
rsh: Unencrypted remote shell
FTP: Unencrypted file transfer

Learn more about FTP and SSL/TLS.

SSH versions:

SSH-1: Original, deprecated (insecure)
SSH-2: Current standard, secure
Status: Only use SSH-2

How SSH Works

SSH Connection Process

Connection establishment:

1. Client connects to server (port 22)
2. Server sends public key
3. Client verifies server identity
4. Negotiate encryption algorithms
5. Establish encrypted connection
6. User authentication
7. Secure session established

Encryption layers:

Transport Layer:
- Server authentication
- Encryption
- Integrity

User Authentication Layer:
- Password
- Public key
- Keyboard-interactive

Connection Layer:
- Multiplexing
- Channel management

SSH Authentication Methods

Password authentication:

Process:
1. User enters password
2. Password sent encrypted
3. Server verifies password
4. Access granted or denied

Security: Weakest method
Risk: Brute force attacks
Recommendation: Disable for production

Public key authentication:

Process:
1. User has key pair (public/private)
2. Public key on server
3. Server sends challenge
4. Client signs with private key
5. Server verifies with public key
6. Access granted

Security: Strong
Advantages: No password transmission
Recommendation: Preferred method

Keyboard-interactive:

Process:
1. Server sends prompts
2. User responds
3. Can include multiple factors
4. Flexible authentication

Use cases:
- Two-factor authentication
- One-time passwords
- Custom challenges

Host-based authentication:

Process:
1. Client host authenticated
2. Based on host keys
3. User trusted from that host

Use: Automated systems
Security: Less common

SSH Key Management

Generating SSH Keys

RSA keys (traditional):

# Generate RSA key (2048-bit minimum, 4096-bit recommended)
ssh-keygen -t rsa -b 4096 -C "your_email@example.com"

# Output:
Generating public/private rsa key pair.
Enter file in which to save the key (/home/user/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Your identification has been saved in /home/user/.ssh/id_rsa
Your public key has been saved in /home/user/.ssh/id_rsa.pub

Ed25519 keys (modern, recommended):

# Generate Ed25519 key (faster, more secure)
ssh-keygen -t ed25519 -C "your_email@example.com"

# Advantages:
- Smaller key size
- Faster
- More secure
- Modern standard

ECDSA keys:

# Generate ECDSA key
ssh-keygen -t ecdsa -b 521 -C "your_email@example.com"

# Note: Ed25519 preferred over ECDSA

Key files:

Private key: ~/.ssh/id_ed25519 (keep secret!)
Public key: ~/.ssh/id_ed25519.pub (share this)
Permissions: 600 for private, 644 for public

Deploying Public Keys

Copy to server:

# Easiest method
ssh-copy-id user@server.com

# Manual method
cat ~/.ssh/id_ed25519.pub | ssh user@server.com "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"

# Or copy-paste
cat ~/.ssh/id_ed25519.pub
# Copy output, then on server:
echo "paste-public-key-here" >> ~/.ssh/authorized_keys

Authorized keys file:

Location: ~/.ssh/authorized_keys
Permissions: 600
Format: One public key per line

Multiple keys:

# authorized_keys can contain multiple keys
ssh-rsa AAAAB3... user1@host1
ssh-ed25519 AAAAC3... user2@host2
ssh-rsa AAAAB3... user3@host3

Key Passphrases

Purpose:

Protect private key
Additional security layer
Required if key stolen

Using ssh-agent:

# Start ssh-agent
eval "$(ssh-agent -s)"

# Add key (enter passphrase once)
ssh-add ~/.ssh/id_ed25519

# List loaded keys
ssh-add -l

# Remove all keys
ssh-add -D

Keychain (persistent):

# Install keychain
sudo apt install keychain

# Add to ~/.bashrc
eval $(keychain --eval id_ed25519)

# Keys loaded on login

SSH Client Usage

Basic Connection

Connect to server:

# Basic connection
ssh user@server.com

# Specify port
ssh -p 2222 user@server.com

# Specify key
ssh -i ~/.ssh/custom_key user@server.com

# Verbose output (debugging)
ssh -v user@server.com
ssh -vv user@server.com  # More verbose
ssh -vvv user@server.com # Maximum verbosity

First connection:

The authenticity of host 'server.com (203.0.113.1)' can't be established.
ED25519 key fingerprint is SHA256:abc123...
Are you sure you want to continue connecting (yes/no)?

Type: yes
Result: Host added to ~/.ssh/known_hosts

SSH Config File

Location: ~/.ssh/config

Basic configuration:

Host myserver
    HostName server.example.com
    User alice
    Port 22
    IdentityFile ~/.ssh/id_ed25519

Host github
    HostName github.com
    User git
    IdentityFile ~/.ssh/github_key

Host *
    ServerAliveInterval 60
    ServerAliveCountMax 3

Usage:

# Instead of: ssh alice@server.example.com
ssh myserver

# Instead of: ssh git@github.com
ssh github

Advanced options:

Host production
    HostName prod.example.com
    User admin
    Port 2222
    IdentityFile ~/.ssh/prod_key
    ForwardAgent yes
    Compression yes
    LogLevel INFO

Host *.internal
    ProxyJump bastion.example.com
    User internal_user

Remote Command Execution

Run single command:

# Execute command and exit
ssh user@server.com "ls -la"

# Multiple commands
ssh user@server.com "cd /var/log && tail -n 20 syslog"

# With sudo
ssh user@server.com "sudo systemctl restart nginx"

Script execution:

# Run local script on remote server
ssh user@server.com 'bash -s' < local_script.sh

# With arguments
ssh user@server.com 'bash -s' < script.sh arg1 arg2

Here document:

ssh user@server.com << 'EOF'
cd /var/www
git pull
npm install
pm2 restart app
EOF

SSH File Transfer

SCP (Secure Copy)

Upload file:

# Single file
scp file.txt user@server.com:/path/to/destination/

# Multiple files
scp file1.txt file2.txt user@server.com:/path/

# Directory (recursive)
scp -r directory/ user@server.com:/path/

Download file:

# Single file
scp user@server.com:/path/to/file.txt .

# Multiple files
scp user@server.com:/path/to/*.txt .

# Directory
scp -r user@server.com:/path/to/directory/ .

Options:

# Preserve timestamps and permissions
scp -p file.txt user@server.com:/path/

# Limit bandwidth (KB/s)
scp -l 1000 file.txt user@server.com:/path/

# Specify port
scp -P 2222 file.txt user@server.com:/path/

# Compression
scp -C largefile.tar user@server.com:/path/

SFTP (SSH File Transfer Protocol)

Interactive session:

# Connect
sftp user@server.com

# Commands
sftp> ls                    # List remote files
sftp> lls                   # List local files
sftp> pwd                   # Remote directory
sftp> lpwd                  # Local directory
sftp> cd /path              # Change remote directory
sftp> lcd /path             # Change local directory
sftp> get file.txt          # Download file
sftp> put file.txt          # Upload file
sftp> get -r directory/     # Download directory
sftp> put -r directory/     # Upload directory
sftp> mkdir newdir          # Create remote directory
sftp> rm file.txt           # Delete remote file
sftp> exit                  # Quit

Batch mode:

# Execute commands from file
sftp -b commands.txt user@server.com

# commands.txt:
cd /var/www
put index.html
put style.css
quit

rsync over SSH

Sync directories:

# Basic sync
rsync -avz /local/dir/ user@server.com:/remote/dir/

# Options:
-a: Archive mode (preserves permissions, timestamps)
-v: Verbose
-z: Compression
-P: Progress and partial transfers
--delete: Delete files not in source

# Exclude files
rsync -avz --exclude '*.log' /local/ user@server.com:/remote/

# Dry run (test)
rsync -avz --dry-run /local/ user@server.com:/remote/

Advantages over scp:

Only transfers changes
Resume capability
Compression
Exclude patterns
Preserves permissions
Faster for updates

SSH Tunneling and Port Forwarding

Local Port Forwarding

Forward local port to remote:

# Syntax
ssh -L local_port:destination:destination_port user@ssh_server

# Example: Access remote database
ssh -L 3306:localhost:3306 user@database-server.com

# Now connect to localhost:3306 → remote MySQL

# Access service on different host
ssh -L 8080:internal-server:80 user@bastion.com
# localhost:8080 → internal-server:80 via bastion

Use cases:

Access remote database
Bypass firewall
Secure unencrypted protocols
Access internal services

Remote Port Forwarding

Forward remote port to local:

# Syntax
ssh -R remote_port:destination:destination_port user@ssh_server

# Example: Share local web server
ssh -R 8080:localhost:80 user@public-server.com

# public-server.com:8080 → your localhost:80

# Expose local service
ssh -R 3000:localhost:3000 user@server.com

Use cases:

Expose local development server
Share local service temporarily
Bypass NAT/firewall
Remote access to local machine

Dynamic Port Forwarding (SOCKS Proxy)

Create SOCKS proxy:

# Start SOCKS proxy on local port
ssh -D 1080 user@server.com

# Configure browser/application to use:
SOCKS5 proxy: localhost:1080

# All traffic routed through SSH tunnel

Use cases:

Secure browsing on public WiFi
Bypass geographic restrictions
Encrypt all traffic
Access region-locked content

Browser configuration:

Firefox:
Settings → Network Settings → Manual proxy
SOCKS Host: localhost
Port: 1080
SOCKS v5: Yes

SSH Jump Host (ProxyJump)

Access through bastion:

# Old method
ssh -J bastion.com user@internal-server

# Or
ssh -o ProxyJump=bastion.com user@internal-server

# Multiple jumps
ssh -J bastion1.com,bastion2.com user@internal-server

Config file:

Host internal
    HostName internal-server.local
    User admin
    ProxyJump bastion.example.com

SSH Server Configuration

Installation

Debian/Ubuntu:

sudo apt update
sudo apt install openssh-server

RHEL/CentOS:

sudo yum install openssh-server

Start service:

sudo systemctl start sshd
sudo systemctl enable sshd

Configuration File

Location: /etc/ssh/sshd_config

Basic hardening:

# Port (change from default)
Port 2222

# Protocol
Protocol 2

# Authentication
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
PermitEmptyPasswords no

# Security
X11Forwarding no
MaxAuthTries 3
MaxSessions 10
LoginGraceTime 60

# Logging
SyslogFacility AUTH
LogLevel VERBOSE

# Allow specific users
AllowUsers alice bob
# Or allow specific groups
AllowGroups sshusers

Apply changes:

# Test configuration
sudo sshd -t

# Restart service
sudo systemctl restart sshd

Security Best Practices

1. Disable password authentication:

PasswordAuthentication no
ChallengeResponseAuthentication no

2. Disable root login:

PermitRootLogin no

3. Change default port:

Port 2222
# Security through obscurity (minor benefit)
# Reduces automated attacks

4. Limit users:

AllowUsers alice bob
# Or
AllowGroups sshusers

5. Use fail2ban:

# Install
sudo apt install fail2ban

# Configure /etc/fail2ban/jail.local
[sshd]
enabled = true
port = 22
filter = sshd
logpath = /var/log/auth.log
maxretry = 3
bantime = 3600

6. Two-factor authentication:

# Install Google Authenticator
sudo apt install libpam-google-authenticator

# Configure PAM
# /etc/pam.d/sshd
auth required pam_google_authenticator.so

# /etc/ssh/sshd_config
ChallengeResponseAuthentication yes
AuthenticationMethods publickey,keyboard-interactive

7. Keep updated:

sudo apt update
sudo apt upgrade openssh-server

Advanced SSH Features

SSH Agent Forwarding

Purpose:

Use local SSH keys on remote servers
Access further servers without copying keys
Convenient for jump hosts

Enable:

# Command line
ssh -A user@server.com

# Config file
Host server
    ForwardAgent yes

Security warning:

Risk: Admin on intermediate server can use your keys
Use: Only on trusted servers
Alternative: ProxyJump (more secure)

SSH Multiplexing

Purpose:

Reuse existing connection
Faster subsequent connections
Reduce overhead

Configuration:

Host *
    ControlMaster auto
    ControlPath ~/.ssh/sockets/%r@%h:%p
    ControlPersist 10m

Create socket directory:

mkdir -p ~/.ssh/sockets

Benefits:

First connection: Normal
Subsequent: Instant (reuses connection)
Persist: Stays open for 10 minutes

SSH Escape Sequences

During session:

~.  : Disconnect
~^Z : Background SSH
~#  : List forwarded connections
~&  : Background SSH at logout
~?  : Help

Usage:

Press Enter, then ~.
Immediately disconnects
Useful for hung connections

Troubleshooting SSH

Connection Issues

Connection refused:

Check: SSH service running
Check: Firewall rules
Check: Correct port
Test: telnet server.com 22

Connection timeout:

Check: Network connectivity
Check: Firewall blocking
Check: Server reachable
Test: ping server.com

Permission denied:

Check: Username correct
Check: Key permissions (600 for private)
Check: authorized_keys permissions (600)
Check: Home directory permissions (755)
Verbose: ssh -vvv user@server.com

Authentication Issues

Public key not working:

Check: Public key in authorized_keys
Check: File permissions
Check: SELinux (if enabled)
Check: sshd_config allows PubkeyAuthentication
Debug: ssh -vvv user@server.com

Permissions:

# Fix permissions
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
chmod 600 ~/.ssh/id_ed25519
chmod 644 ~/.ssh/id_ed25519.pub

Host key verification failed:

Warning: REMOTE HOST IDENTIFICATION HAS CHANGED!

Causes:
- Server reinstalled
- Man-in-the-middle attack
- IP address reused

Fix (if legitimate):
ssh-keygen -R server.com
# Or edit ~/.ssh/known_hosts

Performance Issues

Slow connection:

Cause: DNS lookup
Fix: UseDNS no in sshd_config

Cause: GSSAPI authentication
Fix: GSSAPIAuthentication no

Cause: Network latency
Test: ssh -v to see delays

Slow file transfer:

Enable compression: scp -C
Use rsync: More efficient
Check network: Bandwidth limits

SSH Best Practices

Client-Side

1. Use SSH keys:

Generate strong keys (Ed25519 or RSA 4096)
Use passphrases
Use ssh-agent

2. Configure SSH config:

Organize connections
Set defaults
Use aliases

3. Verify host keys:

Check fingerprints on first connection
Don't blindly accept
Compare with known good value

4. Use ProxyJump:

Safer than agent forwarding
Access internal servers
Cleaner than manual tunneling

Server-Side

1. Harden configuration:

Disable password authentication
Disable root login
Change default port (optional)
Limit users

2. Monitor logs:

Watch for failed attempts
Detect brute force
Investigate anomalies

3. Use fail2ban:

Automatic IP blocking
Reduce brute force attempts
Configurable thresholds

4. Keep updated:

Regular security updates
Monitor CVEs
Test updates in staging

5. Regular audits:

Review authorized_keys
Check user accounts
Verify permissions
Review logs

Conclusion

SSH is the standard for secure remote access and file transfer, providing strong encryption, flexible authentication, and powerful features like tunneling and port forwarding. Proper SSH configuration with key-based authentication, disabled password login, and security hardening is essential for secure server management.


Related Articles

Secure Protocols

Network Concepts

Security

Explore More

Key takeaways: - SSH provides encrypted remote access - Port 22 (default), customizable - Key-based authentication preferred - Disable password authentication - Use Ed25519 or RSA 4096 keys - SSH config simplifies connections - SCP/SFTP for secure file transfer - Port forwarding for tunneling - Harden server configuration - Monitor and update regularly

SSH is indispensable for secure server administration. Always use key-based authentication, disable password login on production servers, keep SSH updated, and follow security best practices. Proper SSH configuration protects against unauthorized access while providing convenient and secure remote management capabilities.

ad placeholder image ad placeholder image
Three funny piglies - an illustration ippigly.com