Skip to content

v0.22.4

Choose a tag to compare

@github-actions github-actions released this 23 Sep 00:34
· 5 commits to main since this release

What's Changed

Fixed

  • The Snap Store listing lost its Donations, Source code and Report-a-bug links after a release — the snap's store links are declared as top-level website / source-code / issues / donation / contact fields, which snapd copies into the built snap.yaml links: block and the store shows on the listing. The contact field held a bare e-mail address (totoshko88@gmail.com); the metadata spec requires a contact e-mail to be mailto:-prefixed, so the bare value was an invalid link entry and the store dropped the whole links: block when the "Update metadata on release" sync ran on promotion — which is why every link vanished, not just the contact one. The five fields are now lists (the spec allows several links per field), the contact e-mail carries a mailto: prefix, and contact also points at the issue tracker so "Report a bug" resolves to the right place.

  • A saved password could be missed on the first connect after startup, prompting for it needlessly — the credential resolver runs the instant a connection is opened, which right after launch (or immediately after saving a password) can be before the secret backend is warm: the encrypted Secret Service session is still being negotiated, keepassxc-cli is paying its first process start, or a startup Bitwarden unlock has not yet populated the process-global session. A read against a not-yet-ready backend failed, and a single failure collapsed straight into the "backend not configured" dialog / a password prompt with the secret sitting in the vault the whole time. The resolver now retries a transient backend read a few times with a short backoff before reporting it, so the backend gets the fraction of a second it needs. Only a genuine read failure is retried — a real miss ("vault entry not found"), a locked KDBX/portable file, or a resolved password are all still final on the first pass, and a permanently absent backend reports the same dialog it always did, delayed by at most a second. The retry runs only on the background connect path; the jump-host bastion resolver, which runs on the UI thread during launch, stays single-attempt so the window never blocks.

  • A Web/SOCKS tunnel through a dead SSH host froze the window and mis-warned about a password — opening a Web connection that browses through an SSH host (or the SSH sidebar's "Open Browser via Tunnel") raised an ssh -N -D SOCKS proxy and then waited for its local port to come up. Several faults made an unreachable jump host painful. The tunnel ssh carried no ConnectTimeout, so it hung on the OS TCP timeout; and the raise-and-wait ran on the GTK thread, so the window stopped responding for the whole time. SSH tunnels now default to ConnectTimeout=8 (all tunnel kinds — the Web SOCKS proxy and the RDP/VNC/SPICE -L forwards; a value in the connection's extra SSH args still wins). Eight seconds is deliberately below the readiness poll's own 10-second budget (40 × 250 ms): a larger value never helped, because the poll gave up first and reported a generic "not ready" while ssh was still alive, losing the real reason — now ssh dies at ~8 s, the next poll sees the dead process, and the failure carries the bastion's own message (e.g. "connect to host … port 22: Connection timed out"). The embedded and custom-browser Web tunnels now raise the proxy on a background thread and build the browser once it is up, so the window stays responsive while the tunnel connects. The tunnel spawn also logs its assembled SSH flags at info level (never the env, where the askpass password lives) so a future tunnel failure is diagnosable from a log.

  • A Web bookmark wrongly warned "you will be prompted for a password" — when a Web connection had no stored credential, RustConn showed the same "Vault entry not found — you will be prompted for a password" toast it shows for SSH/RDP. That notice is meaningless for a Web bookmark: the browser (embedded or external) collects any credential the page itself asks for, and a configured SOCKS tunnel authenticates to its jump host, not the site. Worse, it fired during credential resolution — before the tunnel was even raised — so a bookmark through a dead bastion warned about a password prompt that would never come and then failed to connect at all. Connection::expects_password_prompt, the shared predicate behind that toast, now returns false for Web connections, so the notice no longer appears for them. SSH (password vs key), RDP and VNC behaviour is unchanged.

  • Jump-host connections to an unreachable host hung and were shown as connected — a connection routed through a bastion (SSH ProxyJump/ProxyCommand) skips the pre-connect port check, since the target is not directly reachable. Two problems followed when a bastion or target was down. First, the SSH command carried no ConnectTimeout, so it waited on the OS TCP timeout — up to minutes — with the tab stuck on "Connecting…" instead of failing. SSH commands now default to ConnectTimeout=15 (the target ssh and the jump-host ProxyCommand's own ssh both get it; a value set in a connection's Custom Options still wins), so a dead host or bastion fails in seconds and the terminal shows the reason. Second, the "connected" status was decided purely by terminal output advancing a couple of rows, and a bastion prints its MOTD/banner the instant the first hop connects — seconds before the final hop is attempted — which latched the sidebar green and started remote monitoring against a host that then timed out (and the monitoring probe, using its own accept-new connection, could even show live data for a session the user watched fail). The established-vs-failed decision is now one shared helper used by both the sidebar status and the monitoring start (previously duplicated, so a fix to one missed the other): a jump-host session is treated as connected only once its terminal is free of known SSH failure patterns and shows an interactive shell prompt — proof the final hop handed over a shell, which a bastion banner alone never provides. Direct connections are unchanged.

  • External RDP surfaced a cryptic "Unexpected keyword" with no way to diagnose it (issue #339) — when the external FreeRDP client rejects one of the command-line options RustConn passes, its parser aborts before connecting and prints the bare winpr string "Unexpected keyword". The tabless external-session path (used when a connection runs in an external window) showed that string verbatim as the failure, which tells the user nothing and misattributes an argument mismatch to the connection. Two changes: the failure is now recognised for what it is — a client/argument mismatch — and reported as such, naming the exact option FreeRDP flagged when its log carries it and pointing at the FreeRDP version and the issue tracker; and this launch path now logs the full argument vector at debug level (the password travels in the single-use args file, never on the command line, so the log is safe), which it previously did not, so the rejected option can be identified from a log. The connection's generated options are all valid on current FreeRDP 3.x, so the mismatch points at an older or atypical client build.

Improved

  • External VNC and SPICE viewers now log the exact command they launch (follow-up to issue #339) — the external RDP path was not the only launcher that spawned a client with its output discarded and no record of the arguments passed. The VNC session viewer, the SPICE / generic external viewer, and both embedded-VNC external fallbacks all did the same, so a viewer that rejected an option (a stale custom argument, a flag an older viewer does not know such as -SecurityTypes, or a version-sensitive --spice-* option) simply flashed and died with nothing in the log to explain it. Each of these paths now logs its full argument vector at debug level before spawning. No password is ever on that command line — VNC leaves it to the viewer and SPICE passes it in the single-use .vv file — so the log is safe. Behaviour is otherwise unchanged; this only makes the next such failure diagnosable from a log.

Documentation

  • README demo video is now centred, and the GitHub project description and topics were filled in — the demo-video thumbnail sat left-aligned while every other header element is centred; it is now wrapped in a centred block like the badges and screenshots. The GitHub repository had no topics and a Linux-only one-line description that undersold the project; the description now names the cross-platform reach (Linux, macOS, FreeBSD, Windows/WSLg) and the full protocol set, the homepage points at the Flathub listing, and a set of discovery topics (rust, gtk4, libadwaita, ssh, rdp, vnc, spice, connection-manager, remote-desktop, kubernetes, zero-trust, wayland, and more) was added.

Dependencies

  • Updated (macOS tray, behind tray-macos): tray-icon 0.24→0.25, muda 0.19→0.20 (pulling keyboard-types 0.7→0.8). These crates are only compiled into the macOS tray; the Linux packages do not build them. The 0.22.3 changelog listed the same bump, but the manifest was never actually moved off 0.24/0.19 — this release applies it for real.

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.22.4_amd64.deb
sudo apt-get install -f  # Install dependencies if needed

Fedora (.rpm from this release)

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

AppImage

chmod +x RustConn-0.22.4-x86_64.AppImage
./RustConn-0.22.4-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