SSH: Difference between revisions
Appearance
No edit summary |
Major expansion: add Linux/Debian coverage, port forwarding, security hardening, troubleshooting, advanced techniques |
||
| (One intermediate revision by the same user not shown) | |||
| Line 1: | Line 1: | ||
= | = SSH = | ||
[[File:OpenSSH logo.png|thumb|right|180px|OpenSSH - secure shell protocol]] | |||
'''SSH''' (Secure Shell) is the fundamental protocol for secure remote access. Essential for server administration, development workflows, and secure file transfer. | |||
==== | == Quick Reference == | ||
{| class="wikitable" | |||
! Task !! Command | |||
|- | |||
| Connect || <code>ssh user@host</code> | |||
|- | |||
| Copy file to remote || <code>scp file.txt user@host:/path/</code> | |||
|- | |||
| Copy file from remote || <code>scp user@host:/path/file.txt .</code> | |||
|- | |||
| Sync directories || <code>rsync -avz dir/ user@host:/path/</code> | |||
|- | |||
| Local port forward || <code>ssh -L 8080:localhost:80 user@host</code> | |||
|- | |||
| Remote port forward || <code>ssh -R 9090:localhost:3000 user@host</code> | |||
|- | |||
| SOCKS proxy || <code>ssh -D 1080 user@host</code> | |||
|} | |||
== SSH Key Setup == | |||
=== Generate Keys === | |||
<pre> | <pre> | ||
# Modern Ed25519 (recommended) | |||
ssh-keygen -t ed25519 -C "[email protected]" | |||
# RSA 4096-bit (legacy compatibility) | |||
ssh-keygen -t rsa -b 4096 -C "your@email.com" | |||
</pre> | </pre> | ||
==== Prevent Sleep ( | === Copy Key to Server === | ||
<pre> | |||
# Automatic method | |||
ssh-copy-id user@hostname | |||
# Manual method | |||
cat ~/.ssh/id_ed25519.pub | ssh user@hostname "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys" | |||
</pre> | |||
== SSH Config == | |||
The config file (<code>~/.ssh/config</code>) eliminates repetitive typing: | |||
<pre> | |||
# Personal VPS | |||
Host vps | |||
HostName 123.45.67.89 | |||
User debian | |||
IdentityFile ~/.ssh/id_ed25519 | |||
ServerAliveInterval 30 | |||
ServerAliveCountMax 3 | |||
# Jump through bastion | |||
Host internal-server | |||
HostName 10.0.0.50 | |||
User admin | |||
ProxyJump bastion | |||
# Bastion/jump host | |||
Host bastion | |||
HostName bastion.example.com | |||
User jumpuser | |||
IdentityFile ~/.ssh/bastion_key | |||
# Wildcard for work servers | |||
Host *.work.example.com | |||
User workuser | |||
IdentityFile ~/.ssh/work_key | |||
ForwardAgent yes | |||
</pre> | |||
'''Useful options:''' | |||
* <code>ServerAliveInterval 30</code> - Keep connection alive | |||
* <code>ServerAliveCountMax 3</code> - Retry 3 times before disconnect | |||
* <code>ProxyJump host</code> - Jump through another host | |||
* <code>ForwardAgent yes</code> - Forward SSH agent (use carefully) | |||
* <code>LocalForward 8080 localhost:80</code> - Persistent port forward | |||
* <code>Compression yes</code> - Enable compression | |||
== Port Forwarding == | |||
=== Local Forward === | |||
Access remote service locally: | |||
<pre> | |||
# Access remote PostgreSQL on localhost:5433 | |||
ssh -L 5433:localhost:5432 user@dbserver | |||
# Access internal web app | |||
ssh -L 8080:internal-app:80 user@bastion | |||
</pre> | |||
=== Remote Forward === | |||
Expose local service to remote: | |||
<pre> | |||
# Let remote server access your local dev server | |||
ssh -R 9000:localhost:3000 user@remote | |||
# Expose to all interfaces (requires GatewayPorts yes on server) | |||
ssh -R 0.0.0.0:9000:localhost:3000 user@remote | |||
</pre> | |||
=== Dynamic Forward (SOCKS Proxy) === | |||
<pre> | |||
# Create SOCKS5 proxy | |||
ssh -D 1080 user@host | |||
# Use with curl | |||
curl --socks5 localhost:1080 https://example.com | |||
</pre> | |||
== macOS Setup == | |||
=== Enable SSH Server === | |||
* '''macOS Ventura+:''' System Settings → General → Sharing → "Remote Login" ON | |||
* '''Older macOS:''' System Preferences → Sharing → "Remote Login" | |||
=== Prevent Sleep (for always-on Mac) === | |||
<pre> | <pre> | ||
sudo pmset -c sleep 0 | sudo pmset -c sleep 0 | ||
sudo pmset -c disablesleep 1 | sudo pmset -c disablesleep 1 | ||
sudo pmset -c womp 1 # Wake on network | |||
</pre> | |||
=== Keychain Integration === | |||
Add to <code>~/.ssh/config</code>: | |||
<pre> | |||
Host * | |||
AddKeysToAgent yes | |||
UseKeychain yes | |||
IdentityFile ~/.ssh/id_ed25519 | |||
</pre> | |||
== Linux/Debian Server Setup == | |||
sudo | |||
=== Install and Enable === | |||
<pre> | |||
sudo apt update && sudo apt install openssh-server | |||
sudo systemctl enable ssh | |||
sudo systemctl start ssh | |||
</pre> | </pre> | ||
=== | === Harden SSH === | ||
Edit <code>/etc/ssh/sshd_config</code>: | |||
<pre> | |||
# Disable password auth (keys only) | |||
PasswordAuthentication no | |||
ChallengeResponseAuthentication no | |||
# Disable root login | |||
PermitRootLogin no | |||
# Limit users | |||
AllowUsers debian | |||
# Change port (optional security through obscurity) | |||
# Port 2222 | |||
# Timeout settings | |||
ClientAliveInterval 300 | |||
ClientAliveCountMax 2 | |||
</pre> | |||
Apply changes: <code>sudo systemctl reload ssh</code> | |||
== Mosh (Mobile Shell) == | |||
For unstable connections (WiFi, mobile, high latency): | |||
<pre> | <pre> | ||
ssh | # Install (both client and server) | ||
brew install mosh # macOS | |||
sudo apt install mosh # Debian | |||
# Connect | |||
mosh user@hostname | |||
# With custom port | |||
mosh --ssh="ssh -p 2222" user@hostname | |||
</pre> | </pre> | ||
==== | '''Why Mosh:''' | ||
* Survives IP changes and sleep/wake | |||
* Local echo for instant feedback | |||
* UDP-based, handles packet loss | |||
== Troubleshooting == | |||
=== Connection Refused === | |||
<pre> | <pre> | ||
# | # Check if SSH is running | ||
sudo systemctl status ssh # Linux | |||
sudo systemsetup -getremotelogin # macOS | |||
# | # Check if port is open | ||
nc -zv hostname 22 | |||
# Firewall issues | |||
sudo ufw status # UFW | |||
sudo iptables -L -n # iptables | |||
</pre> | </pre> | ||
==== | === Permission Denied === | ||
<pre> | <pre> | ||
# Fix key permissions (must be restrictive) | |||
chmod 700 ~/.ssh | |||
chmod 600 ~/.ssh/id_* | |||
chmod 644 ~/.ssh/id_*.pub | |||
chmod 600 ~/.ssh/authorized_keys | |||
# Debug connection | |||
ssh -vvv user@hostname | |||
</pre> | </pre> | ||
=== Host Key Changed === | |||
<pre> | |||
# Remove old host key | |||
ssh-keygen -R hostname | |||
# Or edit ~/.ssh/known_hosts manually | |||
</pre> | |||
==== | === Slow Connection === | ||
<pre> | <pre> | ||
# Often DNS-related, disable reverse lookup on server | |||
# Add to /etc/ssh/sshd_config: | |||
UseDNS no | |||
</pre> | </pre> | ||
== Advanced Techniques == | |||
=== SSH Agent === | |||
<pre> | |||
# Start agent | |||
eval $(ssh-agent -s) | |||
# Add key | |||
ssh-add ~/.ssh/id_ed25519 | |||
# List loaded keys | |||
ssh-add -l | |||
</pre> | |||
=== | === Multiplexing === | ||
Speed up multiple connections to same host: | |||
<pre> | <pre> | ||
# | # Add to ~/.ssh/config | ||
Host * | |||
ControlMaster auto | |||
ControlPath ~/.ssh/sockets/%r@%h-%p | |||
ControlPersist 600 | |||
</pre> | |||
=== Run Remote Commands === | |||
<pre> | |||
# Single command | |||
ssh user@host 'ls -la /var/log' | |||
# | # Multiple commands | ||
ssh user@host 'cd /app && git pull && pm2 restart all' | |||
# | # With sudo | ||
sudo | ssh -t user@host 'sudo systemctl restart nginx' | ||
</pre> | </pre> | ||
=== | === Copy with Progress === | ||
<pre> | <pre> | ||
# rsync with progress | |||
# | rsync -avz --progress largefile.tar.gz user@host:/path/ | ||
# scp with compression | |||
scp -C largefile.tar.gz user@host:/path/ | |||
</pre> | </pre> | ||
== Related == | |||
* [[VPS]] - Server administration | |||
* [[Dotfiles]] - Shell configuration | |||
* [[PGP]] - Key management | |||
[[Category:SSH]] | [[Category:SSH]] | ||
[[Category:Networking]] | [[Category:Networking]] | ||
[[Category:Security]] | |||
[[Category:System Administration]] | |||
{{Navbox Technical}} | |||
Latest revision as of 05:31, 15 January 2026
SSH
SSH (Secure Shell) is the fundamental protocol for secure remote access. Essential for server administration, development workflows, and secure file transfer.
Quick Reference
| Task | Command |
|---|---|
| Connect | ssh user@host
|
| Copy file to remote | scp file.txt user@host:/path/
|
| Copy file from remote | scp user@host:/path/file.txt .
|
| Sync directories | rsync -avz dir/ user@host:/path/
|
| Local port forward | ssh -L 8080:localhost:80 user@host
|
| Remote port forward | ssh -R 9090:localhost:3000 user@host
|
| SOCKS proxy | ssh -D 1080 user@host
|
SSH Key Setup
Generate Keys
# Modern Ed25519 (recommended) ssh-keygen -t ed25519 -C "[email protected]" # RSA 4096-bit (legacy compatibility) ssh-keygen -t rsa -b 4096 -C "[email protected]"
Copy Key to Server
# Automatic method ssh-copy-id user@hostname # Manual method cat ~/.ssh/id_ed25519.pub | ssh user@hostname "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"
SSH Config
The config file (~/.ssh/config) eliminates repetitive typing:
# Personal VPS
Host vps
HostName 123.45.67.89
User debian
IdentityFile ~/.ssh/id_ed25519
ServerAliveInterval 30
ServerAliveCountMax 3
# Jump through bastion
Host internal-server
HostName 10.0.0.50
User admin
ProxyJump bastion
# Bastion/jump host
Host bastion
HostName bastion.example.com
User jumpuser
IdentityFile ~/.ssh/bastion_key
# Wildcard for work servers
Host *.work.example.com
User workuser
IdentityFile ~/.ssh/work_key
ForwardAgent yes
Useful options:
ServerAliveInterval 30- Keep connection aliveServerAliveCountMax 3- Retry 3 times before disconnectProxyJump host- Jump through another hostForwardAgent yes- Forward SSH agent (use carefully)LocalForward 8080 localhost:80- Persistent port forwardCompression yes- Enable compression
Port Forwarding
Local Forward
Access remote service locally:
# Access remote PostgreSQL on localhost:5433 ssh -L 5433:localhost:5432 user@dbserver # Access internal web app ssh -L 8080:internal-app:80 user@bastion
Remote Forward
Expose local service to remote:
# Let remote server access your local dev server ssh -R 9000:localhost:3000 user@remote # Expose to all interfaces (requires GatewayPorts yes on server) ssh -R 0.0.0.0:9000:localhost:3000 user@remote
Dynamic Forward (SOCKS Proxy)
# Create SOCKS5 proxy ssh -D 1080 user@host # Use with curl curl --socks5 localhost:1080 https://example.com
macOS Setup
Enable SSH Server
- macOS Ventura+: System Settings → General → Sharing → "Remote Login" ON
- Older macOS: System Preferences → Sharing → "Remote Login"
Prevent Sleep (for always-on Mac)
sudo pmset -c sleep 0 sudo pmset -c disablesleep 1 sudo pmset -c womp 1 # Wake on network
Keychain Integration
Add to ~/.ssh/config:
Host *
AddKeysToAgent yes
UseKeychain yes
IdentityFile ~/.ssh/id_ed25519
Linux/Debian Server Setup
Install and Enable
sudo apt update && sudo apt install openssh-server sudo systemctl enable ssh sudo systemctl start ssh
Harden SSH
Edit /etc/ssh/sshd_config:
# Disable password auth (keys only) PasswordAuthentication no ChallengeResponseAuthentication no # Disable root login PermitRootLogin no # Limit users AllowUsers debian # Change port (optional security through obscurity) # Port 2222 # Timeout settings ClientAliveInterval 300 ClientAliveCountMax 2
Apply changes: sudo systemctl reload ssh
Mosh (Mobile Shell)
For unstable connections (WiFi, mobile, high latency):
# Install (both client and server) brew install mosh # macOS sudo apt install mosh # Debian # Connect mosh user@hostname # With custom port mosh --ssh="ssh -p 2222" user@hostname
Why Mosh:
- Survives IP changes and sleep/wake
- Local echo for instant feedback
- UDP-based, handles packet loss
Troubleshooting
Connection Refused
# Check if SSH is running sudo systemctl status ssh # Linux sudo systemsetup -getremotelogin # macOS # Check if port is open nc -zv hostname 22 # Firewall issues sudo ufw status # UFW sudo iptables -L -n # iptables
Permission Denied
# Fix key permissions (must be restrictive) chmod 700 ~/.ssh chmod 600 ~/.ssh/id_* chmod 644 ~/.ssh/id_*.pub chmod 600 ~/.ssh/authorized_keys # Debug connection ssh -vvv user@hostname
Host Key Changed
# Remove old host key ssh-keygen -R hostname # Or edit ~/.ssh/known_hosts manually
Slow Connection
# Often DNS-related, disable reverse lookup on server # Add to /etc/ssh/sshd_config: UseDNS no
Advanced Techniques
SSH Agent
# Start agent eval $(ssh-agent -s) # Add key ssh-add ~/.ssh/id_ed25519 # List loaded keys ssh-add -l
Multiplexing
Speed up multiple connections to same host:
# Add to ~/.ssh/config
Host *
ControlMaster auto
ControlPath ~/.ssh/sockets/%r@%h-%p
ControlPersist 600
Run Remote Commands
# Single command ssh user@host 'ls -la /var/log' # Multiple commands ssh user@host 'cd /app && git pull && pm2 restart all' # With sudo ssh -t user@host 'sudo systemctl restart nginx'
Copy with Progress
# rsync with progress rsync -avz --progress largefile.tar.gz user@host:/path/ # scp with compression scp -C largefile.tar.gz user@host:/path/
Related
| ⚡ Technical | |
|---|---|
| Core | Technical · CLI · Dotfiles · Nvim · SSH · VPS |
| Tools | Sketchybar · ArchiveBox · ThinkPad Linux |
| Systems | Automation · Personal APIs · Quantified Self |
| Reference | Runbooks · New Computer Runbook · Syntax guide |