paramiko Rekeying过程触发EOFError导致连接关闭如何解决
问题现象
密钥重协商(Rekeying)完成后,_read_all接收到长度为0的字符串并关闭连接,抛出EOFError异常,相关调试日志与栈追踪如下:
DEB [20211007-15:13:46.331] thr=2 paramiko.transport.sftp: [chan 0] open(b'v1_full_25127.zip', 'rb') -> 31 [2021-10-07 15:13:46,331] {sftp.py:158} DEBUG - [chan 0] open(b'v1_full_25127.zip', 'rb') -> 31 DEB [20211007-15:34:48.572] thr=1 paramiko.transport: Rekeying (hit 32846 packets, 536876792 bytes received) [2021-10-07 15:34:48,572] {packet.py:588} DEBUG - Rekeying (hit 32846 packets, 536876792 bytes received) DEB [20211007-15:34:48.992] thr=1 paramiko.transport: kex algos:['diffie-hellman-group14-sha1', 'diffie-hellman-group1-sha1', 'diffie-hellman-group-exchange-sha1', 'diffie-hellman-group-exchange-sha256'] server key:['ssh-rsa'] client encrypt:['aes128-cbc', 'aes192-cbc', 'aes256-cbc', '3des-cbc', 'blowfish-cbc', 'aes128-ctr', 'aes192-ctr', 'aes256-ctr'] server encrypt:['aes128-cbc', 'aes192-cbc', 'aes256-cbc', '3des-cbc', 'blowfish-cbc', 'aes128-ctr', 'aes192-ctr', 'aes256-ctr'] client mac:['hmac-sha1', 'hmac-md5', 'hmac-sha1-96', 'hmac-md5-96', 'hmac-sha256', 'hmac-sha256@ssh.com'] server mac:['hmac-sha1', 'hmac-md5', 'hmac-sha1-96', 'hmac-md5-96', 'hmac-sha256', 'hmac-sha256@ssh.com'] client compress:['none', 'zlib'] server compress:['none', 'zlib'] client lang:[''] server lang:[''] kex follows?False [2021-10-07 15:34:48,992] {transport.py:1819} DEBUG - kex algos:['diffie-hellman-group14-sha1', 'diffie-hellman-group1-sha1', 'diffie-hellman-group-exchange-sha1', 'diffie-hellman-group-exchange-sha256'] server key:['ssh-rsa'] client encrypt:['aes128-cbc', 'aes192-cbc', 'aes256-cbc', '3des-cbc', 'blowfish-cbc', 'aes128-ctr', 'aes192-ctr', 'aes256-ctr'] server encrypt:['aes128-cbc', 'aes192-cbc', 'aes256-cbc', '3des-cbc', 'blowfish-cbc', 'aes128-ctr', 'aes192-ctr', 'aes256-ctr'] client mac:['hmac-sha1', 'hmac-md5', 'hmac-sha1-96', 'hmac-md5-96', 'hmac-sha256', 'hmac-sha256@ssh.com'] server mac:['hmac-sha1', 'hmac-md5', 'hmac-sha1-96', 'hmac-md5-96', 'hmac-sha256', 'hmac-sha256@ssh.com'] client compress:['none', 'zlib'] server compress:['none', 'zlib'] client lang:[''] server lang:[''] kex follows?False DEB [20211007-15:34:48.992] thr=1 paramiko.transport: Kex agreed: diffie-hellman-group-exchange-sha256 [2021-10-07 15:34:48,992] {transport.py:1819} DEBUG - Kex agreed: diffie-hellman-group-exchange-sha256 DEB [20211007-15:34:48.992] thr=1 paramiko.transport: HostKey agreed: ssh-rsa [2021-10-07 15:34:48,992] {transport.py:1819} DEBUG - HostKey agreed: ssh-rsa DEB [20211007-15:34:48.992] thr=1 paramiko.transport: Cipher agreed: aes128-ctr [2021-10-07 15:34:48,992] {transport.py:1819} DEBUG - Cipher agreed: aes128-ctr DEB [20211007-15:34:48.993] thr=1 paramiko.transport: MAC agreed: hmac-sha1 [2021-10-07 15:34:48,993] {transport.py:1819} DEBUG - MAC agreed: hmac-sha1 DEB [20211007-15:34:48.993] thr=1 paramiko.transport: Compression agreed: none [2021-10-07 15:34:48,993] {transport.py:1819} DEBUG - Compression agreed: none DEB [20211007-15:34:49.256] thr=1 paramiko.transport: Got server p (2048 bits) [2021-10-07 15:34:49,256] {transport.py:1819} DEBUG - Got server p (2048 bits) DEB [20211007-15:34:49.567] thr=1 paramiko.transport: Switch to new keys ... [2021-10-07 15:34:49,567] {transport.py:1819} DEBUG - Switch to new keys ... DEB [20211007-15:42:46.628] thr=1 paramiko.transport: [chan 0] EOF sent (0) [2021-10-07 15:42:46,628] {channel.py:1212} DEBUG - [chan 0] EOF sent (0) DEB [20211007-15:42:46.629] thr=2 paramiko.transport.sftp: [chan 0] close(31) [2021-10-07 15:42:46,629] {sftp.py:158} DEBUG - [chan 0] close(31) Traceback (most recent call last): File "/home/python3.8/site-packages/paramiko/sftp_client.py", line 843, in _read_response t, data = self._read_packet() File "/home/python3.8/site-packages/paramiko/sftp.py", line 201, in _read_packet x = self._read_all(4) File "/home/python3.8/site-packages/paramiko/sftp.py", line 188, in _read_all raise EOFError() EOFError
根因说明
该问题是paramiko旧版本的已知缺陷,密钥重协商完成后,SFTP通道的读状态未正确同步,导致_read_all方法读取到空字节后直接抛出EOFError,多出现于大文件传输场景下触发默认重协商阈值时。
解决方案
- 优先升级paramiko到2.9及以上版本,该版本已修复重协商后的通道状态同步问题,执行
pip install --upgrade paramiko即可解决绝大多数同类问题。 - 若环境限制无法升级版本,可手动调高重协商阈值,避免大文件传输过程中触发重协商:初始化Transport对象后添加配置
transport.rekey_threshold = 2 * 1024 * 1024 * 1024,将重协商触发阈值调整为2G,适配大文件传输需求。 - 临时兜底方案可给SFTP读操作增加异常捕获逻辑,捕获
EOFError后检查传输通道是否存活,若通道正常可重建SFTP会话续传文件。
内容的提问来源于stack exchange,提问作者zza
相关产品推荐
相关产品推荐

