如何在 C# 中对 plink 的缓存关键问题回答“是”
我正在使用 c# 中的 plink 连接到 Linux 服务器并运行一些程序。 C# 控制台程序和 plink.exe 都在同一台 Windows 计算机上。
问题是当我第一次连接到 Linux 服务器时,plink 询问我是否要接受并存储来自 Linux 服务器的 SSH 密钥。我总是想回答“是”,因为所有服务器都在我的局域网中,并且不存在安全问题。
我正在使用 c# Process 类型,将正确的参数传递给 plink,重定向输出并启动。现在的问题是当plink提示时,process.StandardOutput.ReadToEnd();挂起,我无法确定 plink 是否提示我接受密钥或实际登录到 Linux 服务器。
string output = string.Empty;
string error = string.Empty;
string arguments = @" -ssh -pw password [email protected] ./Install_xxx.bin";
using (Process process = new Process())
{
ProcessStartInfo psi = new ProcessStartInfo();
psi.FileName = "plink";
psi.Arguments = arguments;
psi.ErrorDialog = false;
psi.UseShellExecute = false;
psi.RedirectStandardError = true;
psi.RedirectStandardInput = true;
psi.RedirectStandardOutput = true;
psi.CreateNoWindow = true;
process.StartInfo = psi;
process.Start();
output = process.StandardOutput.ReadToEnd();
error = process.StandardError.ReadToEnd();
}
谢谢
I'm using plink from c# to connect to Linux servers and run some programs. Both the c# console program and the plink.exe are on the same windows machine.
The problem is when I connect to a Linux server for the first time, plink asks me if I want to accept and store the SSH key from the Linux server. I always want to respond yes to this because all the servers are in my LAN and there is no security issue.
I'm using c# Process type, pass the correct argument to plink, redirect the output and start. Now the problem is when plink prompts, the process.StandardOutput.ReadToEnd(); hangs and I have no way of figuring out whether I'm prompted by plink to accept the key or actually logged into the Linux server.
string output = string.Empty;
string error = string.Empty;
string arguments = @" -ssh -pw password [email protected] ./Install_xxx.bin";
using (Process process = new Process())
{
ProcessStartInfo psi = new ProcessStartInfo();
psi.FileName = "plink";
psi.Arguments = arguments;
psi.ErrorDialog = false;
psi.UseShellExecute = false;
psi.RedirectStandardError = true;
psi.RedirectStandardInput = true;
psi.RedirectStandardOutput = true;
psi.CreateNoWindow = true;
process.StartInfo = psi;
process.Start();
output = process.StandardOutput.ReadToEnd();
error = process.StandardError.ReadToEnd();
}
Thanks
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
流程文档中解释了您的死锁问题。当进程等待输入时,它无法关闭标准输入,因此它将阻塞。 StandardOutput 将不会关闭,因为进程仍在等待来自 stdin 的输入:死锁。
您可以使用异步 api 逐行读取,也可以将另一个线程用于其他流。
Your Deadlock problem is explained in the Process docu. When the process waits for input it cannot close stdin so it will block. StandardOutput will not be closed because the process is still waiting for your input from stdin: Deadlock.
You can either use the asynchronous apis to read line by line or you use for the other stream another thread.
与其使用外部可执行文件来建立 SSH 连接,为什么不使用 SSH 库并通过代码来完成(更可靠)呢?
sharpSsh (最新版本)是 Jsch(一个 BSD 许可的 Java 库)的 C# 端口。我在我的 C# 项目中非常成功地使用了它;您将能够以编程方式处理 SSH 连接的所有方面,包括密钥协商。
Instead of using an external executable to make your SSH connection, why not use a SSH library and do it (more reliably) through code?
sharpSsh (most recent version here) is a C# port of Jsch, a BSD-licensed Java library. I've used it in my C# projects very successfully; you'll be able to programmatically handle all aspects of the SSH connection, including the key negotiation.
为了通过 PLINK 无缝连接到远程服务器,第一次和后续时间,您必须手动协调 SSH 密钥。也就是说,使用 PUTTYGEN 创建 PLINK 将使用的 .ppk 私钥文件,并将相应的公钥预先存储在服务器上的
~/.ssh/authorized_keys
文件中。您还需要协调 sshd 的主机密钥,因此使用 PUTTYGEN 在
/etc/ssh
下生成一组私钥文件ssh_host_rsa_key
和ssh_host_dsa_key
(查看现有文件以确定要导出到的密钥格式),然后运行 ssh-keygen -y -f /etc/ssh/ssh_host_rsa_key > /etc/ssh/ssh_host_rsa_key.pub 创建相应的公钥文件(创建ssh_host_dsa_key.pub
文件执行相同操作)。如果您想要 PLINK 到多个服务器,并且不介意使用相同的密钥连接到所有服务器(这将取决于您本地的 IT 安全策略),那么只需将相同的密钥文件复制到每台服务器上。
然后,在使用 PLINK 的 Windows 计算机上,使用 PUTTY 或 PLINK 手动连接到任何服务器,并以交互方式接受主机密钥。完成此操作后,PUTTY/PLINK 会将该密钥存储在 Windows 注册表中的
HKCU\Software\SimonTatham\PuTTY\SshHostKeys
下。您会注意到类似rsa2@22:host
的条目,其中host
是您服务器的主机名。现在,对于该过程的关键,您需要将 REG_SZ 十六进制值
0x23,...
复制到您的 C# 应用程序中,您必须在其中手动使用Microsoft.Win32。在您使用 PLINK 之前,RegistryKey
类可以使用相同的 rsa2@22:host 命名方案为所有其他服务器写入此值(无论您是否认为此注册表值对安全敏感)由您决定,因此如果需要,请在 C# 应用程序中以某种方式保护它)。就像其他人提到的那样,您可能需要考虑使用 SSH 库来获得有关连接过程的更多编程反馈,但要使用 PLINK,这就是您需要做的。
In order to seamlessly connect to a remote server via PLINK, the first time and on subsequent times, you have to manually coordinate your SSH keys. That is, use PUTTYGEN to create your .ppk private key file that PLINK will use, and store the corresponding public key in the
~/.ssh/authorized_keys
file on the server beforehand.You also need to coordinate the sshd's host keys, so use PUTTYGEN to generate a set of private key files
ssh_host_rsa_key
andssh_host_dsa_key
under/etc/ssh
(look at the existing files to figure out which key formats to export to), and then runssh-keygen -y -f /etc/ssh/ssh_host_rsa_key > /etc/ssh/ssh_host_rsa_key.pub
to create the corresponding public key files (do the same to create thessh_host_dsa_key.pub
file).If you have more than one server you want to PLINK to, and don't mind using the same key to connect to all of them (this will depend on your local IT security policy), then just copy the same key files onto each server.
THEN, on your Windows machine that you're using PLINK, manually connect to any server using PUTTY or PLINK, and interactively accept the host key. Once you do that, PUTTY/PLINK stores that key in the Windows registry, under
HKCU\Software\SimonTatham\PuTTY\SshHostKeys
. You'll notice a entry likersa2@22:host
, wherehost
is your server's host name.Now, for the crux of the procedure, you need to copy the REG_SZ hex value
0x23,...
into your C# app, where you'll have to manually use theMicrosoft.Win32.RegistryKey
classes to write this value for all other servers using the samersa2@22:host
naming scheme before you shell out to PLINK (whether you consider this registry value to be security-sensitve is up to you, so protect it somehow in your C# app if you have to).Like others have mentioned, you may want to consider using an SSH library to get more programmatic feedback on your connection process, but to use PLINK, this is what you need to do.