When working with SSH connections, you might notice that every keystroke is immediately sent to the remote server. This default behavior originates from the terminal's character-at-a-time mode, which can cause noticeable lag when working on high-latency connections. The underlying mechanism uses the POSIX terminal interface in canonical mode.
Interestingly, this behavior mirrors how classic Telnet protocols handle input. Just like Telnet sends each character as it's typed, SSH inherits similar characteristics when dealing with interactive sessions. While this provides immediate feedback in local scenarios, it becomes problematic over WAN connections.
Most modern SSH clients offer configuration options to modify this behavior. Here's how to implement line buffering in popular clients:
# OpenSSH configuration (~/.ssh/config)
Host *
# Enable line buffering (sends on Enter)
SendEnv LC_LINE_BUFFERING
# Alternative method using escape characters
EscapeChar ~
For administrators who control the SSH server, these options in /etc/ssh/sshd_config
can help:
# Disable immediate echo
UsePAM no
# Adjust flow control
TCPKeepAlive yes
# Optimize for high-latency
ClientAliveInterval 60
For complete control over input timing, you can wrap your SSH session in an expect script:
#!/usr/bin/expect -f
spawn ssh user@host
# Wait for prompt
expect "$ "
# Configure line editing
send "stty -echo -icanon\r"
interact {
\r {send "\r"; expect "$ "}
\t {send "\t"}
}
The effectiveness of these solutions varies across shells:
- Bash: Responds well to
stty -icanon
settings - Zsh: May require additional
zle
configuration - Windows SSH: Needs Putty/Windows Terminal specific adjustments
Many developers experience frustrating typing delays when working over SSH connections, especially with high-latency networks. The default behavior where SSH transmits each keystroke immediately creates noticeable lag during interactive sessions.
SSH clients typically operate in one of two modes:
- Character-at-a-time mode: Default behavior (what we want to change)
- Line-buffered mode: Data only sent after Enter/Tab
The most effective solution is to configure your SSH client to use line buffering:
For OpenSSH Clients
ssh -o "StrictHostKeyChecking=no" -o "ConnectionAttempts=3" \
-T user@host.example.com bash --noprofile --norc
Alternatively, add this to your ~/.ssh/config
:
Host *
StrictHostKeyChecking no
ConnectionAttempts 3
RequestTTY force
RemoteCommand bash --noprofile --norc
If you control the server, consider these improvements:
# In /etc/ssh/sshd_config
UseDNS no
GSSAPIAuthentication no
Terminal multiplexers can help mitigate the issue:
ssh user@host.example.com -t 'tmux new-session -A -s main'
Measure your typing latency before and after changes:
time ssh user@host.example.com "echo 'latency test'"
For interactive testing, try typing rapidly in vim or another sensitive editor to feel the difference.
If problems continue:
- Check network latency with
ping
andtraceroute
- Experiment with different cipher algorithms
- Consider compression for high-latency links