Troubleshooting SSH Performance Issues: Causes and Solutions for Latency and Lag


2 views

When your SSH session exhibits the following behaviors, you're likely dealing with performance issues:

  • Keystroke-to-display delays (echo latency)
  • Character bunching (multiple characters appearing at once)
  • Unresponsive terminal during text input
  • Intermittent freezes followed by rapid output

Network conditions are the most common culprits for SSH sluggishness:

# Check network latency to remote host
ping remote.example.com
traceroute remote.example.com

# Test for packet loss (run for 30+ seconds)
mtr --report remote.example.com

TCP Window Scaling Issues: Mismatched window sizes can cause throughput problems. Check with:

# View current TCP window settings
cat /proc/sys/net/ipv4/tcp_window_scaling
cat /proc/sys/net/ipv4/tcp_rmem
cat /proc/sys/net/ipv4/tcp_wmem

Modify your SSH client configuration (~/.ssh/config):

Host *
    ServerAliveInterval 60
    ServerAliveCountMax 3
    TCPKeepAlive yes
    Compression yes
    Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com
    MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com

Adjust your local terminal settings:

# For Linux terminals
infocmp $TERM | grep -E 'key_(up|down|left|right|home|end)'

On the remote server, consider these optimizations:

# Add to /etc/ssh/sshd_config
UseDNS no
GSSAPIAuthentication no
LoginGraceTime 30s
MaxStartups 10:30:60

For persistent issues, gather detailed diagnostics:

# Client-side debugging
ssh -vvv user@host

# Server-side logging
journalctl -u sshd -f

# Network capture (requires root)
tcpdump -i eth0 -s0 -w ssh-capture.pcap port 22

For high-latency connections, consider alternatives:

# Mosh (mobile shell) installation
sudo apt install mosh
mosh user@host --predict=always

When working with remote systems via SSH, terminal latency can significantly impact productivity. The symptoms you're describing - delayed character echo and buffered output - typically indicate underlying network or configuration issues rather than a problem with SSH itself.

# Check basic network latency:
ping remote_host
traceroute remote_host

# Test for packet loss:
mtr --report remote_host

High latency (>100ms) or packet loss (>1%) will cause noticeable typing delays. Satellite connections or congested VPNs are common offenders. Consider:

  • Using compression: ssh -C user@host
  • Tweaking MTU settings
  • Testing alternative ports (ISP might throttle default port 22)
# Common performance-related settings in /etc/ssh/sshd_config:
UseDNS no
GSSAPIAuthentication no
LoginGraceTime 30

Particularly on older systems, DNS lookups and GSSAPI can introduce significant delays. The UseDNS no directive prevents reverse DNS lookups for each connection.

# ~/.ssh/config example for latency-sensitive connections:
Host myremote
    HostName remote.example.com
    User myuser
    Compression yes
    ServerAliveInterval 60
    TCPKeepAlive yes
    ControlMaster auto
    ControlPath ~/.ssh/sockets/%r@%h-%p
    ControlPersist 4h

The ControlMaster setup maintains a persistent connection, eliminating the TCP handshake overhead for subsequent sessions.

Modern terminal emulators (iTerm2, Kitty, Alacritty) offer GPU-accelerated rendering. For slow connections:

  • Disable fancy features like ligatures
  • Set a lower frame rate
  • Use simpler fonts
# Benchmark cipher performance:
ssh -Q cipher | xargs -I{} sh -c 'echo -n "{}: "; \
time ssh -c {} user@host "exit" 2>&1 | grep real'

On high-latency networks, chacha20-poly1305 often outperforms AES. Consider forcing modern protocols:

Host *
    Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com
    HostKeyAlgorithms ssh-ed25519
    KexAlgorithms curve25519-sha256@libssh.org

For extremely poor connections, consider:

# Mosh (Mobile Shell) - handles intermittent connectivity better:
mosh user@remote_host

# tmux session recovery:
ssh user@remote_host -t 'tmux attach || tmux new'

Mosh uses UDP and predictive echo to maintain responsiveness even with 30% packet loss.

# 1. Isolate the issue:
ssh -vvv user@host 2> ssh_debug.log

# 2. Check where delays occur:
time ssh user@host 'exit'

# 3. Test with minimal configuration:
ssh -F /dev/null user@host

# 4. Compare with localhost:
ssh localhost