字
字节笔记本
2026年2月23日
DartSSH2:纯 Dart 编写的 SSH/SFTP 客户端库
DartSSH2 是一个使用纯 Dart 编写的 SSH 和 SFTP 客户端库,旨在提供功能丰富且易于使用的远程连接解决方案。该库支持 Dart VM 和 Flutter 环境,可用于构建跨平台的 SSH 客户端应用。
项目简介
DartSSH2 是 dartssh 的完全重写版本,由 TerminalStudio 团队开发维护。截至目前,该项目在 GitHub 上已获得 243+ stars,是一个成熟稳定的开源项目。
核心特性
- 纯 Dart 实现:同时支持 Dart VM 和 Flutter 环境
- SSH 会话管理:执行命令、交互式 Shell、环境变量设置、伪终端支持
- 多种认证方式:支持密码认证、私钥认证和交互式认证
- 端口转发:支持本地端口转发和远程端口转发
- 完整 SFTP 支持:实现 SFTPv3 协议的所有操作,包括上传、下载、列表、链接、删除、重命名等
技术栈
- Dart:核心编程语言
- Flutter:支持移动端和桌面端应用开发
- SSH-2.0 协议:兼容 OpenSSH 等主流 SSH 服务器
- SFTPv3 协议:文件传输协议实现
安装指南
添加依赖
在 pubspec.yaml 文件中添加依赖:
yaml
dependencies:
dartssh2: ^2.11.0安装命令行工具
bash
# 安装 dartssh 命令行工具
dart pub global activate dartssh2_cli
# 使用 dartssh 作为常规 ssh 命令
dartssh user@example.com
# 执行远程命令
dartssh user@example.com ls -al
# 连接非标准端口
dartssh user@example.com:<port>
# 通过 SFTP 传输文件
dartsftp user@example.com快速开始
连接到远程主机
dart
import 'package:dartssh2/dartssh2.dart';
void main() async {
final client = SSHClient(
await SSHSocket.connect('localhost', 22),
username: '<username>',
onPasswordRequest: () => '<password>',
);
}在远程主机上执行命令
dart
void main() async {
final uptime = await client.run('uptime');
print(utf8.decode(uptime));
}启动交互式 Shell
dart
void main() async {
final shell = await client.shell();
stdout.addStream(shell.stdout); // 监听标准输出
stderr.addStream(shell.stderr); // 监听标准错误
stdin.cast<Uint8List>().listen(shell.write); // 写入标准输入
await shell.done; // 等待 Shell 退出
client.close();
}使用示例
公钥认证
dart
void main() async {
final client = SSHClient(
socket,
username: '<username>',
identities: [
// 单个私钥文件可能包含多个密钥
...SSHKeyPair.fromPem(await File('path/to/id_rsa').readAsString())
],
);
}加密 PEM 文件处理
dart
void main() async {
// 检测私钥是否加密
final encrypted = SSHKeyPair.isEncrypted(await File('path/to/id_rsa').readAsString());
print(encrypted);
// 如果私钥已加密,需要提供密码短语
final keys = SSHKeyPair.fromPem('<pem text>', '<passphrase>');
print(keys);
}本地端口转发
dart
void main() async {
final serverSocket = await ServerSocket.bind('localhost', 8080);
await for (final socket in serverSocket) {
final forward = await client.forwardLocal('httpbin.org', 80);
forward.stream.cast<List<int>>().pipe(socket);
socket.pipe(forward.sink);
}
}远程端口转发
dart
void main() async {
final forward = await client.forwardRemote(port: 2222);
if (forward == null) {
print('Failed to forward remote port');
return;
}
await for (final connection in forward.connections) {
final socket = await Socket.connect('localhost', 22);
connection.stream.cast<List<int>>().pipe(socket);
socket.pipe(connection.sink);
}
}跳板机连接
dart
void main() async {
final jumpServer = SSHClient(
await SSHSocket.connect('<jump server>', 22),
username: '...',
onPasswordRequest: () => '...',
);
final client = SSHClient(
await jumpServer.forwardLocal('<target server>', 22),
username: '...',
onPasswordRequest: () => '...',
);
print(utf8.decode(await client.run('hostname')));
}SFTP 操作
列出远程目录
dart
void main() async {
final sftp = await client.sftp();
final items = await sftp.listdir('/');
for (final item in items) {
print(item.longname);
}
}读取远程文件
dart
void main() async {
final sftp = await client.sftp();
final file = await sftp.open('/etc/passwd');
final content = await file.readBytes();
print(latin1.decode(content));
}文件上传
dart
void main() async {
final sftp = await client.sftp();
final file = await sftp.open('file.txt', mode: SftpFileOpenMode.create | SftpFileOpenMode.write);
await file.write(File('local_file.txt').openRead().cast());
}暂停和恢复上传
dart
void main() async {
final uploader = await file.write(File('local_file.txt').openRead().cast());
// ...
await uploader.pause();
// ...
await uploader.resume();
await uploader.done;
}目录操作
dart
void main() async {
final sftp = await client.sftp();
await sftp.mkdir('/path/to/dir');
await sftp.rmdir('/path/to/dir');
}获取/设置文件属性
dart
void main() async {
await sftp.stat('/path/to/file');
await sftp.setStat(
'/path/to/file',
SftpFileAttrs(mode: SftpFileMode(userRead: true)),
);
}获取磁盘空间信息
dart
void main() async {
final sftp = await client.sftp();
final statvfs = await sftp.statvfs('/root');
print('total: ${statvfs.blockSize * statvfs.totalBlocks}');
print('free: ${statvfs.blockSize * statvfs.freeBlocks}');
}基于 DartSSH2 构建的项目
项目链接
分享: