SSH Connection Multiplexing¶
Overview¶
Connection multiplexing allows multiple SSH sessions to share a single TCP connection. Benefits:
- Faster subsequent connections (no new handshake)
- Reduced authentication overhead
- Single connection through firewalls
- Efficient resource usage
┌──────────────────────────────────────────────────────────────────────────┐
│ Without Multiplexing │
│ │
│ ssh user@host ────────── [TCP + Auth + Crypto] ──────▶ Session 1 │
│ ssh user@host ────────── [TCP + Auth + Crypto] ──────▶ Session 2 │
│ ssh user@host ────────── [TCP + Auth + Crypto] ──────▶ Session 3 │
│ │
│ 3 connections, 3 authentications, 3 key exchanges │
│ │
├──────────────────────────────────────────────────────────────────────────┤
│ With Multiplexing │
│ │
│ ssh user@host ────────── [TCP + Auth + Crypto] ──────┐ │
│ ssh user@host ──────────────────────────────────────▶│ Sessions │
│ ssh user@host ──────────────────────────────────────▶│ 1, 2, 3 │
│ │ │
│ 1 connection, 1 authentication, shared over socket │ │
│ └──────────────┘
└──────────────────────────────────────────────────────────────────────────┘
Enable Multiplexing¶
SSH Config¶
Create Socket Directory¶
Options Explained¶
| Option | Description |
|---|---|
ControlMaster auto | Automatically create master or use existing |
ControlPath | Socket file location |
ControlPersist 600 | Keep connection alive 10 minutes after last session |
ControlPath Tokens¶
| Token | Meaning |
|---|---|
%r | Remote username |
%h | Remote hostname |
%p | Port |
%n | Original hostname (before config) |
%l | Local hostname |
%C | Hash of %l%h%p%r (unique) |
Recommended Paths¶
# Simple
ControlPath ~/.ssh/sockets/%r@%h-%p
# With hash (handles long hostnames)
ControlPath ~/.ssh/sockets/%C
# In /tmp (cleared on reboot)
ControlPath /tmp/ssh-%r@%h:%p
ControlMaster Options¶
# Automatic (recommended)
ControlMaster auto
# Yes - always be master
ControlMaster yes
# No - never be master, use existing
ControlMaster no
# Ask - prompt before creating
ControlMaster ask
# Autoask - auto but ask for new
ControlMaster autoask
ControlPersist Options¶
# Time in seconds
ControlPersist 600 # 10 minutes
# Or with units
ControlPersist 10m # 10 minutes
ControlPersist 1h # 1 hour
# Stay forever until manually closed
ControlPersist yes
# Close when last session ends
ControlPersist no
Managing Multiplexed Connections¶
Check Status¶
List Sessions¶
Add Port Forward to Existing Connection¶
Cancel Port Forward¶
Stop Master Connection¶
Per-Host Configuration¶
# ~/.ssh/config
# Enable for most hosts
Host *
ControlMaster auto
ControlPath ~/.ssh/sockets/%C
ControlPersist 10m
# Disable for unreliable connections
Host flaky-server
ControlMaster no
# Longer persist for frequently used
Host workstation
ControlPersist 2h
Command Line Usage¶
Start Master Explicitly¶
Use Existing Master¶
Background Master¶
Use Cases¶
Faster Git Operations¶
Multiple git operations share one connection:
Multiple Terminals to Same Host¶
First terminal creates master, subsequent reuse:
# Terminal 1 (creates master)
ssh server
# Terminal 2 (instant connect)
ssh server
# Terminal 3 (instant connect)
ssh server
Faster Rsync/SCP¶
# First transfer creates master
rsync -avz dir/ user@host:/path/
# Subsequent transfers are faster
rsync -avz file.txt user@host:/path/
scp another.txt user@host:/path/
Batch Operations¶
#!/bin/bash
# Start master
ssh -M -S /tmp/batch-%h -N -f user@host
# Multiple operations (all fast)
for i in {1..10}; do
ssh -S /tmp/batch-%h user@host "do_something $i"
done
# Close master
ssh -S /tmp/batch-%h -O exit user@host
Troubleshooting¶
Socket File Issues¶
# Permission denied
chmod 700 ~/.ssh/sockets
# Socket exists but stale
rm ~/.ssh/sockets/user@host-22
# Or
ssh -O exit user@host 2>/dev/null
# Path too long
# Use %C instead of %r@%h-%p
ControlPath ~/.ssh/sockets/%C
Connection Sharing Failed¶
# Check master is running
ssh -O check user@host
# Check socket exists
ls -la ~/.ssh/sockets/
# Debug
ssh -vvv user@host 2>&1 | grep -i multiplex
Master Died, Sessions Affected¶
When master dies, all sessions die. Solutions:
# Use longer ControlPersist
ControlPersist 1h
# Or don't use multiplexing for critical sessions
ssh -o ControlMaster=no user@host
Incompatible Operations¶
Some operations can't share connections:
Security Considerations¶
Socket Permissions¶
# Socket directory must be 700
chmod 700 ~/.ssh/sockets
# Sockets are only usable by owner
ls -la ~/.ssh/sockets/
# srw------- 1 user user 0 Jan 1 12:00 user@host-22
Shared Connection Risks¶
- All sessions share one connection
- If one session has higher privileges, others might access
- Consider separate connections for different security contexts
Disabling for Sensitive Operations¶
Performance Comparison¶
| Scenario | Without Multiplex | With Multiplex |
|---|---|---|
| First connection | ~500ms | ~500ms |
| Second connection | ~500ms | ~50ms |
| 10 quick commands | ~5000ms | ~500ms |
| Git fetch + pull + push | ~1500ms | ~600ms |
Best Practices¶
- Always enable for frequently accessed hosts
- Use ControlPersist to avoid premature closure
- Use %C for socket path (handles long names)
- Create socket directory with proper permissions
- Monitor socket files, clean stale ones
- Disable for sensitive or unstable connections
- Test that configuration works as expected