SSH | Linux - Wyatt's Notes
SSH Protocol Overview
Section titled “SSH Protocol Overview”SSH (Secure Shell) protocol version 2 provides encrypted remote login and command execution. The Protocol operates in three layers:
flowchart TD A["Transport Layer<br />(TCP/IP, encryption, server auth)"] --> B["Authentication Layer<br />(password, key, keyboard-interactive)"] B --> C["Connection Layer<br />(channels, forwarding, X11, SFTP)"]Transport Layer
Section titled “Transport Layer”- TCP connection (default port 22)
- Server presents host key for verification
- Key exchange (curve25519-sha256, ecdh-sha2-nistp256, diffie-hellman-group14-sha256)
- Symmetric encryption (chacha20-poly1305, aes256-gcm)
- MAC / AEAD for integrity
- Session keys derived from shared secret
Authentication Layer
Section titled “Authentication Layer”- Password authentication
- Public key authentication (default preferred method)
- Keyboard-interactive (PAM, 2FA, OTP)
- GSSAPI (Kerberos)
- Host-based authentication
Connection Layer
Section titled “Connection Layer”- Multiplexed channels over a single TCP connection
- Session channels (shell, exec, subsystem)
- Port forwarding channels
- X11 forwarding
- Agent forwarding
- SFTP subsystem
Client Configuration
Section titled “Client Configuration”~/.ssh/config
Section titled “~/.ssh/config”The SSH client configuration file supports per-host settings, pattern matching, and conditional Blocks.
## ~/.ssh/config
## Global defaultsHost * ServerAliveInterval 60 ServerAliveCountMax 3 AddKeysToAgent yes IdentityFile ~/.ssh/id_ed25519 IdentitiesOnly yes StrictHostKeyChecking accept-new UserKnownHostsFile ~/.ssh/known_hosts
# Jump host (bastion)Host bastion HostName bastion.example.com User deploy Port 2222 IdentityFile ~/.ssh/id_bastion
# Internal servers via jump hostHost 10.0.0.* ProxyJump bastion User admin IdentityFile ~/.ssh/id_internal
# Specific serverHost web-prod HostName 10.0.0.10 User www ProxyJump bastion ForwardAgent yes
# GitHubHost github.com HostName github.com User git IdentityFile ~/.ssh/id_github IdentitiesOnly yesMatch Blocks (Conditional Configuration)
Section titled “Match Blocks (Conditional Configuration)”Host * User admin
# Override for specific hostsMatch host 10.0.0.* exec "ping -c 1 -W 1 %h" ProxyJump bastion
# Match on original host (useful with ProxyJump)Match host bastion.example.com ForwardAgent yes
# Match on local userMatch host * user root PermitTTY no ForwardAgent no
# Match on destination portMatch host * port 2222 User jumpuserCommon Client Options
Section titled “Common Client Options”HostName # actual hostname (not the alias)User # login usernamePort # SSH port (default 22)IdentityFile # path to private key fileIdentitiesOnly # only use explicitly specified keys (default no)ProxyJump # jump host (simpler than ProxyCommand)ProxyCommand # custom command for connection (more flexible)ForwardAgent # forward SSH agent (yes/no/ask)ForwardX11 # forward X11 (yes/no/ask)LocalForward # local port forwarding (-L)RemoteForward # remote port forwarding (-R)DynamicForward # SOCKS proxy (-D)ServerAliveInterval # send keepalive every N secondsServerAliveCountMax # max missed keepalives before disconnectTCPKeepAlive # enable TCP keepalive (default yes)Compression # enable compression (yes/no)ControlMaster # connection multiplexing (yes/no/ask/auto)ControlPath # socket path for multiplexed connectionsControlPersist # how long to keep master connection openStrictHostKeyChecking # (yes/no/accept-new/ask)UserKnownHostsFile # path to known_hosts fileLogLevel # (QUIET/FATAL/ERROR/INFO/VERBOSE/DEBUG)NumberOfPasswordPrompts # max password prompts (default 3)Connection Multiplexing
Section titled “Connection Multiplexing”# Enable connection sharing in ~/.ssh/configHost * ControlMaster auto ControlPath ~/.ssh/sockets/%r@%h-%p ControlPersist 600
# Create socket directorymkdir -p ~/.ssh/sockets
# First connection opens a master socketssh server.example.com
# Subsequent connections reuse the existing socket (instant!)ssh server.example.com # reuses existing connectionscp file server.example.com:/tmp/ # also reusesKey Management
Section titled “Key Management”ssh-keygen
Section titled “ssh-keygen”# Generate Ed25519 key (recommended — small, fast, secure)ssh-keygen -t ed25519 -C "user@workstation"ssh-keygen -t ed25519 -a 100 -C "user@workstation" # 100 KDF rounds
# Generate RSA key (4096 bits, for legacy compatibility)ssh-keygen -t rsa -b 4096 -C "user@workstation"
# Generate ECDSA keyssh-keygen -t ecdsa -b 521 -C "user@workstation"
# Specify output filessh-keygen -t ed25519 -f ~/.ssh/id_github -C "github-key"
# Generate key with no passphrase (for automation — use with caution)ssh-keygen -t ed25519 -f ~/.ssh/id_deploy -N ""
# Change passphrase on existing keyssh-keygen -p -f ~/.ssh/id_ed25519
# Generate public key from private keyssh-keygen -y -f ~/.ssh/id_ed25519 > ~/.ssh/id_ed25519.pub
# Generate fingerprintssh-keygen -l -f ~/.ssh/id_ed25519.pub
# Generate visual fingerprint (randomart)ssh-keygen -lv -f ~/.ssh/id_ed25519.pubKey Formats
Section titled “Key Formats”OpenSSH (default): id_ed25519 — private key (OpenSSH format) id_ed25519.pub — public key (single line)
PEM (legacy): id_rsa — "BEGIN RSA PRIVATE KEY" (PEM format) id_rsa.pub — public key
PKCS8: Convert with: ssh-keygen -p -f id_rsa -m PEM # to PEM Convert with: ssh-keygen -p -f id_rsa -m RFC4716 # to RFC4716
Ed25519 keys: - Best security per bit - Fastest key operations (sign/verify) - Smallest key size (64 bytes) - Recommended for all new keys
RSA keys: - Minimum 2048 bits (2048 is weak, 3072 is acceptable, 4096 is standard) - Slower than Ed25519 - Widely compatible with legacy systemsauthorized_keys
Section titled “authorized_keys”# ~/.ssh/authorized_keys — one public key per line# Format: [options] key-type base64-key [comment]
# Restrict key to specific commandcommand="/usr/bin/backup.sh",no-port-forwarding,no-X11-forwarding,no-pty ssh-ed25519 AAAA... backup@server
# Restrict by source IPfrom="10.0.0.0/24" ssh-ed25519 AAAA... admin@office
# Disable specific forwardingno-port-forwarding,no-X11-forwarding,no-agent-forwarding ssh-ed25519 AAAA... restricted
# Combined restrictionscommand="/usr/local/bin/monitor",from="10.0.0.50",no-pty,no-port-forwarding ssh-ed25519 AAAA... monitor
# Restrict to specific environment variablesenvironment="PATH=/usr/bin:/bin" ssh-ed25519 AAAA... env-user# Deploy public key to remote serverssh-copy-id user@server.example.com
# Manual deploymentcat ~/.ssh/id_ed25519.pub | ssh user@server "mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"
# View authorized_keys with restrictionscat ~/.ssh/authorized_keysKey Rotation
Section titled “Key Rotation”# Generate new keyssh-keygen -t ed25519 -f ~/.ssh/id_ed25519_new -C "user@workstation"
# Deploy new keyssh-copy-id -i ~/.ssh/id_ed25519_new.pub user@server
# Test new keyssh -i ~/.ssh/id_ed25519_new user@server
# Remove old key from authorized_keys on serverssh user@server "sed -i "/OLD_KEY_COMMENT/d" ~/.ssh/authorized_keys"
# Update local configsed -i 's/id_ed25519/id_ed25519_new/' ~/.ssh/config
# Remove old keyrm ~/.ssh/id_ed25519 ~/.ssh/id_ed25519.pubServer Configuration
Section titled “Server Configuration”sshd_config
Section titled “sshd_config”# NetworkPort 22AddressFamily inet # inet (IPv4 only), inet6, anyListenAddress 0.0.0.0ListenAddress ::
# Host keysHostKey /etc/ssh/ssh_host_ed25519_keyHostKey /etc/ssh/ssh_host_rsa_key
# Key exchange algorithms (drop weak ones)KexAlgorithms curve25519-sha256,curve25519-sha256@libssh.org,ecdh-sha2-nistp521,ecdh-sha2-nistp384,ecdh-sha2-nistp256,diffie-hellman-group14-sha256
# CiphersCiphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com
# MACsMACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com
# AuthenticationPermitRootLogin prohibit-password # yes/no/prohibit-password/forced-commands-onlyPubkeyAuthentication yesPasswordAuthentication noPermitEmptyPasswords noChallengeResponseAuthentication noKbdInteractiveAuthentication noUsePAM no
# Authorized keys locationAuthorizedKeysFile .ssh/authorized_keysAuthorizedPrincipalsFile none
# Access controlAllowUsers deploy admin@10.0.0.0/24# AllowGroups ssh-users# DenyUsers baduser# DenyGroups nogroup
# SessionMaxAuthTries 3MaxSessions 10LoginGraceTime 30ClientAliveInterval 300ClientAliveCountMax 2X11Forwarding noAllowTcpForwarding yesPermitTunnel noPermitTTY yes
# SecurityStrictModes yes # check file permissions on key filesPermitRootLogin prohibit-passwordAllowAgentForwarding noAllowTcpForwarding no # disable if not needed
# LoggingSyslogFacility AUTHLogLevel VERBOSE
# BannerBanner /etc/ssh/banner
# SubsystemsSubsystem sftp /usr/lib/openssh/sftp-server# or for chrooted SFTP:# Subsystem sftp internal-sftpHost Key Management
Section titled “Host Key Management”# Generate host keysssh-keygen -t ed25519 -f /etc/ssh/ssh_host_ed25519_keyssh-keygen -t rsa -b 4096 -f /etc/ssh/ssh_host_rsa_key
# Show host key fingerprintsssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub
# Verify server fingerprint from clientssh-keyscan server.example.com | ssh-keygen -lf -Restart and Test
Section titled “Restart and Test”# Validate configuration before restartingsshd -tsshd -T # show effective configuration
# Restartsystemctl restart sshd
# Check statussystemctl status sshdsystemctl is-active sshdSSH Agent
Section titled “SSH Agent”ssh-agent
Section titled “ssh-agent”# Start the agenteval $(ssh-agent)ssh-agent bash # start a shell with agent
# Add keys to the agentssh-add # add default keysssh-add ~/.ssh/id_ed25519 # add specific keyssh-add -l # list keys in agentssh-add -L # list public keysssh-add -d ~/.ssh/id_ed25519 # remove specific keyssh-add -D # remove all keys
# Add key with limited lifetimessh-add -t 3600 ~/.ssh/id_ed25519 # 1 hourssh-add -t 8h ~/.ssh/id_ed25519 # 8 hours
# Lock agentssh-add -x # lock with password promptAgent Forwarding
Section titled “Agent Forwarding”# Enable forwarding per-host in ~/.ssh/configHost server ForwardAgent yes
# Or via command linessh -A user@server
# Or via ProxyJump (forward agent through jump host)Host internal ProxyJump bastion ForwardAgent yesIntuition
Section titled “Intuition”Processes are programs in execution, each with its own memory space and priority. Systemd manages the lifecycle of services, starting them at boot and restarting them if they fail. Understanding process states (running, sleeping, stopped, zombie) helps you diagnose why a service is not responding. Signals like SIGTERM and SIGKILL provide graceful and forceful ways to control processes.