在 Hacker News 的讨论中,有用户报告了一个令人困惑的现象:在使用 SSH 进行交互式会话时,一次普通的按键操作在 tcpdump 或 Wireshark 中会呈现出近百个数据包的记录。这一现象在高速网络中尤其明显,引发了关于带宽占用与延迟的担忧。要理解这一行为,我们需要深入 SSH 协议的二进制报文层(Binary Packet Protocol),并结合近年来引入的安全机制来分析其根源。
RFC 4253 二进制报文协议的固定开销
SSH 传输层协议(RFC 4253)在第六节定义了「二进制报文协议」的严格结构。每一个 SSH 数据包都遵循以下固定格式:首先是 4 字节的 packet_length 字段,用于声明后续数据的长度;接着是 1 字节的 padding_length,用于指明随机填充字节的长度;然后是变长的 payload(实际的应用数据,如按键内容);随后是最少 4 字节的随机填充(random padding);最后是可选的 MAC(消息认证码)字段。
这种结构导致了显著的协议开销。以典型的 HMAC-SHA1 配置为例,单个数据包在不含实际负载时的基础开销约为 4(长度)+ 1(填充长度)+ 4(最小填充)+ 20(HMAC-SHA1)= 29 字节。当使用块加密算法(如 CBC 模式)时,为了满足块对齐要求,还需要额外的填充字节。这意味着即使用户只是按下一个字母「a」(1 字节负载),SSH 客户端也必须将其封装进一个包含完整加密、认证信息的报文中发送。
更为关键的是,为了提供可靠的数据完整性保护,MAC 的计算发生在加密之前:服务器在收到报文后,需要先解密验证 MAC,再将 payload 交付给上层应用。这个过程在每一次按键时都会完整执行,确保了安全性,但也意味着交互式流量无法像批量传输那样进行高效合并。
TCP_NODELAY 与交互式会话的包量放大
在传统的 SSH 交互场景中,TCP_NODELAY 选项扮演了重要角色。由于 SSH 是一种交互式协议,对延迟极为敏感,客户端通常会主动禁用 Nagle 算法。Nagle 算法原本的设计目的是通过合并小数据包来减少网络中的小报文数量,但这会引入最多 200 毫秒的延迟,对于命令行操作而言是不可接受的。因此,SSH 客户端默认设置 TCP_NODELAY,确保每一个按键数据都能立即发送。
当 TCP_NODELAY 与 SSH 的单次按键单次封装规则结合时,即便是最简单的字符输入,也会产生一个独立的 IP 包。对于远程桌面、游戏或需要高频按键的应用场景,这种「按键即发送」的策略虽然保证了响应速度,但也意味着网络层面的包率(Packet Per Second)会显著高于批量数据传输场景。
OpenSSH 9.5 的键盘时序混淆机制
上述协议开销虽然存在,但在传统配置下,单次按键通常只对应 1-2 个 SSH 报文(客户端发送与服务器回显)。 Hacker News 讨论中提到的「近百个数据包」现象,实际上源于 OpenSSH 9.5(2023 年发布)引入的一项安全功能:键盘时序混淆(ObscureKeystrokeTiming,或称为 keystroke timing obfuscation)。
这一机制的设计初衷是防范时序攻击(Timing Attack)。在极端情况下,攻击者如果能够监听网络流量,有可能通过分析按键之间的时间间隔来推断用户输入的内容,例如密码。为了消除这种时间信号与输入内容之间的相关性,OpenSSH 在检测到低流量的交互式会话时,会持续发送「干扰」报文(chaff packets),即 SSH2_MSG_PING 类型消息。这些虚假流量会淹没真实按键的时间特征,使得外部观察者难以区分哪些包对应实际的按键操作。
根据社区反馈与测试,该功能默认以约 20 毫秒的固定间隔发送干扰流量。当用户进行一次按键操作时,系统不仅发送真实的按键报文,还会按照固定节奏发送数十甚至上百个干扰包,直到会话恢复正常流量状态。这解释了为何在抓包工具中会观察到「一次按键对应近百个数据包」的现象 —— 其中大部分是安全机制产生的「噪声」。
工程权衡:安全性的代价与配置选项
键盘时序混淆机制在安全性与性能之间做出了明确的取舍。对于安全性要求极高的场景(如通过 SSH 访问核心基础设施),这一机制提供了额外的防护层,即使攻击者能够监听网络流量,也难以提取有意义的时序信息。然而,对于带宽受限的环境(如移动网络、卫星链路)或对延迟极度敏感的应用(如通过 SSH 玩在线游戏),这种持续的干扰流量会造成可感知的性能下降。
好消息是,最新的 OpenSSH 版本已经响应社区反馈,提供了禁用该功能的选项。通过在 /etc/ssh/sshd_config 中设置 ObscureKeystrokeTiming no,或者在客户端配置中调整相关参数,运维人员可以根据实际需求在安全性与性能之间找到平衡点。这一配置项的引入,体现了开源项目在面对用户实际痛点时的快速响应能力。
从协议设计的角度来看,SSH 在过去二十余年间始终保持着相对稳定的核心报文结构,而键盘时序混淆则是一个后加的安全增强层。理解这两者的区别,有助于工程师在排查网络问题或进行性能调优时准确定位根因。
资料来源:RFC 4253 协议规范、OpenSSH 9.5 release notes、Hacker News 技术讨论区。