Network SecurityBeginner

Secure Shell SSH 101

Master the fundamentals of SSH (Secure Shell) protocol, from basic connections to advanced security configurations, key management, and tunneling techniques.

By James Mitchell
11/14/2025
28 min read
#SSH#Network Security#Remote Access#Linux Administration#Security Protocols#Key Management

Introduction to SSH

Secure Shell (SSH) is one of the most fundamental protocols in modern cybersecurity and system administration. Whether you're a developer connecting to remote servers, a system administrator managing infrastructure, or a security professional conducting assessments, SSH is an essential tool in your arsenal.

This comprehensive tutorial will take you from SSH basics to advanced configurations, covering everything you need to know to use SSH securely and effectively in professional environments.

What is SSH?

SSH (Secure Shell) is a cryptographic network protocol that provides secure communication over an unsecured network. It was designed to replace insecure protocols like Telnet, rlogin, and rsh, which transmitted data in plaintext.

  • Encryption: All data is encrypted during transmission
  • Authentication: Verifies the identity of users and servers
  • Integrity: Ensures data hasn't been tampered with
  • Versatility: Supports command execution, file transfer, and tunneling

SSH History and Evolution

SSH was originally developed by Tatu Ylönen in 1995 as a response to a password-sniffing attack at his university. The protocol has evolved significantly:

SSH Protocol Versions:

  • SSH-1: Original protocol (deprecated due to vulnerabilities)
  • SSH-2: Current standard, incompatible with SSH-1
  • OpenSSH: Most popular implementation, developed by OpenBSD team

Why SSH Matters for Security

In today's interconnected world, SSH serves as the backbone of secure remote administration:

  • Remote Server Management: Securely manage servers across the globe
  • Secure File Transfer: Transfer files safely using SCP and SFTP
  • Network Tunneling: Create secure channels through untrusted networks
  • Git Operations: Securely interact with code repositories
  • Database Access: Secure connections to remote databases

SSH Protocol Fundamentals

Protocol Architecture

SSH operates as a layered protocol, similar to the OSI model:

SSH Protocol Layers:

┌─────────────────────────────┐
│    SSH Connection Layer     │  ← Channels, port forwarding
├─────────────────────────────┤
│   SSH Authentication Layer │  ← User authentication
├─────────────────────────────┤
│    SSH Transport Layer      │  ← Encryption, key exchange
├─────────────────────────────┤
│         TCP Layer           │  ← Reliable transport
└─────────────────────────────┘

Encryption Methods

SSH uses multiple encryption techniques to ensure security:

Symmetric Encryption

Used for data encryption after key exchange. Common algorithms: AES, ChaCha20

Asymmetric Encryption

Used for key exchange and authentication. Common algorithms: RSA, ECDSA, Ed25519

Authentication Types

SSH Authentication Methods:

1. Password Authentication
   └── Username + password (least secure)

2. Public Key Authentication  
   └── Private/public key pairs (most common)

3. Host-based Authentication
   └── Based on host identity

4. Keyboard-interactive
   └── Multi-factor authentication support

5. GSSAPI/Kerberos
   └── Enterprise authentication integration

Basic SSH Usage

Making Your First SSH Connection

The basic SSH connection syntax is straightforward:

# Basic connection syntax
ssh username@hostname

# Examples
ssh john@192.168.1.100
ssh admin@example.com
ssh root@server.company.com

# Specify custom port
ssh -p 2222 user@hostname

# Connect with specific key
ssh -i ~/.ssh/my_key user@hostname

# Enable verbose output for troubleshooting
ssh -v user@hostname

First Connection: When connecting to a host for the first time, SSH will display the server's fingerprint and ask you to verify it. This prevents man-in-the-middle attacks.

SSH Client Options

SSH clients offer numerous options to customize your connection:

# Common SSH client options
ssh -o "StrictHostKeyChecking=no" user@host    # Skip host key verification (risky)
ssh -o "UserKnownHostsFile=/dev/null" user@host # Don't save host keys
ssh -4 user@host                               # Force IPv4
ssh -6 user@host                               # Force IPv6
ssh -C user@host                               # Enable compression
ssh -X user@host                               # Enable X11 forwarding
ssh -Y user@host                               # Enable trusted X11 forwarding

# Connection timeout and keep-alive
ssh -o "ConnectTimeout=10" user@host
ssh -o "ServerAliveInterval=60" user@host
ssh -o "ServerAliveCountMax=3" user@host

Essential SSH Commands

# Execute single command remotely
ssh user@host "ls -la /var/log"
ssh user@host "uptime && df -h"

# Copy files with SCP
scp file.txt user@host:/remote/path/
scp user@host:/remote/file.txt /local/path/
scp -r directory/ user@host:/remote/path/

# SFTP for interactive file transfer
sftp user@host
> put local_file.txt
> get remote_file.txt
> ls
> exit

# Secure file synchronization with rsync over SSH
rsync -avz -e ssh /local/dir/ user@host:/remote/dir/

SSH Key Management

Generating SSH Keys

SSH keys provide a more secure authentication method than passwords:

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

# Generate Ed25519 key (modern, recommended)
ssh-keygen -t ed25519 -C "your_email@example.com"

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

# Generate key with custom filename and passphrase
ssh-keygen -t ed25519 -f ~/.ssh/production_key -C "production-server-key"

# Generate key without passphrase (automated systems)
ssh-keygen -t ed25519 -N "" -f ~/.ssh/automation_key

Understanding Key Types

AlgorithmKey SizeSecurityPerformanceRecommendation
RSA2048-4096 bitsGood (with 4096 bits)ModerateLegacy compatibility
Ed25519256 bitsExcellentFastPreferred choice
ECDSA256-521 bitsGoodFastAlternative to Ed25519

Key Deployment and Management

# Copy public key to server (automated)
ssh-copy-id user@hostname
ssh-copy-id -i ~/.ssh/specific_key.pub user@hostname

# Manual key deployment
cat ~/.ssh/id_ed25519.pub | ssh user@host "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"

# Set correct permissions (crucial for security)
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
chmod 600 ~/.ssh/id_*
chmod 644 ~/.ssh/id_*.pub

# List loaded keys in SSH agent
ssh-add -l

# Add key to SSH agent
ssh-add ~/.ssh/id_ed25519
ssh-add -t 3600 ~/.ssh/id_ed25519  # Expire after 1 hour

# Remove all keys from agent
ssh-add -D

SSH Configuration

Client Configuration

The SSH client configuration file (~/.ssh/config) allows you to define connection shortcuts:

# ~/.ssh/config example

# Production server
Host prod
    HostName production.example.com
    User admin
    Port 2222
    IdentityFile ~/.ssh/production_key
    IdentitiesOnly yes
    ServerAliveInterval 60

# Development server with jump host
Host dev
    HostName 10.0.1.100
    User developer
    ProxyJump bastion.example.com
    IdentityFile ~/.ssh/dev_key

# Bastion/Jump host
Host bastion
    HostName bastion.example.com
    User jump_user
    Port 22
    IdentityFile ~/.ssh/bastion_key

# Wild card for internal network
Host 10.0.*
    User admin
    IdentityFile ~/.ssh/internal_key
    StrictHostKeyChecking no
    UserKnownHostsFile /dev/null

# GitHub (common configuration)
Host github.com
    HostName github.com
    User git
    IdentityFile ~/.ssh/github_key
    IdentitiesOnly yes

Server Configuration

The SSH daemon configuration (/etc/ssh/sshd_config) controls server behavior:

# /etc/ssh/sshd_config - Security-focused configuration

# Basic settings
Port 22                              # Change from default for security
Protocol 2                           # Use SSH protocol version 2 only
HostKey /etc/ssh/ssh_host_ed25519_key # Prefer Ed25519 keys
HostKey /etc/ssh/ssh_host_rsa_key     # Keep RSA for compatibility

# Authentication
PubkeyAuthentication yes             # Enable public key auth
PasswordAuthentication no            # Disable password auth
PermitEmptyPasswords no             # Never allow empty passwords
ChallengeResponseAuthentication no   # Disable challenge-response auth
UsePAM yes                          # Use PAM for account management

# Access control
PermitRootLogin no                  # Disable root login
AllowUsers admin developer          # Whitelist specific users
DenyUsers guest anonymous           # Blacklist specific users
AllowGroups ssh-users               # Restrict to specific groups

# Session settings
ClientAliveInterval 300             # Send keepalive every 5 minutes
ClientAliveCountMax 2               # Disconnect after 2 failed keepalives
MaxAuthTries 3                      # Maximum authentication attempts
MaxSessions 10                      # Maximum concurrent sessions
MaxStartups 10:30:60               # Connection rate limiting

# Security features
X11Forwarding no                    # Disable X11 forwarding
AllowTcpForwarding yes             # Allow port forwarding
GatewayPorts no                    # Don't bind to external interfaces
PermitTunnel no                    # Disable tun device forwarding

Security Hardening

Critical Security Measures

  • • Always change the default SSH port (22) on public-facing servers
  • • Disable password authentication and use keys only
  • • Never permit root login over SSH
  • • Implement fail2ban or similar intrusion prevention
  • • Use strong ciphers and disable weak algorithms

Advanced SSH Features

Port Forwarding and Tunneling

SSH tunneling allows you to securely forward network traffic through encrypted channels:

# Local port forwarding (access remote service locally)
ssh -L 8080:localhost:80 user@remote-server
# Access remote server's web service at http://localhost:8080

# Remote port forwarding (expose local service remotely)
ssh -R 9000:localhost:3000 user@remote-server
# Remote server can access your local service on port 9000

# Dynamic port forwarding (SOCKS proxy)
ssh -D 1080 user@remote-server
# Use localhost:1080 as SOCKS proxy in your browser

# Practical examples
# Access remote database
ssh -L 5432:db.internal:5432 user@jump-server

# Access internal web application
ssh -L 8080:internal-app:80 user@gateway

# Create reverse tunnel for remote access
ssh -R 22000:localhost:22 user@public-server

# Background tunnel (no interactive session)
ssh -fN -L 8080:localhost:80 user@remote-server

SSH Agent and Key Forwarding

# Start SSH agent
eval $(ssh-agent)

# Add keys to agent
ssh-add ~/.ssh/id_ed25519
ssh-add -t 7200 ~/.ssh/production_key  # Expire after 2 hours

# Agent forwarding (use local keys on remote servers)
ssh -A user@remote-server
# Now you can git clone, SSH to other servers, etc. using your local keys

# In ~/.ssh/config
Host production
    HostName prod.example.com
    User admin
    ForwardAgent yes

# Caution: Only use agent forwarding on trusted servers
# Alternative: Use ProxyJump instead of agent forwarding

Jump Hosts and ProxyCommand

# Modern ProxyJump (SSH 7.3+)
ssh -J user1@jump-host user2@target-server

# Multiple hops
ssh -J user1@hop1,user2@hop2 user3@target

# Configuration file approach
Host target
    HostName 10.0.1.100
    User admin
    ProxyJump jump-host

Host jump-host
    HostName jump.example.com
    User jump_user

# Legacy ProxyCommand approach
Host target-legacy
    HostName 10.0.1.100
    User admin
    ProxyCommand ssh -W %h:%p jump-host

# Complex example: Database access through jump host
Host db-server
    HostName database.internal
    User dbadmin
    ProxyJump bastion.company.com
    LocalForward 5432 localhost:5432

SSH Troubleshooting

Common Connection Issues

Permission Denied (publickey)

Common causes and solutions:

  • Wrong key path: Verify with -i flag or SSH config
  • Key not in SSH agent: Run ssh-add
  • Wrong permissions: chmod 600 ~/.ssh/id_* and chmod 700 ~/.ssh
  • Key not on server: Check ~/.ssh/authorized_keys

Connection Timeout or Refused

Network and service issues:

  • Wrong port: Check if SSH runs on non-standard port
  • Firewall blocking: Verify network connectivity
  • SSH daemon not running: Check service status
  • Wrong hostname/IP: Verify target address

Debugging Techniques

# Verbose SSH client output (levels 1-3)
ssh -v user@host                    # Basic debugging
ssh -vv user@host                   # More detailed
ssh -vvv user@host                  # Maximum verbosity

# Check SSH server logs
sudo journalctl -u ssh              # systemd systems
sudo tail -f /var/log/auth.log      # Debian/Ubuntu
sudo tail -f /var/log/secure        # RHEL/CentOS

# Test specific authentication methods
ssh -o PreferredAuthentications=publickey user@host
ssh -o PreferredAuthentications=password user@host

# Check SSH service status
sudo systemctl status ssh           # systemd
sudo service ssh status             # SysV

# Verify SSH daemon configuration
sudo sshd -t                        # Test config syntax
sudo sshd -T                        # Show effective configuration

# Network connectivity tests
telnet hostname 22                  # Test port connectivity
nmap -p 22 hostname                 # Check if port is open
nc -zv hostname 22                  # Netcat connection test

Security Best Practices

SSH Hardening Checklist

Server Configuration

Key Management

Monitoring and Logging

# Enhanced SSH logging configuration
# Add to /etc/ssh/sshd_config
LogLevel VERBOSE                    # Detailed logging
SyslogFacility AUTH                # Use auth facility

# Monitor SSH connections in real-time
sudo tail -f /var/log/auth.log | grep sshd

# Find failed SSH login attempts
grep "Failed password" /var/log/auth.log

# Find successful logins
grep "Accepted" /var/log/auth.log

# Count failed attempts by IP
grep "Failed password" /var/log/auth.log | awk '{print $11}' | sort | uniq -c | sort -nr

# Install and configure fail2ban
sudo apt install fail2ban
sudo systemctl enable fail2ban

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

Real-World Scenarios

Scenario 1: Accessing Internal Services

You need to access a database that's only available on the internal network.

ssh -L 5432:db.internal:5432 user@gateway
psql -h localhost -p 5432 dbname

Scenario 2: Secure File Transfer

Transfer large files securely to a remote server with compression.

rsync -avz -e "ssh -C" /local/data/ user@server:/remote/backup/

Scenario 3: Multi-Hop Connection

Access a server through multiple jump hosts in a secure environment.

ssh -J bastion,internal-gw target-server

Scenario 4: Emergency Access

Provide temporary access to a colleague for troubleshooting.

ssh-add -t 3600 ~/.ssh/emergency_key
ssh -o "UserKnownHostsFile=/tmp/known_hosts" user@server

Conclusion

SSH is much more than just a remote login tool—it's a comprehensive security protocol that forms the backbone of modern secure system administration. From basic connections to complex tunneling scenarios, mastering SSH is essential for anyone working in cybersecurity, DevOps, or system administration.

The key to SSH mastery lies in understanding both its powerful features and its security implications. Always prioritize security hardening, use strong key-based authentication, and follow the principle of least privilege when configuring access.

Next Steps: Practice these techniques in a lab environment, gradually implementing security hardening measures in your production systems. Remember that SSH security is an ongoing process, not a one-time setup.