feat: add SSH key passphrase field and file picker for key path

- Add ssh_key_passphrase field to ConnectionConfig model with full keyring lifecycle
- Pass passphrase to russh load_secret_key for encrypted SSH keys
- Add native file picker (FolderOpen icon) next to SSH key path input
- Add password-type input for key passphrase in connection dialog
- Make connection dialog form scrollable for short windows
- Fix alignment of key path input and browse button
- Add i18n keys (en + zh-CN)
This commit is contained in:
yavon007
2026-05-03 04:39:03 +08:00
parent 0fdd0c1f9b
commit 58ca9a3b21
8 changed files with 60 additions and 4 deletions
+5 -2
View File
@@ -28,6 +28,7 @@ async fn connect_and_authenticate(
ssh_user: &str,
ssh_password: &str,
ssh_key_path: &str,
ssh_key_passphrase: &str,
) -> Result<Handle<SshClient>, String> {
let config = Arc::new(Config {
nodelay: true,
@@ -39,7 +40,8 @@ async fn connect_and_authenticate(
.map_err(|e| format!("SSH connection failed: {e}"))?;
if !ssh_key_path.is_empty() {
let key_pair = load_secret_key(ssh_key_path, None)
let passphrase = if ssh_key_passphrase.is_empty() { None } else { Some(ssh_key_passphrase) };
let key_pair = load_secret_key(ssh_key_path, passphrase)
.map_err(|e| format!("Failed to load SSH key: {e}"))?;
let auth_res = session
.authenticate_publickey(
@@ -158,6 +160,7 @@ impl TunnelManager {
ssh_user: &str,
ssh_password: &str,
ssh_key_path: &str,
ssh_key_passphrase: &str,
remote_host: &str,
remote_port: u16,
expose_to_lan: bool,
@@ -165,7 +168,7 @@ impl TunnelManager {
let local_port = portpicker::pick_unused_port().ok_or("No available port")?;
let session =
connect_and_authenticate(ssh_host, ssh_port, ssh_user, ssh_password, ssh_key_path)
connect_and_authenticate(ssh_host, ssh_port, ssh_user, ssh_password, ssh_key_path, ssh_key_passphrase)
.await?;
let bind_addr = if expose_to_lan { "0.0.0.0" } else { "127.0.0.1" };