SSH.NET 实战教程:SSH/SFTP 操作完全指南
前言
SSH.NET 是一个功能强大的 .NET 库,用于处理 SSH(安全外壳协议)和 SFTP(SSH 文件传输协议)操作。本文将深入讲解如何使用 SSH.NET 进行各种常见的远程操作,包括命令执行、文件传输、身份验证等场景。
基础环境准备
在开始之前,请确保你的项目已添加 SSH.NET 的引用。可以通过 NuGet 包管理器安装最新版本。
基础连接与命令执行
简单命令执行
最基本的操作是通过 SSH 连接到远程服务器并执行命令:
using (var client = new SshClient("sftp.foo.com", "guest", new AuthenticationKeyFile("path/to/my/key")))
{
client.Connect();
using SshCommand cmd = client.RunCommand("echo 'Hello World!'");
Console.WriteLine(cmd.Result); // 输出: "Hello World!\n"
}
关键点解析:
SshClient
是 SSH 连接的核心类- 构造函数接受主机名、用户名和认证信息(这里使用密钥文件认证)
RunCommand
方法同步执行命令并返回结果
文件传输操作
SFTP 文件上传与目录列表
SSH.NET 提供了 SftpClient
类专门处理 SFTP 操作:
using (var client = new SftpClient("sftp.foo.com", "guest", "pwd"))
{
client.Connect();
// 上传文件
using (FileStream fs = File.OpenRead(@"C:\tmp\test-file.txt"))
{
client.UploadFile(fs, "/home/guest/test-file.txt");
}
// 列出目录内容
foreach (ISftpFile file in client.ListDirectory("/home/guest/"))
{
Console.WriteLine($"{file.FullName} {file.LastWriteTime}");
}
}
注意事项:
- 上传大文件时建议使用异步方法或分块上传
ListDirectory
会返回 "." 和 ".." 目录项,处理时需过滤
高级认证方式
多因素认证
SSH.NET 支持多种认证方式的组合:
var connectionInfo = new ConnectionInfo("sftp.foo.com",
"guest",
new PasswordAuthenticationMethod("guest", "pwd"),
new AuthenticationKeyMethod("path/to/my/key"));
using (var client = new SftpClient(connectionInfo))
{
client.Connect();
}
认证机制说明:
- 可以同时提供密码和密钥认证
- 服务器会按配置顺序尝试认证方式
证书认证
对于企业级环境,可以使用证书进行认证:
using (var authKeyFile = new AuthenticationKeyFile("path/to/my/key", passPhrase: null, "path/to/my/certificate.pub"))
using (var client = new SshClient("sftp.foo.com", "guest", authKeyFile))
{
client.Connect();
}
主机验证与安全
指纹验证
确保连接的是正确的服务器至关重要:
string expectedFingerPrint = "LKOy5LvmtEe17S4lyxVXqvs7uPMy+yF79MQpHeCs/Qo";
using (var client = new SshClient("sftp.foo.com", "guest", "pwd"))
{
client.HostKeyReceived += (sender, e) =>
{
e.CanTrust = e.FingerPrintSHA256 == expectedFingerPrint;
};
client.Connect();
}
安全建议:
- 始终验证服务器指纹
- 使用 SHA256 指纹而非较弱的 MD5
- 对于生产环境,考虑使用证书颁发机构(CA)验证
交互式 Shell 操作
创建 Shell 会话
using (var client = new SshClient("sftp.foo.com", "user", "password"))
{
client.Connect();
using ShellStream shellStream = client.CreateShellStream("ShellName", 80, 24, 800, 600, 1024);
// 可以在此进行交互式操作
client.Disconnect();
}
特权提升示例 (su - root)
using (var client = new SshClient("sftp.foo.com", "user", "password"))
{
client.Connect();
using ShellStream shellStream = client.CreateShellStream("ShellName", 80, 24, 800, 600, 1024);
// 等待登录完成
string prompt = shellStream.Expect(new Regex(@"[$>]"));
// 发送特权提升命令
shellStream.WriteLine("su - root");
prompt = shellStream.Expect(new Regex(@"([$#>:])"));
// 处理密码提示
if (prompt.Contains(":"))
{
shellStream.WriteLine("password");
prompt = shellStream.Expect(new Regex(@"[$#>]"));
}
client.Disconnect();
}
交互技巧:
Expect
方法等待特定模式出现- 处理不同提示符需要灵活的正则表达式
- 考虑超时设置避免无限等待
流式数据处理
向命令发送流数据
using (var client = new SshClient("sftp.foo.com", "guest", "pwd"))
{
client.Connect();
using (SshCommand command = client.CreateCommand("cat"))
{
Task executeTask = command.ExecuteAsync(CancellationToken.None);
using (Stream inputStream = command.CreateInputStream())
{
inputStream.Write("Hello World!"u8);
}
await executeTask;
Console.WriteLine(command.ExitStatus); // 0 表示成功
Console.WriteLine(command.Result); // "Hello World!"
}
}
应用场景:
- 处理大文件时避免内存问题
- 实时数据传输
- 与需要持续输入的交互式程序通信
最佳实践与性能优化
- 连接管理:始终使用
using
语句确保连接关闭 - 错误处理:捕获
SshException
和SftpException
- 超时设置:为长时间操作配置合理的超时
- 资源释放:及时释放命令和流对象
- 异步操作:对于耗时操作使用异步方法
总结
SSH.NET 提供了强大而灵活的 API 来处理 SSH 和 SFTP 操作。通过本文的示例,你应该已经掌握了从基础连接到高级操作的关键技术。在实际应用中,根据具体需求选择合适的方法,并始终将安全性放在首位。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考