SSH (Secure Shell) is the backbone of secure server administration. Beyond basic login functionality, SSH provides powerful features for tunneling, port forwarding, and secure file transfer. This guide covers essential SSH configurations and advanced techniques from a senior developer's perspective.
Why Master SSH
SSH proficiency enables:
- Secure Access: Encrypted communication to remote servers
- Key-Based Auth: Eliminate password vulnerabilities
- Port Forwarding: Access internal services securely
- File Transfer: SFTP and SCP for secure copies
- Jump Hosts: Traverse network boundaries safely
SSH Key Management
Generate SSH Keys
# Modern Ed25519 (recommended)
ssh-keygen -t ed25519 -f ~/.ssh/project_name -C "[email protected]"
# RSA for older servers
ssh-keygen -t rsa -b 4096 -f ~/.ssh/project_name -C "[email protected]"
You'll have two files:
~/.ssh/project_name - Private key (keep secret)~/.ssh/project_name.pub - Public key (share freely)
Copy Key to Server
# Automated method
ssh-copy-id -i ~/.ssh/project_name user@hostname
# Manual method
cat ~/.ssh/project_name.pub | ssh user@hostname "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"
Set Proper Permissions
chmod 700 ~/.ssh
chmod 600 ~/.ssh/project_name
chmod 644 ~/.ssh/project_name.pub
chmod 600 ~/.ssh/authorized_keys
chmod 600 ~/.ssh/config
SSH Config File
Create ~/.ssh/config for convenient connections:
# Default settings for all hosts
Host *
AddKeysToAgent yes
IdentitiesOnly yes
ServerAliveInterval 60
ServerAliveCountMax 3
# Production server
Host prod
HostName 192.168.1.100
User admin
Port 22
IdentityFile ~/.ssh/production_key
# Staging with non-standard port
Host staging
HostName staging.example.com
User deploy
Port 2222
IdentityFile ~/.ssh/staging_key
# Jump through bastion host
Host internal-server
HostName 10.0.0.50
User admin
ProxyJump bastion
Host bastion
HostName bastion.example.com
User jumpuser
IdentityFile ~/.ssh/bastion_key
# Development with forwarding
Host dev
HostName dev.example.com
User developer
LocalForward 3306 localhost:3306
LocalForward 6379 localhost:6379
Now connect with simple commands:
ssh prod
ssh staging
ssh internal-server
SSH Tunnels and Port Forwarding
Local Port Forwarding
Access remote services as if they're local:
# Forward local:8080 to remote:80
ssh -L 8080:localhost:80 user@server
# Access remote database locally
ssh -L 3306:localhost:3306 user@server
# Access a service on a remote network
ssh -L 8080:internal-db:5432 user@bastion
Now localhost:8080 connects to the remote service.
Remote Port Forwarding
Expose local services to a remote server:
# Make local:3000 accessible on remote:8080
ssh -R 8080:localhost:3000 user@server
Remote users can access server:8080 to reach your local app.
Dynamic Port Forwarding (SOCKS Proxy)
Create a SOCKS proxy through SSH:
ssh -D 1080 user@server
Configure your browser/application to use a SOCKS5 proxy at localhost:1080.
SSH Tunnel for Database Access
Access a database that only allows localhost connections:
# MySQL
ssh -L 3306:127.0.0.1:3306 user@db-server
mysql -h 127.0.0.1 -P 3306 -u dbuser -p
# PostgreSQL
ssh -L 5432:127.0.0.1:5432 user@db-server
psql -h 127.0.0.1 -p 5432 -U dbuser database
Persistent Tunnel with autossh
Keep tunnels alive automatically:
# Install autossh
sudo apt install autossh
# Create a persistent tunnel
autossh -M 0 -f -N -L 3306:localhost:3306 user@server
Accessing Localhost-Only Services
Some services (like phpMyAdmin) only accept localhost connections. Use SSH tunneling:
ssh -N -L 8080:127.0.0.1:80 -i key.pem user@server
Access via http://localhost:8080 in your browser.
SSHFS - Mount Remote Filesystems
Mount remote directories locally:
# Install sshfs
sudo apt install sshfs
# Mount remote directory
sshfs user@server:/remote/path /local/mount -o reconnect,ServerAliveInterval=15,ServerAliveCountMax=3
# Follow symlinks
sshfs user@server:/remote/path /local/mount -o reconnect,ServerAliveInterval=15,ServerAliveCountMax=3,follow_symlinks
# Unmount
fusermount -u /local/mount
SSH Agent
Manage keys without repeated passphrase entry:
# Start agent
eval "$(ssh-agent -s)"
# Add key
ssh-add ~/.ssh/project_name
# List loaded keys
ssh-add -l
# Remove all keys
ssh-add -D
Save Passphrases in Agent
Add to ~/.ssh/config:
Host *
AddKeysToAgent yes
UseKeychain yes # macOS only
Server-Side Hardening
Secure SSH Daemon Configuration
Edit /etc/ssh/sshd_config:
# Disable root login
PermitRootLogin no
# Disable password authentication
PasswordAuthentication no
ChallengeResponseAuthentication no
# Use only SSH Protocol 2
Protocol 2
# Restrict to specific users/groups
AllowUsers admin deploy
AllowGroups ssh-users
# Limit authentication attempts
MaxAuthTries 3
# Set idle timeout
ClientAliveInterval 300
ClientAliveCountMax 2
# Disable empty passwords
PermitEmptyPasswords no
# Disable X11 forwarding if not needed
X11Forwarding no
# Use strong ciphers only
Ciphers [email protected],[email protected]
MACs [email protected],[email protected]
KexAlgorithms curve25519-sha256,[email protected]
Restart SSH after changes:
sudo systemctl restart sshd
Restrict Root to Specific IPs
# In /etc/ssh/sshd_config
Match Address 10.0.0.0/8
PermitRootLogin yes
Restrict Key Usage by Source IP
In ~/.ssh/authorized_keys:
from="192.168.1.100,10.0.0.0/24" ssh-ed25519 AAAAC3... user@host
SSH Through Proxy
HTTP Proxy
# Using netcat
ssh -o ProxyCommand='nc -X connect -x proxy:3128 %h %p' user@server
# In config file
Host server
ProxyCommand nc -X connect -x proxy:3128 %h %p
SOCKS Proxy
ssh -o ProxyCommand='nc -X 5 -x localhost:1080 %h %p' user@server
Troubleshooting
Debug Connection Issues
# Verbose output
ssh -v user@server
# More verbose
ssh -vv user@server
# Maximum verbosity
ssh -vvv user@server
Common Permission Errors
# "Permissions are too open" error
chmod 600 ~/.ssh/private_key
# "Host key verification failed"
ssh-keygen -R hostname # Remove old host key
Connection Timeout
# Increase connection timeout
ssh -o ConnectTimeout=30 user@server
# Keep connection alive
ssh -o ServerAliveInterval=60 user@server
Secure File Transfer
SCP
# Copy to remote
scp local_file user@server:/remote/path/
# Copy from remote
scp user@server:/remote/file ./local/
# Copy directory recursively
scp -r ./local/dir user@server:/remote/
SFTP
sftp user@server
# Interactive commands: get, put, ls, cd, mkdir, rm
Rsync over SSH
rsync -avz -e ssh ./local/ user@server:/remote/
Key Takeaways
- Use Ed25519 keys: Modern, secure, and fast
- Configure
~/.ssh/config: Simplify complex connections - Disable password auth: Use keys only on servers
- Use SSH agent: Avoid passphrase fatigue
- Master tunneling: Access internal services securely
- Harden servers: Limit users, disable root, use strong ciphers
SSH is far more than just remote login—it's a secure networking toolkit that, when mastered, dramatically improves both security and productivity.