带有密码提示 C# 的多跳 SSH 问题
Posted
技术标签:
【中文标题】带有密码提示 C# 的多跳 SSH 问题【英文标题】:Trouble with Multi-Hop SSH with password prompt C# 【发布时间】:2020-02-01 08:58:35 【问题描述】:如何将密码传递给不允许我通过命令发送的 SSH 提示?
这不起作用
KeyboardInteractiveAuthenticationMethod DEVICEkauth = new KeyboardInteractiveAuthenticationMethod(DEVICEsshUname);
PasswordAuthenticationMethod DEVICEpauth = new PasswordAuthenticationMethod(DEVICEsshUname, DEVICEsshPass);
我正在尝试进行多跳 ssh 连接,但由于 SSH 协议识别,它在第三跳失败。
Multi hop SSH through SSH.NET in C# 没有解决我的问题 问题,它确实帮助我完成了大部分工作。这个问题试图 进行第三次跳跃,但不起作用。
这是通过 VeloCloud 网关连接到 Velo Edge,然后连接到终端设备(DiGi 传输)
我目前所拥有的:
int sssshTimeOut = 1000;
KeyboardInteractiveAuthenticationMethod VCGkauth = new KeyboardInteractiveAuthenticationMethod(VCGsshUname);
PasswordAuthenticationMethod VCGpauth = new PasswordAuthenticationMethod(VCGsshUname, VCGsshPass);
VCGkauth.AuthenticationPrompt += new EventHandler<AuthenticationPromptEventArgs>(VCGHandleKeyEvent);
SshClient sshVCG = new SshClient(new ConnectionInfo(VCGsshHost, VCGsshPort, VCGsshUname, VCGpauth, VCGkauth));
if (sssshTimeOut != 0)
sshVCG.ConnectionInfo.Timeout = TimeSpan.FromSeconds(sssshTimeOut);
void VCGHandleKeyEvent(Object sender, AuthenticationPromptEventArgs e)
foreach (AuthenticationPrompt prompt in e.Prompts)
if (prompt.Request.IndexOf("Password:", StringComparison.InvariantCultureIgnoreCase) != -1)
prompt.Response = VCGsshPass;
KeyboardInteractiveAuthenticationMethod EDGEkauth = new KeyboardInteractiveAuthenticationMethod(EDGEsshUname);
PasswordAuthenticationMethod EDGEpauth = new PasswordAuthenticationMethod(EDGEsshUname, EDGEsshPass);
EDGEkauth.AuthenticationPrompt += new EventHandler<AuthenticationPromptEventArgs>(EDGEHandleKeyEvent);
void EDGEHandleKeyEvent(Object sender, AuthenticationPromptEventArgs e)
foreach (AuthenticationPrompt prompt in e.Prompts)
if (prompt.Request.IndexOf("Password:", StringComparison.InvariantCultureIgnoreCase) != -1)
prompt.Response = EDGEsshPass;
KeyboardInteractiveAuthenticationMethod DEVICEkauth = new KeyboardInteractiveAuthenticationMethod(DEVICEsshUname);
PasswordAuthenticationMethod DEVICEpauth = new PasswordAuthenticationMethod(DEVICEsshUname, DEVICEsshPass);
DEVICEkauth.AuthenticationPrompt += new EventHandler<AuthenticationPromptEventArgs>(DEVICEHandleKeyEvent);
void DEVICEHandleKeyEvent(Object sender, AuthenticationPromptEventArgs e)
foreach (AuthenticationPrompt prompt in e.Prompts)
if (prompt.Request.IndexOf("password:", StringComparison.InvariantCultureIgnoreCase) != -1)
prompt.Response = DEVICEsshPass;
Console.WriteLine("Connecting to VCG: "+ VCGsshHost + "");
sshVCG.Connect();
Console.WriteLine("Sending ARP command to VCG: " + VCGsshHost + "");
var commandVCG = sshVCG.CreateCommand("arp -n");
var resultVCG = commandVCG.Execute();
Console.WriteLine(resultVCG);
Console.WriteLine("");
Console.WriteLine("");
Console.WriteLine("Forwarding SSH connection to Edge: " + EDGEsshHost + "");
var portVCG = new ForwardedPortLocal("127.0.0.1", uintVCGsshPort, EDGEsshHost, uintEDGEsshPort);
sshVCG.AddForwardedPort(portVCG);
portVCG.Start();
if (portVCG.IsStarted)
Console.WriteLine("Forwarding SSH connection to Edge: Started!");
else
Console.WriteLine("Forwarding SSH connection to Edge: seems to have failed.....");
SshClient sshEDGE = new SshClient(new ConnectionInfo(portVCG.BoundHost, (int)portVCG.BoundPort, EDGEsshUname, EDGEpauth, EDGEkauth));
sshEDGE.Connect();
Console.WriteLine("Sending ARP command to Edge: " + EDGEsshHost + "");
var commandEDGE = sshEDGE.CreateCommand("arp -n");
var resultEDGE = commandEDGE.Execute();
Console.WriteLine(resultEDGE);
Console.WriteLine("");
Console.WriteLine("");
Console.WriteLine("Forwarding SSH connection to EndDevice: " + DEVICEsshHost + "");
var portEDGE = new ForwardedPortLocal("127.0.0.1", uintEDGEsshPort, DEVICEsshHost, uintDEVICEsshPort);
sshEDGE.AddForwardedPort(portEDGE);
//sshVCG.AddForwardedPort(portEDGE);
portEDGE.Start();
if (portEDGE.IsStarted)
Console.WriteLine("Forwarding SSH connection to End Device: Started!");
else
Console.WriteLine("Forwarding SSH connection to End Device: seems to have failed.....");
SshClient sshDEVICE = new SshClient(new ConnectionInfo(portEDGE.BoundHost, (int)portEDGE.BoundPort, DEVICEsshUname, DEVICEpauth, DEVICEkauth));
//SshClient sshDEVICE = new SshClient(new ConnectionInfo(portVCG.BoundHost, (int)portVCG.BoundPort, DEVICEsshUname, DEVICEpauth, DEVICEkauth));
//SshClient sshDEVICE = new SshClient(portEDGE.BoundHost, (int)portEDGE.BoundPort, DEVICEsshUname, DEVICEsshPass);
sshDEVICE.Connect();
Console.WriteLine("");
Console.WriteLine("");
Console.WriteLine("Sending HW command to End Device: " + DEVICEsshHost + "");
var commandDEVICE = sshDEVICE.CreateCommand("hw");
var resultDEVICE = commandDEVICE.Execute();
Console.WriteLine(resultDEVICE);
我希望 SSH 连接到 VGC,然后是 Edge,然后是终端设备,然后运行命令。
如果我通过 Plink 执行此过程,则此过程会变得很远......
错误:
Renci.SshNet.Common.SshConnectionException: '服务器响应没有 包含 SSH 协议标识。'
链接
Plink Window 1
C:\Users\ncarter>Plink.exe -ssh -L 4000:xxx.xxx.xxx.2:22 xxxxxxx@xx.xx.xxx.85 -P 10444
Using username "xxxxxxx".
xxxxxx@xx.xx.xxx.85's password:
Welcome to Velocloud VCG (GNU/Linux 3.13.0-160-generic x86_64)
* Documentation: https://help.ubuntu.com/
Get cloud support with Ubuntu Advantage Cloud Guest:
http://www.ubuntu.com/business/services/cloud
Last login: Fri Oct 11 18:44:59 2019 from xxx.xxx.x.42
]0;xxxxxx@xxxx-xxlab: ~xxxxxx@xxxx-xxlab:~$
Plink Window 2
C:\Users\ncarter>Plink.exe -ssh -L 8001:xxx.xxx.xx.1:xxx97 xxxx@127.0.0.1 -P 4000
Using username "xxxxx".
Using keyboard-interactive authentication.
Password:
BusyBox v1.23.2 (2018-10-19 16:11:09 UTC) built-in shell (ash)
_ __ __ ________ __
| | / /__ / /___ / ____/ /___ __ ______/ /
| | / / _ \/ / __ \/ / / / __ \/ / / / __ /
| |/ / __/ / /_/ / /___/ / /_/ / /_/ / /_/ /
|___/\___/_/\____/\____/_/\____/\__,_/\__,_/
VeloCloud Inc.
------------------------------------------------
velocloud Test-Edge-1:~# [6narp
Address HWtype HWaddress Flags Mask Iface
192.168.11.1 ether 00:04:2d:07:b9:1f C ge4
xx.xxx.xxx.227 ether 50:7b:9d:35:1d:12 C br-network1
SIP-xxxx.xxx ether 80:5e:c0:29:61:ad C br-network1
198.19.0.33 ether 00:50:56:91:ff:2e C ge3
198.19.0.1 ether 90:6c:ac:bb:c9:8c C ge3
198.19.0.32 ether 00:50:56:91:7f:da C ge3
xxx.xxx.xx.4 ether 50:7b:9d:35:1d:12 C br-network1
velocloud Test-Edge-1:~# [6nssh -p xxx97 xxxxxx@192.168.11.1 -t 'hw'
xxxxxx@192.168.11.1's password:
SN:506143
Welcome. Your access level is SUPER
ss506143>
Serial Number: 506143
HW Rev: 3205b
MAC 0: 00042d07b91f
MAC 1: 00042df7b91f
MAC 2: 00042de7b91f
MAC 3: 00042dd7b91f
MAC 4: 00042dc7b91f
MAC 5: 000000000000
MAC 6: 000000000000
Model: WR11
Part#: WR11-L800-DE1-SU
RAM: 64 MB
OK
ss506143>Connection to 192.168.11.1 closed.
velocloud Test-Edge-1:~# [6n
【问题讨论】:
见Multi hop SSH through SSH.NET in C# 我在发布我的问题之前检查了这一点,该解决方案没有正确验证 SSH 连接。它在第一次连接时失败。同样,SSH 连接(两者)都需要键盘交互式身份验证。也许我做错了什么? 好的,我知道你需要使用键盘认证。但我相信你的键盘验证码是正确的。在我看来,这是端口转发代码。所以使用我的代码进行端口转发,只需将密码认证替换为键盘交互认证即可。 @MartinPrikryl,谢谢,就是这样!我需要使用 portVCG.BoundHost 和 portVCG.BoundPort 变量,它们替换了 EDGEsshHost 和 EDGEsshPort 变量。 这条线现在的样子 SshClient sshEDGE = new SshClient(new ConnectionInfo(portVCG.BoundHost, (int)portVCG.BoundPort, EDGEsshUname, EDGEpauth, EDGEkauth));错过这个我觉得很愚蠢! 我想我需要将新端口添加到第一跳,所以它看起来像 sshVCG.AddForwardedPort(portEDGE);。我会尽快对此进行测试。 【参考方案1】:我找到了适合我具体情况的答案:
我只能通过 SSH 连接到 VCG(第一个设备),然后通过 SSH 隧道(转发)到 Edge(第二个设备),最后只需在 Edge 上运行 SSH 命令将命令传递给DiGi(Third Device),然后听触发器输入密码。
我所做的是创建一个名为“input”的 PipeStream,然后启动一个 shell 使用“输入”管道流作为外壳到称为“外壳”的边缘 输入。然后我在 “输入”管道流。
然后我将我的 SSH 命令发送到 sshEDGE shell 并监听 PipeStream 上的单词“密码”并传入所需的密码。
注意 while 循环,我将每个循环的位置重置为 0。
然后我正在监听“关闭”这个词或指定的超时时间 知道何时退出第二个 while 循环。
然后我 StreamRead '输出'并将其分配给我的'ssdeviceResponse' var (reader.ReadToEnd();).
ssdeviceResponse = "";
uint uintssvcgPort = (uint)(int)ssvcgPort;
uint uintEDGEsshPort = (uint)(int)ssedgePort;
uint uintssdevicePort = (uint)(int)ssdevicePort;
int sssshTimeOut = 1000;
KeyboardInteractiveAuthenticationMethod VCGkauth = new KeyboardInteractiveAuthenticationMethod(ssvcgUN);
PasswordAuthenticationMethod VCGpauth = new PasswordAuthenticationMethod(ssvcgUN, ssvcgPass);
VCGkauth.AuthenticationPrompt += new EventHandler<AuthenticationPromptEventArgs>(VCGHandleKeyEvent);
void VCGHandleKeyEvent(Object sender, AuthenticationPromptEventArgs e)
foreach (AuthenticationPrompt prompt in e.Prompts)
if (prompt.Request.IndexOf("Password:", StringComparison.InvariantCultureIgnoreCase) != -1)
prompt.Response = ssvcgPass;
KeyboardInteractiveAuthenticationMethod EDGEkauth = new KeyboardInteractiveAuthenticationMethod(ssedgeUN);
PasswordAuthenticationMethod EDGEpauth = new PasswordAuthenticationMethod(ssedgeUN, ssedgePass);
EDGEkauth.AuthenticationPrompt += new EventHandler<AuthenticationPromptEventArgs>(EDGEHandleKeyEvent);
void EDGEHandleKeyEvent(Object sender, AuthenticationPromptEventArgs e)
foreach (AuthenticationPrompt prompt in e.Prompts)
if (prompt.Request.IndexOf("Password:", StringComparison.InvariantCultureIgnoreCase) != -1)
prompt.Response = ssedgePass;
SshClient sshVCG = new SshClient(new ConnectionInfo(ssvcgAddress, ssvcgPort, ssvcgUN, VCGpauth, VCGkauth));
if (sssshTimeOut != 0)
sshVCG.ConnectionInfo.Timeout = TimeSpan.FromSeconds(sssshTimeOut);
sshVCG.Connect();
var portVCG = new ForwardedPortLocal("127.0.0.1", ssedgeAddress, uintEDGEsshPort);
sshVCG.AddForwardedPort(portVCG);
portVCG.Start();
SshClient sshEDGE = new SshClient(new ConnectionInfo(portVCG.BoundHost, (int)portVCG.BoundPort, ssedgeUN, EDGEpauth, EDGEkauth));
sshEDGE.Connect();
var input = new PipeStream();
var streamWriter = new StreamWriter(input) AutoFlush = true ;
Stream outPut = new MemoryStream();
var outPutEXT = new MemoryStream();
var shell = sshEDGE.CreateShell(input, outPut, outPutEXT);
shell.Start();
streamWriter.WriteLine("ssh -p " + ssdevicePort + " " + ssdeviceUN + "@" + ssdeviceAddress + " -t '" + ssdeviceCommand + "'");
int Count = 0;
while (input.CanRead)
outPut.Position = 0;
StreamReader reader1 = new StreamReader(outPut);
string i = reader1.ReadToEnd();
if (i.Contains("password"))
streamWriter.WriteLine(ssdevicePass);
break;
while (input.CanRead)
Count = Count + 1;
Thread.Sleep(2000); //Added this because the shell would close if I read to fast, weird...
outPut.Position = 0;
StreamReader reader1 = new StreamReader(outPut);
string i = reader1.ReadToEnd();
if (i.Contains("closed"))
break;
else if (Count >= 10)
//Timeout
break;
outPut.Position = 0;
StreamReader reader = new StreamReader(outPut);
ssdeviceResponse = reader.ReadToEnd();
//Console.WriteLine(ssdeviceResponse);
//Console.WriteLine("!!!END!!!");
streamWriter.Dispose();
reader.Dispose();
outPutEXT.Dispose();
outPut.Dispose();
【讨论】:
以上是关于带有密码提示 C# 的多跳 SSH 问题的主要内容,如果未能解决你的问题,请参考以下文章