【更新2021-4-25】如何处理PoshSSH 连接主机时的"New-SSHSession : Key exchange negotiation failed."故障
背景:
PoshSSH是一款在PowerShell下非常流行的SSH命令行客户端,可以通过https://www.powershellgallery.com/packages/Posh-SSH 获取。
近期笔者在使用这款客户端完成批量任务下发的时候遇到了部分主机链接失效的问题,于此同时使用独立客户端工具putty尝试连接却是正常的,证明问题存在于客户端自身。
图 1连接意外的报错信息
PS C:\Users\zhouguanyu> New-SSHSession-ComputerName ??.??.??.??
位于命令管道位置 1 的 cmdlet New-SSHSession
请为以下参数提供值:
(请键入 !? 以查看帮助。)
Credential
New-SSHSession : Key exchange negotiation failed.
所在位置行:1 字符: 1
+ New-SSHSession -ComputerName ??.??.??.??
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : SecurityError: (Renci.SshNet.SshClient:SshClient) [New-SSHSession],SshConnectionException
+ FullyQualifiedErrorId : SSH.NewSshSession
处理:
首先使用“Key exchange negotiation failed.”作为关键字检索发现有github上的一个issuse315[1] ,和我的症状一致,所以尝试了更新PoshSSH的版本为2.3.0 后测试依旧存在问题,联想到这些出现故障链接的主机曾经都有重装过系统,莫非有些主机特征被记录在SSH的客户端里,但是因为PoshSSH是PowerShell的一个模块,本身也没有配置项记录的文件。
PS C:\Program Files\WindowsPowerShell\Modules\Posh-SSH\2.3.0> tree /F
文件夹 PATH 列表
C:.
│ Posh-SSH.psd1
│ Posh-SSH.psm1
│ PoshSSH.dll
│ PoshSSH.pdb
│
├─Assembly
│ Ionic.Zlib.dll
│ Newtonsoft.Json.dll
│ Renci.SshNetPS.dll
│
├─en-US
│ Posh-SSH-help.xml
│ Posh-SSH.psm1-Help.xml
│ PoshSSH.dll-help.xml
│
└─Format
Renci.SshNet.Sftp.SftpFile.Format.ps1xml
Renci.SshNet.SshCommand.Format.ps1xml
SFTPSession.Format.ps1xml
SSHSession.Format.ps1xml
请出 Mark Russinovich 大师的 Process Monitor 抓一下系统包,了解一下PoshSSH在运行的时候都去系统的那些窜过门。
图 2使用主机IP作为关键字进行检索
确实可以发现对“注册表”和“TCP链接”的两种操作,同时注册表的详细信息内可以看到他查询了主机,通过删除该主机在注册表中的键值,再次链接问题得到解决。
图 3证据支持PoshSSH会利用注册表进行远程主机指纹的记录
存下历史链接主机的指纹可以加速下次链接进入的速度,但是PoshSSH并没有考虑到系统renew指纹后的再次连接的问题。
结论:
因为笔者还需要继续操作脚本,并避免下次遇此问题被回退,可以在脚本里面加一条清理“HKEY_CURRENT_USER\Software\PoshSSH”键值的语句。
reg delete HKEY_CURRENT_USER\Software\PoshSSH /f
更新:
新版PoshSSH新版已经有命令支持删除信任主机的命令(Remove-SSHTrustedHost),因此批量或单点操作的时候可以使用。
使用方式可以配合罗列信任主机的命令(Get-SSHTrustedHost)一同操作更加高效。
删除所有已经记录的信任主机(等同于 reg delete HKEY_CURRENT_USER\Software\PoshSSH /f )
Get-SSHTrustedHost | Remove-SSHTrustedHost
-=EOB=-