Keys, Config, and Tunnels
Keys, Config, and Tunnels#
Concepts#
SSH Key Authentication#
Key-based auth is more secure than passwords: the private key never leaves your machine, and it can be protected with a passphrase.
Generate a Key Pair#
ssh-keygen -t ed25519 -C "your_email@example.com"
# -t ed25519: modern, fast, secure algorithm
# -C: comment (usually your email)
It asks for:
- File: default
~/.ssh/id_ed25519(press Enter) - Passphrase: encrypts the private key (recommended — adds a second factor)
This creates two files:
~/.ssh/id_ed25519— your private key (never share this)~/.ssh/id_ed25519.pub— your public key (put this on servers)
Copy Public Key to a Server#
ssh-copy-id user@hostname
# Prompts for password one last time
# Copies your public key to ~/.ssh/authorized_keys on the server
Now you can log in without a password:
ssh user@hostname
# Logs in using your key — no password prompt!
Manual Key Setup#
If ssh-copy-id is not available:
# On the server:
mkdir -p ~/.ssh
chmod 700 ~/.ssh
# Paste your public key into:
nano ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys
SSH File Permissions#
SSH is strict about permissions. Wrong permissions = refused connection:
| Path | Permission | Meaning |
|---|---|---|
~/.ssh/ |
700 |
Owner only |
~/.ssh/authorized_keys |
600 |
Owner read/write only |
~/.ssh/id_ed25519 |
600 |
Private key — owner only |
~/.ssh/id_ed25519.pub |
644 |
Public key — anyone can read |
~/.ssh/config |
600 |
Config — owner only |
All of these codes are explained in File Permissions.
SSH Agent#
If your key has a passphrase, you’d normally type it every time. The SSH agent caches the decrypted key in memory:
# Start the agent (usually auto-started on desktop)
eval "$(ssh-agent -s)"
# Add your key (prompts for passphrase once)
ssh-add ~/.ssh/id_ed25519
# List loaded keys
ssh-add -l
# Now SSH connections use the cached key — no passphrase prompt
SSH Config File#
~/.ssh/config saves connection settings so you don’t have to type them every time:
# ~/.ssh/config
Host myserver
HostName 192.168.1.100
User kmiguel
Port 22
IdentityFile ~/.ssh/id_ed25519
Host webdev
HostName dev.example.com
User deploy
Port 2222
ForwardAgent yes
Host *
ServerAliveInterval 60
ServerAliveCountMax 3
Now instead of:
ssh -p 2222 deploy@dev.example.com
You just type:
ssh webdev
Common options:
| Option | Meaning |
|---|---|
HostName |
Real hostname or IP |
User |
Username on the remote |
Port |
SSH port |
IdentityFile |
Which private key to use |
ForwardAgent |
Forward your SSH agent to the remote (use cautiously) |
ServerAliveInterval |
Send keepalive every N seconds (prevents timeout) |
ProxyJump |
Jump through another SSH server (bastion host) |
Port Forwarding (Tunnels)#
SSH can forward network ports through the encrypted connection.
Local Port Forwarding#
Access a remote service through a local port:
ssh -L 8080:localhost:80 user@server
# Now http://localhost:8080 on YOUR machine → port 80 on the SERVER
Use case: access a web app on a remote server that only listens on localhost.
Remote Port Forwarding#
Expose a local service through the remote server:
ssh -R 9090:localhost:3000 user@server
# Now port 9090 on the SERVER → port 3000 on YOUR machine
Dynamic Port Forwarding (SOCKS Proxy)#
ssh -D 1080 user@server
# Creates a SOCKS proxy on localhost:1080
# Configure your browser to use it — all traffic goes through the server
SOCKS is similar to an HTTP proxy but there are some very important differences denoted in this article.
Copying Keys Between Machines#
# Copy your public key to clipboard (install xclip first)
cat ~/.ssh/id_ed25519.pub | xclip -selection clipboard
# Or just display it and copy manually
cat ~/.ssh/id_ed25519.pub
Lab#
Exercise 1: Generate an SSH Key#
# Generate a key pair (if you don't have one)
ls ~/.ssh/id_ed25519 2>/dev/null || ssh-keygen -t ed25519 -C "lab@course"
# View your public key
cat ~/.ssh/id_ed25519.pub
# Check permissions
ls -la ~/.ssh/
Exercise 2: Set Up Key Authentication (Localhost)#
# Copy key to localhost
ssh-copy-id $(whoami)@localhost
# Test — should connect without password
ssh $(whoami)@localhost "echo 'Key auth works!'"
Exercise 3: Create an SSH Config#
cat > ~/.ssh/config << 'EOF'
Host local
HostName localhost
User $USER
Host *
ServerAliveInterval 60
ServerAliveCountMax 3
EOF
# Fix the $USER placeholder
sed -i "s/\$USER/$(whoami)/" ~/.ssh/config
chmod 600 ~/.ssh/config
# Test
ssh local "hostname"
Exercise 4: Local Port Forwarding#
# Start a simple web server on port 8888
python3 -m http.server 8888 &
WEB_PID=$!
# Forward local port 9999 to localhost:8888 through SSH
ssh -f -N -L 9999:localhost:8888 $(whoami)@localhost
# Test — both should show the same content
curl -s http://localhost:8888 | head -5
curl -s http://localhost:9999 | head -5
# Clean up
kill $WEB_PID
pkill -f "ssh.*9999:localhost:8888"
Exercise 5: SSH Agent#
# Check if agent is running
echo $SSH_AUTH_SOCK
# List loaded keys
ssh-add -l
# Add your key
ssh-add ~/.ssh/id_ed25519
# Verify
ssh-add -l
Review#
1. How do you generate an SSH key pair?
ssh-keygen -t ed25519 -C "comment". This creates a private key (~/.ssh/id_ed25519) and a public key (~/.ssh/id_ed25519.pub).
2. How do you install your public key on a server?
ssh-copy-id user@host. This copies your public key to ~/.ssh/authorized_keys on the server. After that, you can log in without a password.
3. What is the SSH agent?
A program that caches your decrypted private keys in memory. You type your passphrase once (ssh-add), and subsequent SSH connections use the cached key without re-prompting.
4. What does the `~/.ssh/config` file do?
It stores connection presets (hostname, user, port, key, options) so you can connect with ssh shortname instead of typing the full command every time.
5. What is local port forwarding?
ssh -L local_port:target:target_port user@server — creates a tunnel so that connecting to localhost:local_port on your machine actually reaches target:target_port through the SSH server.
Previous: SSH Fundamentals | Next: tmux