Project 4: SSH Config Mastery

Build a secure, readable SSH config with host aliases, keys, and safe defaults.

Quick Reference

Attribute Value
Difficulty Level 2 (Intermediate)
Time Estimate 4-8 hours
Main Language SSH config + Shell
Prerequisites Basic SSH usage, key generation, file permissions
Key Topics Host aliases, key management, SSH config precedence

1. Learning Objectives

By completing this project, you will:

  1. Design a structured ~/.ssh/config with readable host blocks.
  2. Manage multiple SSH keys and identities safely.
  3. Use host aliases for faster and safer connections.
  4. Configure security defaults (agent forwarding, strict host checking).
  5. Document SSH workflows for future portability.

2. Theoretical Foundation

2.1 Core Concepts

  • Host Blocks: SSH config lets you define per-host settings (user, port, identity).
  • Key Management: Multiple keys allow separation of work and personal access.
  • ProxyJump and Bastions: Access internal hosts through a gateway securely.
  • SSH Config Precedence: Global vs user config and how the first matching rule wins.

2.2 Why This Matters

SSH is the backbone of developer workflows: git, servers, and remote automation all rely on it. A sloppy SSH config leads to credential mix-ups and security risks. A clean config makes access fast and safe while keeping identities separate.

2.3 Historical Context / Background

SSH replaced insecure protocols (telnet, rsh) by introducing encrypted authentication. Over time, SSH config evolved to support complex infrastructures: jump hosts, key segregation, and multiplexing. Modern setups depend on .ssh/config to reduce risk and increase speed.

2.4 Common Misconceptions

  • “One SSH key for everything is fine”: It creates unnecessary risk.
  • “Agent forwarding is always safe”: It can leak credentials on compromised hosts.
  • “Config is optional”: Manual ssh user@host -p ... doesn’t scale.

3. Project Specification

3.1 What You Will Build

A structured SSH config that:

  • Defines at least 5 host aliases
  • Uses separate keys for work and personal access
  • Includes a bastion/jump host example
  • Sets strict host key checking defaults
  • Documents how to add new hosts and keys

3.2 Functional Requirements

  1. Host Aliases: Create named hosts (e.g., work-git, prod-db).
  2. Key Segregation: At least two keys with explicit IdentityFile assignments.
  3. Jump Host: Include a ProxyJump example.
  4. Security Defaults: Configure IdentitiesOnly yes, ServerAliveInterval, and StrictHostKeyChecking.
  5. Docs: Provide a short README or comments on host blocks.

3.3 Non-Functional Requirements

  • Security: Avoid unsafe defaults like permanent agent forwarding.
  • Portability: Keep paths OS-neutral where possible.
  • Reliability: Connections should be repeatable with short host names.

3.4 Example Usage / Output

$ ssh work-git
Welcome to work Git server.

$ ssh prod-bastion
prod-bastion:~$ ssh prod-db

3.5 Data Formats / Schemas

Host work-git
  HostName git.company.com
  User git
  IdentityFile ~/.ssh/id_ed25519_work
  IdentitiesOnly yes

3.6 Edge Cases

  • Host alias collides with existing command name.
  • SSH agent not running when required.
  • Host key mismatch due to re-provisioned server.
  • ProxyJump chain fails when bastion is down.

3.7 Real World Outcome

You can run ssh prod-app or git clone work-repo: without remembering hostnames, usernames, or ports. Keys are separated, and mistakes (wrong identity or host) are much harder to make.


4. Solution Architecture

4.1 High-Level Design

~/.ssh/config
  |-- Host work-*
  |-- Host personal-*
  |-- Host prod-bastion
  |-- Host prod-db (ProxyJump)

4.2 Key Components

Component Responsibility Key Decisions
host aliases human-readable shortcuts naming conventions
identity files separate keys work vs personal
bastion config secure jump path ProxyJump vs ProxyCommand

4.3 Data Structures (No Full Code)

Host prod-db
  HostName 10.0.0.5
  User ubuntu
  ProxyJump prod-bastion

4.4 Algorithm Overview

Connection Resolution

  1. SSH reads system config.
  2. SSH reads user config and matches the first host pattern.
  3. Options are applied in order; later blocks override earlier ones.
  4. Identity is selected and connection established.

Complexity Analysis:

  • Time: O(N) host blocks
  • Space: O(1)

5. Implementation Guide

5.1 Development Environment Setup

ssh -V
ssh-keygen -t ed25519 -C "work"
ssh-keygen -t ed25519 -C "personal"

5.2 Project Structure

~/.ssh/
├── config
├── id_ed25519_work
├── id_ed25519_personal
└── known_hosts

5.3 The Core Question You Are Answering

“How do I make SSH safer, faster, and less error-prone across many machines?”

5.4 Concepts You Must Understand First

  1. SSH Config Precedence
    • How matching works and which rules apply
  2. Key Isolation
    • Why separate keys reduce risk
  3. Jump Hosts
    • How ProxyJump reduces exposure of internal hosts

5.5 Questions to Guide Your Design

  1. Which hosts do you access most often?
  2. Where do you need separate identities?
  3. Which servers should never allow agent forwarding?
  4. What should be your default keepalive interval?

5.6 Thinking Exercise

List all servers you access. Group them into work/personal/prod and define a consistent alias prefix.

5.7 The Interview Questions They Will Ask

  1. How does SSH choose which config options to apply?
  2. Why use IdentitiesOnly yes?
  3. What risks come with agent forwarding?

5.8 Hints in Layers

Hint 1: Start with a few host aliases.

Hint 2: Add separate keys for work and personal.

Hint 3: Add a ProxyJump chain.

5.9 Books That Will Help

Topic Book Chapter
SSH basics The Linux Command Line Ch. 17
Security workflows Practical UNIX and Internet Security Ch. 2

5.10 Implementation Phases

Phase 1: Core Config (1-2 hours)

Goals:

  • Create host aliases
  • Add key references

Checkpoint: ssh work-git connects correctly.

Phase 2: Security Defaults (1-2 hours)

Goals:

  • Add keepalive settings
  • Set IdentitiesOnly yes

Checkpoint: SSH uses expected key and does not prompt unexpectedly.

Phase 3: Advanced Hosts (1-2 hours)

Goals:

  • Add ProxyJump example
  • Document patterns

Checkpoint: Jump host connection works.

5.11 Key Implementation Decisions

Decision Options Recommendation Rationale
Key separation one key vs multiple multiple reduces blast radius
Agent forwarding on vs off off by default safer for prod
Host naming short vs verbose short with prefixes easier typing

6. Testing Strategy

6.1 Test Categories

Category Purpose Examples
Connection Tests validate aliases ssh work-git
Identity Tests correct key used ssh -v output
Jump Tests proxy works ssh prod-db

6.2 Critical Test Cases

  1. Work host: uses work key only.
  2. Personal host: uses personal key only.
  3. Bastion: connection flows through jump host.

6.3 Test Data

Use ssh -v and confirm the key path in debug output.


7. Common Pitfalls and Debugging

Pitfall Symptom Solution
Wrong key used Permission denied Set IdentitiesOnly yes and IdentityFile
Host not matched config ignored Ensure host alias matches pattern
Jump fails timeout verify bastion reachability

7.2 Debugging Strategies

  • Use ssh -vvv to see which config options are applied.
  • Use ssh -G host to print the final config.

8. Extensions and Challenges

8.1 Beginner Extensions

  • Add a Host * block with safe defaults.
  • Add a custom port alias.

8.2 Intermediate Extensions

  • Add Match blocks for conditional rules.
  • Configure SSH multiplexing for speed.

8.3 Advanced Extensions

  • Integrate with ssh-agent and keychain.
  • Add YubiKey-based authentication.

9. Real-World Connections

9.1 Industry Applications

  • Secure access to production servers
  • Consistent Git access across organizations
  • Bastion-based security architecture
  • OpenSSH: reference implementation
  • sshuttle: VPN-like workflows over SSH

9.3 Interview Relevance

  • Demonstrates operational security knowledge and workflow design.

10. Resources

10.1 Essential Reading

  • The Linux Command Line (Ch. 17)
  • OpenSSH ssh_config man page

10.2 Tools and Documentation

  • ssh -G, ssh -v
  • OpenSSH ssh_config
  • Project 2: Git Configuration Powerhouse
  • Project 13: Machine-Specific Configuration

11. Self-Assessment Checklist

11.1 Understanding

  • I can explain host block matching rules
  • I can describe how SSH chooses keys
  • I understand ProxyJump basics

11.2 Implementation

  • Host aliases work reliably
  • Key separation is enforced
  • Jump host works when required

11.3 Growth

  • I can add new hosts quickly
  • I can debug SSH with verbose output

12. Submission / Completion Criteria

Minimum Viable Completion:

  • 5+ host aliases
  • Separate keys for work and personal

Full Completion:

  • ProxyJump example and security defaults

Excellence (Going Above and Beyond):

  • Multiplexing setup
  • Hardware-backed key support