0% found this document useful (0 votes)
2 views16 pages

SSH Complete Guide

This document is a comprehensive guide to SSH (Secure Shell), covering installation, usage, key management, and server hardening. It explains the protocol's functionality, compares it to other protocols, and provides detailed instructions on setting up OpenSSH, using SSH commands, and managing keys. Additionally, it includes best practices for security and troubleshooting, making it suitable for developers, sysadmins, and DevOps engineers.

Uploaded by

serkan
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
2 views16 pages

SSH Complete Guide

This document is a comprehensive guide to SSH (Secure Shell), covering installation, usage, key management, and server hardening. It explains the protocol's functionality, compares it to other protocols, and provides detailed instructions on setting up OpenSSH, using SSH commands, and managing keys. Additionally, it includes best practices for security and troubleshooting, making it suitable for developers, sysadmins, and DevOps engineers.

Uploaded by

serkan
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

SSH

Secure Shell — Complete Reference Guide

Everything you need to know about SSH: from first connection to advanced tunnelling, key management, OpenSSH
server hardening, and automation. Suitable for developers, sysadmins, and DevOps engineers.

Topics Covered

Installation & first steps

Public / Private key cryptography

Key generation, types & best practices

SSH config file & aliases

SSH agent & agent forwarding

Port forwarding & tunnelling

SCP / SFTP file transfers

OpenSSH server (sshd) setup & hardening

Multiplexing & ProxyJump

Common options & flags reference

Troubleshooting & security checklist


1. What Is SSH?
SSH (Secure Shell) is a cryptographic network protocol for operating network services securely over an unsecured
network. It replaces older plaintext protocols such as Telnet, rlogin, and rsh, providing encrypted communication, strong
authentication, and data integrity.

1.1 How SSH Works


SSH uses a client-server model. The client initiates a TCP connection (default port 22) to the server. A handshake
negotiates a shared session key using algorithms such as Diffie-Hellman, then all traffic is encrypted with symmetric
encryption (e.g. AES-256). Authentication follows — either by password or, preferably, by public-key cryptography.

Layer Purpose Example Algorithms

Transport Encryption, integrity, compression AES-256-CTR, ChaCha20, SHA-256

Authentication Verify client identity RSA, Ed25519, ECDSA

Connection Multiplex channels (shell, tunnel…) TCP channels over one SSH session

1.2 SSH vs Other Protocols


Protocol Port Encrypted? Use

SSH 22 Yes Remote shell, tunnels, file transfer

Telnet 23 No Legacy remote shell (avoid)

FTP 21 No Legacy file transfer (avoid)

SFTP 22 Yes File transfer over SSH

RDP 3389 Yes Windows GUI remote desktop

2. Installing OpenSSH
OpenSSH is the most widely used SSH implementation. It ships with most Linux distributions and macOS. Windows
10/11 includes it as an optional feature.

2.1 Linux
# Debian / Ubuntu
sudo apt update && sudo apt install openssh-client openssh-server

# RHEL / CentOS / Fedora


sudo dnf install openssh-clients openssh-server

# Arch Linux
sudo pacman -S openssh

2.2 macOS
# OpenSSH client is pre-installed. To install server:
# Enable via System Settings > General > Sharing > Remote Login
# Or use Homebrew for a newer version:
brew install openssh

2.3 Windows
# PowerShell (run as Administrator):
Add-WindowsCapability -Online -Name [Link]~~~~[Link]
Add-WindowsCapability -Online -Name [Link]~~~~[Link]

# Start & enable the service:


Start-Service sshd
Set-Service -Name sshd -StartupType Automatic

2.4 Verify Installation


ssh -V
# Example output: OpenSSH_9.7p1, OpenSSL 3.3.0

■ Always keep OpenSSH updated. Security vulnerabilities are patched regularly.


3. Basic SSH Usage

3.1 Connect to a Remote Host


ssh username@hostname
ssh username@[Link]
ssh username@hostname -p 2222 # custom port
ssh -v username@hostname # verbose (debug)
ssh -vvv username@hostname # very verbose

3.2 Run a Remote Command Without Opening a Shell


ssh user@host 'uptime'
ssh user@host 'ls -la /var/log'
ssh user@host 'df -h && free -m'

3.3 Common ssh Flags


Flag Meaning

-p PORT Connect to non-standard port

-i FILE Use specific private key file

-l USER Specify login username

-v / -vvv Verbose / very verbose logging

-N No remote command (useful for tunnels)

-f Background after authentication

-T Disable pseudo-terminal allocation

-A Enable agent forwarding

-X Enable X11 forwarding (GUI apps)

-C Enable compression

-4 / -6 Force IPv4 / IPv6

-o OPT=V Pass a config option inline

-J host Jump / proxy through host

-L Local port forward

-R Remote port forward

-D Dynamic SOCKS proxy

4. Public-Key Cryptography Explained


SSH public-key authentication uses an asymmetric key pair: a private key (secret, stays on your machine) and a
public key (shared freely, placed on remote servers).

When you connect, the server issues a challenge encrypted with your public key. Only your private key can decrypt it,
proving your identity — your password never travels over the network.
Key Where? Secret? What it does

Private key ~/.ssh/id_ed25519 YES — never share Decrypts server challenges, signs data

Public key ~/.ssh/id_ed25519.pub No — share freely Added to server's authorized_keys

■ NEVER share your private key. If compromised, revoke it immediately on all servers.

5. Generating SSH Keys

5.1 Recommended Key Types (2024+)


Algorithm Command flag Key size / curve Recommendation

Ed25519 -t ed25519 256-bit (Curve25519) ★ Best choice — fast, small, modern

ECDSA -t ecdsa 256/384/521-bit Good — widely supported

RSA -t rsa -b 4096 required Legacy — use only if Ed25519 unsupported

DSA -t dsa 1024-bit only ✗ Deprecated — do not use

5.2 Generate a Key Pair


# Recommended — Ed25519
ssh-keygen -t ed25519 -C 'your@[Link]'

# RSA 4096 (legacy compat)


ssh-keygen -t rsa -b 4096 -C 'your@[Link]'

# With custom output file


ssh-keygen -t ed25519 -f ~/.ssh/myserver_key -C 'myserver'

You will be prompted for a passphrase — this encrypts your private key on disk. Strongly recommended; use ssh-agent
to avoid re-typing it every time.

5.3 Key Files Created


File Type Description

~/.ssh/id_ed25519 Private Keep secret. Permissions must be 600

~/.ssh/id_ed25519.pub Public Copy to servers. Safe to share.

# Fix permissions (required — SSH refuses keys with wrong perms)


chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_ed25519
chmod 644 ~/.ssh/id_ed25519.pub

5.4 Copy Public Key to Server


# Easiest way:
ssh-copy-id -i ~/.ssh/id_ed25519.pub user@host

# Manual way:
cat ~/.ssh/id_ed25519.pub | ssh user@host 'mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys'
# Fix permissions on server side:
ssh user@host 'chmod 700 ~/.ssh && chmod 600 ~/.ssh/authorized_keys'
■ You can have multiple key pairs — one per server or purpose. Name them clearly.
6. SSH Agent
The SSH agent holds your decrypted private keys in memory so you only enter the passphrase once per session, not on
every connection.

6.1 Start & Add Keys


# Start agent (if not already running)
eval $(ssh-agent -s)

# Add default key (~/.ssh/id_ed25519)


ssh-add

# Add specific key


ssh-add ~/.ssh/myserver_key

# Add with expiry (key auto-removed after 4 hours)


ssh-add -t 14400 ~/.ssh/id_ed25519

# List loaded keys


ssh-add -l

# Remove all keys from agent


ssh-add -D

6.2 Agent Forwarding


Agent forwarding lets you SSH from a remote server to another server using your local keys — no need to copy private
keys to intermediate hosts.

ssh -A user@bastion # -A enables agent forwarding


# Now from bastion you can: ssh user@internal-server

■ Only enable agent forwarding to trusted hosts. A compromised server with forwarding can use your keys against other
servers.

6.3 macOS Keychain Integration


# Add to ~/.ssh/config to auto-load keys on macOS:
Host *
AddKeysToAgent yes
UseKeychain yes
IdentityFile ~/.ssh/id_ed25519

7. SSH Config File (~/.ssh/config)


The config file lets you define aliases and per-host defaults so you can type ssh myserver instead of long commands.

7.1 Full Example Config


# Global defaults
Host *
ServerAliveInterval 60
ServerAliveCountMax 3
AddKeysToAgent yes
IdentitiesOnly yes

# Production web server


Host prod
HostName [Link]
User deploy
Port 22
IdentityFile ~/.ssh/prod_key

# Internal server via jump host


Host internal
HostName [Link]
User admin
ProxyJump bastion

# Bastion / jump host


Host bastion
HostName [Link]
User ec2-user
IdentityFile ~/.ssh/bastion_key
ForwardAgent yes

# GitHub
Host [Link]
User git
IdentityFile ~/.ssh/github_ed25519

7.2 Key Config Directives


Directive Effect

HostName Actual hostname or IP to connect to

User Default username

Port Non-standard port number

IdentityFile Path to private key for this host

IdentitiesOnly yes Only use specified key (don't try others)

ProxyJump host Jump through an intermediate SSH host

ForwardAgent yes Enable agent forwarding to this host

ServerAliveInterval N Send keepalive every N seconds

ServerAliveCountMax N Max missed keepalives before disconnect

StrictHostKeyChecking no / yes / ask — host key verification

Compression yes Enable data compression (slow links)

ControlMaster auto Enable connection multiplexing

ControlPath ~/.ssh/... Socket path for multiplexed connections

LogLevel VERBOSE Logging verbosity for debug

Permissions on ~/.ssh/config must be 600 or SSH will ignore the file.


8. Port Forwarding & Tunnelling

8.1 Local Port Forwarding (-L)


Forwards a local port to a destination via the SSH server. Useful to access a remote database or web UI locally.

# Forward local :8080 -> remote server's :80


ssh -L 8080:localhost:80 user@remote

# Access a DB on the remote network (not on remote itself):


ssh -L 5432:[Link] user@bastion
# Now: psql -h localhost -p 5432
# Persistent / background:
ssh -fNL 8080:localhost:80 user@remote

8.2 Remote Port Forwarding (-R)


Exposes a local port on the remote server. Useful to give others access to a local dev server.

# Expose local :3000 on remote's :9000


ssh -R 9000:localhost:3000 user@remote
# Anyone on the remote can now curl [Link]
# For external access, add to sshd_config on server:
GatewayPorts yes

8.3 Dynamic SOCKS Proxy (-D)


Turns SSH into a SOCKS5 proxy. Route any application's traffic through the remote server — acts like a simple VPN.

ssh -D 1080 -fN user@remote


# Then set SOCKS5 proxy in browser: localhost:1080
# Or use with curl:
curl --socks5 localhost:1080 [Link]

8.4 ProxyJump (-J)


Connect to a target through one or more bastion hosts in a single command.

ssh -J user@bastion user@target

# Multiple hops:
ssh -J user@hop1,user@hop2 user@target

# In config file:
Host target
ProxyJump bastion

Type Flag Direction Use Case

Local forward -L local:dest:port local → remote network Access remote DB locally

Remote forward -R remote:dest:port remote → local network Expose local service

Dynamic proxy -D port all traffic via remote Bypass firewall / VPN

ProxyJump -J jumphost chain through bastion Multi-hop access

9. File Transfer: SCP & SFTP

9.1 SCP (Secure Copy)


# Upload local file to remote
scp [Link] user@host:/remote/path/

# Download remote file


scp user@host:/remote/[Link] ./local/

# Recursive directory copy


scp -r ./mydir user@host:/home/user/

# Specify port
scp -P 2222 [Link] user@host:/tmp/

# Use a specific key


scp -i ~/.ssh/prod_key [Link] user@host:/tmp/

9.2 SFTP (Interactive)


sftp user@host

# Common SFTP commands:


# ls, lls — list remote / local directory
# cd, lcd — change remote / local directory
# get file — download file
# put file — upload file
# mget *.log — download multiple files
# mput *.csv — upload multiple files
# rm, rmdir — remove file / directory
# mkdir — create directory
# quit / bye — exit SFTP

9.3 rsync over SSH (Preferred for Large Transfers)


# Sync local dir to remote (incremental, compressed)
rsync -avz ./localdir/ user@host:/remote/dir/

# Dry run (preview changes):


rsync -avzn ./localdir/ user@host:/remote/dir/

# Custom SSH options with rsync:


rsync -avz -e 'ssh -p 2222 -i ~/.ssh/prod_key' ./src/ user@host:/dst/

■ rsync is far more efficient than scp for large directories — it only transfers changed files.
10. OpenSSH Server (sshd) — Setup & Hardening

10.1 Service Management


sudo systemctl start sshd # start
sudo systemctl stop sshd # stop
sudo systemctl restart sshd # restart
sudo systemctl enable sshd # start on boot
sudo systemctl status sshd # check status

# Reload config without dropping connections:


sudo systemctl reload sshd # or: sudo kill -HUP $(cat /run/[Link])

10.2 sshd_config — Secure Configuration


File location: /etc/ssh/sshd_config (root + reload required after changes)

# --- Port & Protocol ---


Port 2222 # change from default 22 (obscurity)
AddressFamily inet # IPv4 only (or inet6 / any)
ListenAddress [Link]

# --- Authentication ---


PermitRootLogin no # NEVER allow root login
MaxAuthTries 3 # limit brute-force attempts
MaxSessions 5
PubkeyAuthentication yes # enable key-based auth
AuthorizedKeysFile .ssh/authorized_keys
PasswordAuthentication no # disable passwords (keys only!)
PermitEmptyPasswords no
ChallengeResponseAuthentication no
UsePAM yes

# --- Restrictions ---


AllowUsers deploy admin youruser # whitelist users
# AllowGroups sshusers # or restrict by group
LoginGraceTime 30 # seconds to complete login
ClientAliveInterval 300
ClientAliveCountMax 2

# --- Forwarding (disable what you don't need) ---


X11Forwarding no
AllowAgentForwarding no # set yes only when needed
AllowTcpForwarding no # set yes only for tunnels
GatewayPorts no

# --- Logging ---


LogLevel VERBOSE # captures key fingerprints
SyslogFacility AUTH

# --- Cryptographic hardening (OpenSSH 8+) ---


KexAlgorithms curve25519-sha256,diffie-hellman-group16-sha512
Ciphers chacha20-poly1305@[Link],aes256-gcm@[Link]
MACs hmac-sha2-512-etm@[Link],hmac-sha2-256-etm@[Link]
HostKeyAlgorithms ssh-ed25519,rsa-sha2-512

■ Disable PasswordAuthentication only AFTER you have verified key-based login works. Locking yourself out requires
console access.
10.3 Test Config Before Reload
sudo sshd -t # test — prints errors, silent on success
sudo sshd -T # dump full effective config

11. Key Management

11.1 List & Inspect Keys


# Show fingerprint of a key
ssh-keygen -lf ~/.ssh/id_ed25519.pub

# Show fingerprint in randomart:


ssh-keygen -lv -f ~/.ssh/id_ed25519.pub

# Show all keys the server has (from client):


ssh-keyscan hostname

11.2 Change Passphrase


ssh-keygen -p -f ~/.ssh/id_ed25519

11.3 Revoke / Remove a Key


# On the server, edit ~/.ssh/authorized_keys
# Delete the line containing the public key to revoke
nano ~/.ssh/authorized_keys

# Or use sed to remove a specific key (match by comment):


sed -i '/compromised-key-comment/d' ~/.ssh/authorized_keys

11.4 Known Hosts


When you first connect to a server, SSH stores its host key in ~/.ssh/known_hosts. On subsequent connections the key
is verified to detect MITM attacks.

# Remove a specific host entry (after server rebuild / IP change):


ssh-keygen -R hostname
ssh-keygen -R [Link]

# Show hash of a known host:


ssh-keygen -F hostname

■ Never blindly accept changed host keys. Verify the new fingerprint out-of-band (e.g. via the cloud console) before
removing the old entry.
12. Connection Multiplexing
Multiplexing reuses a single TCP connection for multiple SSH sessions, dramatically speeding up repeated connections
(no new handshake / auth).

# In ~/.ssh/config:
Host *
ControlMaster auto
ControlPath ~/.ssh/sockets/%r@%h-%p
ControlPersist 600 # keep master alive 10 min after last session

# Create socket directory:


mkdir -p ~/.ssh/sockets

# Check active masters:


ls -la ~/.ssh/sockets/

# Close a master explicitly:


ssh -O exit user@host

■ Multiplexing is especially useful in CI/CD pipelines and Ansible — connections after the first are near-instant.

13. Git & GitHub over SSH


# 1. Generate a dedicated key:
ssh-keygen -t ed25519 -f ~/.ssh/github -C 'me@[Link]'

# 2. Add to GitHub: Settings > SSH Keys > New SSH Key
# (paste contents of ~/.ssh/[Link])
# 3. Add to ~/.ssh/config:
Host [Link]
User git
IdentityFile ~/.ssh/github
AddKeysToAgent yes

# 4. Test:
ssh -T git@[Link]
# Output: Hi username! You've successfully authenticated.
# 5. Clone via SSH:
git clone git@[Link]:user/[Link]

14. Security Checklist


# Check Why

1 Use Ed25519 keys Strongest modern algorithm

2 Set a passphrase on private key Protects if key file is stolen

3 Disable PasswordAuthentication Eliminates brute-force risk

4 Set PermitRootLogin no Root never needed over SSH

5 Change default port (22) Reduces automated scan noise

6 AllowUsers / AllowGroups Restrict who can log in

7 Enable LogLevel VERBOSE Audit trail for forensics

8 Install fail2ban / sshguard Auto-ban repeated failures


9 Use ProxyJump over agent fwd Safer multi-hop access

10 Rotate keys annually Limit blast radius of leak

11 Audit authorized_keys regularly Remove stale / unknown keys

12 Keep OpenSSH updated Patch known CVEs promptly

13 Use ssh-keygen -t to expire agent keys Limit exposure window

14 Restrict cipher suites in sshd_config Drop weak algorithms


15. Troubleshooting
Problem Likely Cause Fix

Permission denied (publickey) Wrong key / not in authorized_keys ssh-copy-id; check key permissions (600/700)

Connection refused sshd not running or firewall systemctl status sshd; check ufw/iptables

Host key verification failed Server key changed ssh-keygen -R hostname

Too many authentication failures Agent offers too many keys Use -o IdentitiesOnly=yes -i key

Timeout / hangs No keepalive / firewall drops idle Set ServerAliveInterval 60 in config

Bad permissions on config ~/.ssh/config is world-readable chmod 600 ~/.ssh/config

ssh-add: No such file Agent not running eval $(ssh-agent -s)

Broken pipe Network drop / idle timeout ServerAliveInterval + ServerAliveCountMax

Debug Steps
# 1. Verbose client output
ssh -vvv user@host 2>&1 | head -60

# 2. Check sshd logs on server


sudo journalctl -u sshd -n 50
sudo tail -f /var/log/[Link]

# 3. Verify authorized_keys on server


cat ~/.ssh/authorized_keys
ls -la ~/.ssh/

# 4. Test sshd config


sudo sshd -t

16. Quick Reference Card


Task Command

Connect ssh user@host

Custom port ssh -p 2222 user@host

Specific key ssh -i ~/.ssh/mykey user@host

Run command ssh user@host 'command'

Generate Ed25519 key ssh-keygen -t ed25519 -C 'comment'

Copy key to server ssh-copy-id user@host

Start agent eval $(ssh-agent -s)

Add key to agent ssh-add ~/.ssh/id_ed25519

List agent keys ssh-add -l

Upload file (scp) scp [Link] user@host:/path/

Download file (scp) scp user@host:/path/[Link] ./

Sync directory (rsync) rsync -avz ./src/ user@host:/dst/


SFTP session sftp user@host

Local tunnel :8080→:80 ssh -L 8080:localhost:80 user@host

Remote tunnel :9000→:3000 ssh -R 9000:localhost:3000 user@host

SOCKS proxy on :1080 ssh -D 1080 -fN user@host

Jump through bastion ssh -J bastion user@target

Remove known host ssh-keygen -R hostname

Test sshd config sudo sshd -t

Reload sshd sudo systemctl reload sshd

View sshd logs sudo journalctl -u sshd -n 50

SSH Complete Guide — generated with OpenSSH 9.x in mind. Check 'man ssh', 'man ssh_config', 'man sshd_config' for the full
reference.

You might also like