Skip to content

v0.21.2

Latest

Choose a tag to compare

@github-actions github-actions released this 31 Aug 13:21

What's Changed

Fixed

  • SSH through a jump host could hang at the target password prompt when the proxy step was slow (issue #301) — the target host's password was typed by a watcher that read the terminal and recognised the password: prompt, and that watcher gave up after a fixed 10-second window measured from the moment SSH was spawned. The whole ProxyCommand handshake to the bastion ate into the same budget, so when the proxy step ran long the watcher had already stopped by the time the target prompt appeared and the session sat at password: doing nothing.

    The deadline is not the fix. SSH no longer types the target password into the terminal at all: it is handed to OpenSSH itself through SSH_ASKPASS, which has no deadline to miss because OpenSSH asks the helper exactly when it needs the credential, however long the proxy chain took to get there. See Changed below for the shape of that mechanism.

    The terminal watcher is still what logs Telnet and Serial in, and its deadline was the real defect there too — a device that spends a long time on its banner could outlast a window that started at spawn. It is now measured from the last terminal activity: as long as output keeps arriving the watcher keeps waiting, and it gives up only after the terminal has been genuinely idle for the timeout (default 10 s, still overridable per connection or group), with a 120-second absolute ceiling so a device printing a heartbeat cannot keep it alive forever.

  • A SPICE connection asked for the password every time, whatever the password source (issue #308) — SPICE runs in an external viewer (remote-viewer), and RustConn resolved and cached the connection's password at connect time but then never handed it to the viewer, which prompted on its own. The password source only affected how the secret was resolved, so changing it made no difference — the launch discarded the secret regardless. RustConn now passes it through a virt-viewer .vv connection file, mirroring how RDP delivers a password: written to a mode-0600 file in the user's runtime directory, carrying delete-this-file=1 so the viewer removes it after reading, and never placed on the command line or in the environment where another process could read it. The file is used for host/port and TLS connections; a unix-socket SPICE connection, which the .vv format cannot address and which needs no password in practice, is unchanged and still relies on the viewer. Connection-independent options (USB redirection, shared folders, window title) continue to be passed as flags alongside the file.

  • The embedded web browser lost its login on every restart (issue #309) — a Web connection opened in Embedded mode asked for credentials again after RustConn was closed and reopened, while the same connection in System mode stayed logged in. Each connection already gets a persistent NetworkSession with its own data directory, which makes the website data manager persistent — but WebKitGTK keeps cookies in a separate subsystem that stays in memory only until set_persistent_storage is called on the cookie manager, and that call was missing. Cookies are now written to cookies.sqlite in the connection's data directory, so a session survives a restart. Existing connections gain this automatically the next time they are opened; there is nothing to migrate, since there were no persisted cookies before.

  • A new Local Shell tab in Flatpak could open at the wrong size when the window had changed size since the last tab (issue #294) — the host shell runs through flatpak-spawn --host and script, which copies the window size exactly once at startup and never sees a later SIGWINCH (flatpak-spawn does not forward it). The spawn already waited for the terminal to be laid out before starting, but the test was a non-zero pixel allocation, and that arrives one frame before VTE recomputes its row and column count for that allocation. A tab opened while the window was a different size than the previous one therefore spawned on the very first poll tick with the previous grid still in place, freezing the host shell at that stale size (the reported 18×80). The spawn now waits until the grid has settled — a non-zero allocation plus two consecutive polls reporting the same row/column count — so script inherits the size the user is actually looking at. SSH and other sessions were never affected: they run on RustConn's own PTY, which tracks resizes normally.

Changed

  • A stored SSH password is now given to OpenSSH instead of typed into the terminal — this replaces the auto-fill watcher that has answered SSH password prompts since 0.17.5, and it is the mechanism behind the #301 fix above. The old arrangement worked by reading terminal output and calling feed_child, which meant RustConn had to guess, from text, both what was being asked and who was asking. That guess is what issues #191, #203, #254 and #301 were all variations of.

    What happens now: the credential is written to a mode-0600 file in $XDG_RUNTIME_DIR and only its path is placed in the SSH process environment, so the secret is no longer visible in /proc/<pid>/environ. An SSH_ASKPASS helper opens that file, unlinks it, and prints it — once. The helper answers only the prompt OpenSSH generates itself for the password method (<user>@<host>'s password: ) and exits without printing for a private-key passphrase, a host-key confirmation, a keyboard-interactive or OTP challenge, or a password-change prompt. Bastion passwords moved to the same file-path indirection (the environment variable is _RC_JH_PW_FILE where it used to be _RC_JH_PW), and every generated proxy hop now starts with an env boundary that blanks the credentials that hop must not see. Files are removed when the session's child exits, and on any spawn that fails.

    Nothing about which authentication method runs is pinned, and that is deliberate: what keeps the credential away from the wrong question is the helper declining to answer it, not a narrowed method list. A method the helper declines simply fails without consuming the secret file, and OpenSSH moves on to the next one — so a key inherited from a group is still offered and still wins when it works, and a server that tries keyboard-interactive before password still reaches the prompt the helper answers. The only two options added are about the shape of the launch rather than the method: NumberOfPasswordPrompts=1, which keeps the one-shot posture that stops a wrong stored password from walking an account into a lockout, and StrictHostKeyChecking=accept-new unless the connection sets its own, so a forced helper is never handed a host-key question. A changed host key is still refused.

    Where askpass steps aside, the terminal watcher still does the typing, exactly as it did before: an authentication method whose point is an interactive second factor (security key, keyboard-interactive), a PKCS#11 token, a custom option that redirects authentication or routing, or a proxy route RustConn did not build. That last one is detected by asking ssh -G, which resolves ~/.ssh/config the way a real connection would — a bastion declared only there would otherwise spawn a nested ssh that inherits the helper and gets asked for a password with the very shape the helper answers, which would hand the target's credential to the bastion. Costs one short-lived ssh -G (~4 ms, no network) on connections that are otherwise eligible. The per-connection and per-group expected password prompt override from issue #254 and the login timeout apply to the watcher, so they keep working for every connection that uses it.

Dependencies

  • Updated: gtk-rs stack (glib, gio, cairo-rs, pango, gdk-pixbuf-sys, graphene-sys and their -sys crates) 0.22.8 → 0.22.9, aes 0.9.2 → 0.9.3, hyper 1.11.0 → 1.11.1, indexmap 2.14.0 → 2.14.1; system-deps 9.0.0 pulled in transitively. All are semver-compatible patch updates from cargo update.

Installation

Flatpak (Recommended)

flatpak install flathub io.github.totoshko88.RustConn

Snap

sudo snap install rustconn

Debian/Ubuntu (.deb from this release)

sudo dpkg -i rustconn_0.21.2_amd64.deb
sudo apt-get install -f  # Install dependencies if needed

Fedora (.rpm from this release)

sudo dnf install rustconn-0.21.2-1.fc44.x86_64.rpm

AppImage

chmod +x RustConn-0.21.2-x86_64.AppImage
./RustConn-0.21.2-x86_64.AppImage

macOS (Homebrew)

brew tap totoshko88/rustconn
brew install rustconn
open $(brew --prefix)/opt/rustconn/RustConn.app

All dependencies (GTK4, libadwaita, VTE, Adwaita icons) are installed automatically.
Requires macOS 13 (Ventura) or later.

OBS Repositories

Packages available at: https://build.opensuse.org/package/show/home:totoshko88:rustconn/rustconn

# Debian 13 (Trixie)
echo 'deb http://download.opensuse.org/repositories/home:/totoshko88:/rustconn/Debian_13/ /' \
  | sudo tee /etc/apt/sources.list.d/rustconn.list
curl -fsSL https://download.opensuse.org/repositories/home:/totoshko88:/rustconn/Debian_13/Release.key \
  | gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/rustconn.gpg > /dev/null
sudo apt update && sudo apt install rustconn

# Ubuntu 24.04 LTS (Noble)
echo 'deb http://download.opensuse.org/repositories/home:/totoshko88:/rustconn/xUbuntu_24.04/ /' \
  | sudo tee /etc/apt/sources.list.d/rustconn.list
curl -fsSL https://download.opensuse.org/repositories/home:/totoshko88:/rustconn/xUbuntu_24.04/Release.key \
  | gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/rustconn.gpg > /dev/null
sudo apt update && sudo apt install rustconn

# Ubuntu 26.04 LTS (Resolute)
echo 'deb http://download.opensuse.org/repositories/home:/totoshko88:/rustconn/xUbuntu_26.04/ /' \
  | sudo tee /etc/apt/sources.list.d/rustconn.list
curl -fsSL https://download.opensuse.org/repositories/home:/totoshko88:/rustconn/xUbuntu_26.04/Release.key \
  | gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/rustconn.gpg > /dev/null
sudo apt update && sudo apt install rustconn

# Fedora 44
sudo dnf config-manager addrepo --from-repofile=https://download.opensuse.org/repositories/home:/totoshko88:/rustconn/Fedora_44/home:totoshko88:rustconn.repo
sudo dnf install rustconn

# Fedora 43
sudo dnf config-manager addrepo --from-repofile=https://download.opensuse.org/repositories/home:/totoshko88:/rustconn/Fedora_43/home:totoshko88:rustconn.repo
sudo dnf install rustconn

# openSUSE Tumbleweed
sudo zypper ar https://download.opensuse.org/repositories/home:/totoshko88:/rustconn/openSUSE_Tumbleweed/ rustconn
sudo zypper ref && sudo zypper in rustconn

# openSUSE Leap 16.0
sudo zypper ar https://download.opensuse.org/repositories/home:/totoshko88:/rustconn/openSUSE_Leap_16.0/ rustconn
sudo zypper ref && sudo zypper in rustconn

Arch Linux (AUR)

yay -S rustconn

FreeBSD (Ports)

pkg install rustconn

Full installation guide: https://github.com/totoshko88/RustConn/blob/main/docs/INSTALL.md