Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

SSH: Secure Shell

SSH (Secure Shell) provides encrypted remote access, replacing insecure protocols like Telnet and rlogin. Beyond shell access, SSH enables secure file transfer, port forwarding, and tunneling.

SSH Capabilities

┌─────────────────────────────────────────────────────────────────────┐
│                      SSH Use Cases                                  │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│  Remote Shell:     Interactive command line on remote server        │
│  File Transfer:    SFTP, SCP over encrypted channel                 │
│  Port Forwarding:  Tunnel any TCP connection through SSH            │
│  X11 Forwarding:   Run graphical apps remotely                      │
│  Agent Forwarding: Use local keys on remote servers                 │
│  Git Transport:    Secure repository access                         │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘

Authentication Methods

Password Authentication

$ ssh user@server.example.com
user@server.example.com's password: ********

Simple but:
  - Vulnerable to brute force
  - Requires typing password
  - Can't be automated safely

Public Key Authentication

# Generate key pair
$ ssh-keygen -t ed25519 -C "alice@laptop"
# Creates: ~/.ssh/id_ed25519 (private)
#          ~/.ssh/id_ed25519.pub (public)

# Copy public key to server
$ ssh-copy-id user@server.example.com
# Or manually add to ~/.ssh/authorized_keys

# Login (no password!)
$ ssh user@server.example.com

Key Types

Ed25519:     Modern, fast, secure (recommended)
RSA:         Widely compatible (4096-bit minimum)
ECDSA:       Elliptic curve (P-256, P-384)

Avoid:
  DSA:       Deprecated, weak
  RSA <2048: Too short

SSH Configuration

Client Config (~/.ssh/config)

# Default settings
Host *
    AddKeysToAgent yes
    IdentityFile ~/.ssh/id_ed25519

# Named host
Host myserver
    HostName server.example.com
    User alice
    Port 22
    IdentityFile ~/.ssh/work_key

# Now just:
$ ssh myserver

Server Config (/etc/ssh/sshd_config)

# Secure settings
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
AllowUsers alice bob
Protocol 2

Port Forwarding

Local Forwarding (-L)

Access remote service through local port:

$ ssh -L 8080:localhost:80 user@server

  Local:8080  ──────SSH Tunnel──────>  Server ────> localhost:80
     │                                      (server's port 80)
     └── Your browser connects here

Use case: Access web app behind firewall

Remote Forwarding (-R)

Expose local service to remote:

$ ssh -R 9000:localhost:3000 user@server

  Server:9000  <─────SSH Tunnel───────  Local:3000
     │                                      │
     └── Internet can access          Your dev server

Use case: Share local development server

Dynamic Forwarding (-D)

SOCKS proxy through SSH:

$ ssh -D 1080 user@server

Configure browser to use SOCKS proxy localhost:1080
All browser traffic goes through server.

Use case: Bypass network restrictions, privacy

SSH Tunnels for Security

┌─────────────────────────────────────────────────────────────────────┐
│                    SSH Tunnel Example                               │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│  Scenario: Connect to database behind firewall                      │
│                                                                     │
│  ┌────────┐        ┌────────────┐        ┌──────────┐              │
│  │ Laptop │──SSH──>│ Jump Host  │        │ Database │              │
│  │        │        │ (bastion)  │──────>│ :5432    │              │
│  └────────┘        └────────────┘        └──────────┘              │
│                                                                     │
│  $ ssh -L 5432:db.internal:5432 user@bastion                        │
│  $ psql -h localhost -p 5432 mydb                                   │
│                                                                     │
│  Database connection encrypted through SSH tunnel.                  │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘

Best Practices

Key Management:
  ✓ Use Ed25519 keys
  ✓ Protect private key with passphrase
  ✓ Use ssh-agent to avoid retyping passphrase
  ✓ Rotate keys periodically

Server Security:
  ✓ Disable password authentication
  ✓ Disable root login
  ✓ Use fail2ban for brute force protection
  ✓ Keep SSH updated
  ✓ Use non-standard port (security through obscurity, minor)

Access Control:
  ✓ Limit allowed users
  ✓ Use bastion/jump hosts
  ✓ Audit authorized_keys regularly

Troubleshooting

# Verbose output
$ ssh -v user@server      # Basic
$ ssh -vvv user@server    # Maximum verbosity

# Check key permissions
$ ls -la ~/.ssh/
# id_ed25519 should be 600
# authorized_keys should be 600

# Test authentication
$ ssh -T git@github.com

# Check server logs (on server)
$ sudo tail -f /var/log/auth.log