What “supported” means
sortOfRemoteNG distinguishes four kinds of protocol surface. This matters because a backend crate, an importer mapping, or a settings form does not by itself make a usable connection tab.
| Classification | Meaning |
|---|---|
| Interactive client | A saved connection mounts a dedicated view while it is connecting. That view owns the real transport lifecycle and reports success or failure from the runtime. |
| External handoff | sortOfRemoteNG validates and launches an installed native client. The remote desktop is not rendered inside the app. |
| Management surface | Commands or hooks manage a provider, appliance, or operating-system feature. Opening it as a generic connection tab is intentionally rejected. |
| Unavailable direct session | Some types, import mappings, or backend code may exist, but there is no honest end-to-end saved-session path yet. The app fails closed instead of showing a simulated “Connected” screen. |
The executable contract is src/utils/session/protocolAvailability.ts. The session manager consults it before creating a direct session, and the regression test tests/session/protocolAvailability.test.ts checks every persisted protocol and every protocol advertised by the primary editor.
Saved connection protocols
| Protocol | Product classification | Direct-session path and limits | Primary evidence |
|---|---|---|---|
| RDP | Interactive client | Embedded RDP session with native lifecycle, rendering/input, diagnostics, detach/reattach, gateway options, and supported Network Paths. | src/components/rdp/RDPClient.tsx, src-tauri/crates/sorng-rdp |
| SSH | Interactive client | Embedded terminal backed by the native SSH runtime, including authentication, host trust, terminal overrides, detach/reattach, and Network Paths. | src/components/ssh/WebTerminal.tsx, src-tauri/crates/sorng-ssh |
| Apple Remote Desktop (ARD) | Interactive client | A portable profile can use Screen Sharing.app for Apple Account authentication on macOS and an explicitly configured embedded remote-Mac-account or dedicated-VNC fallback on Windows/Linux. Both routes use truthful independent lifecycle state; Apple passwords/tokens never enter the embedded RFB client. Embedded ARD is direct TCP only and does not apply app proxy, SSH-hop, VPN, or tunnel-chain routes. | src/components/protocol/ArdClient.tsx, src/hooks/protocol/useArdClient.ts, src-tauri/crates/sorng-ard |
| Serial | Interactive client | Native serial terminal with saved port settings, exact byte streaming, line controls, reconnect status, port enumeration, and explicit disconnect. The port is either a fixed device path or resolved at every connect from a fresh enumeration (“first detected device”, “first USB device”, or a VID/PID/name match); the resolved port is shown in the session header and status line. See Serial device selection. | src/components/protocol/SerialClient.tsx, src/hooks/protocol/useSerialSession.ts, src-tauri/crates/sorng-serial |
| VNC | Interactive client, constrained transport | A native TCP/RFB session owns connection state, framebuffer delivery, keyboard and pointer input, clipboard transfer, reconnect, and disconnect. Legacy unencrypted, weak-authentication, and unauthenticated modes remain blocked unless the saved connection explicitly enables the corresponding exception. VeNCrypt/TLS and Tight security negotiation are not yet supported. | src/components/protocol/VNCClient.tsx, src/hooks/protocol/useVNCClient.ts, src-tauri/crates/sorng-vnc |
| AnyDesk | External handoff | Starts the locally installed AnyDesk launcher and tracks only that child process. A native URL fallback is an untracked handoff. The AnyDesk client owns remote authentication, connection state, framebuffer, and input; the app never reports those as confirmed. A saved password is written to the supported Windows/Linux client’s stdin and is never placed in process arguments, logs, session metadata, or errors. macOS uses the native prompt because its documented CLI does not support password initiation. | src/components/protocol/AnyDeskClient.tsx, src-tauri/crates/sorng-remote-mgmt/src/anydesk.rs |
| HTTP / HTTPS | Interactive client | Embedded browser session with navigation, TLS/trust handling, configured authentication, bookmarks, and optional same-origin auto-login. | src/components/protocol/WebBrowser.tsx, src-tauri/crates/sorng-protocols/src/http.rs |
| Telnet | Interactive client | Native Telnet negotiation and terminal I/O, including resize, BREAK, AYT, reconnect configuration, and backend event streaming. Telnet is plaintext; use it only on a trusted network. | src/components/protocol/TelnetClient.tsx, src/hooks/protocol/useTelnetSession.ts, src-tauri/crates/sorng-telnet |
| Raw Socket | Interactive client | Binary-safe TCP/UDP payload client with exact byte send/receive, transcript handling, replay, stats, and native close. It is not a terminal protocol and provides no encryption by itself. | src/components/protocol/RawSocketClient.tsx, src/hooks/protocol/useRawSocketSession.tsx, src-tauri/crates/sorng-protocols/src/raw_socket |
| RLogin | Interactive client | RFC 1282 handshake, terminal I/O, resize, replay, diagnostics, and native lifecycle. RLogin is plaintext and requires explicit acknowledgement in its saved settings. | src/components/protocol/RloginClient.tsx, src/hooks/protocol/useRloginSession.tsx, src-tauri/crates/sorng-protocols/src/rlogin |
| MySQL / MariaDB | Interactive client, direct-route only | An isolated per-session sorng-mysql workbench (schema browser, query/statement editor, EXPLAIN, process list, CSV/JSON export) with explicit TLS modes and certificate paths; the dialect badge reports MySQL vs MariaDB from the server version. Proxy, VPN, SSH-hop, and tunnel-chain routes fail closed. The legacy process-wide db.rs commands are no longer used by the UI. |
src/components/protocol/MySQLClient.tsx, src/hooks/protocol/useMySQLClient.ts, src-tauri/crates/sorng-mysql |
| PostgreSQL | Interactive client, direct-route only | An isolated native session owns catalog browsing, SQL queries/statements, typed results, reconnect, and close. SQLx receives the selected SSL mode plus optional CA/client certificate/key paths. Configured proxy, VPN, SSH-hop, and tunnel-chain routes fail closed before credentials are sent. | src/components/protocol/PostgreSQLClient.tsx, src/hooks/protocol/usePostgreSQLClient.ts, src-tauri/crates/sorng-postgres |
| MongoDB | Interactive client, direct-route only | An isolated native sorng-mongodb session (official Rust driver) owns the databases → collections browser, document Find with JSON filter/projection/sort plus limit/skip paging, count, aggregation pipelines, an indexes list with create/drop, collection statistics, a table/JSON toggle with a single-document viewer, and JSON export. Insert/update/delete run only behind an explicit edit mode with a confirm dialog. Credentials and any connection-string password are redacted from errors; configured proxy, VPN, SSH-hop, and tunnel-chain routes fail closed before credentials are sent. |
src/components/protocol/MongoDBClient.tsx, src/hooks/protocol/useMongoDBClient.ts, src-tauri/crates/sorng-mongodb |
| SPICE | External handoff | Launches installed virt-viewer remote-viewer and monitors its local process. A saved ticket is supplied through the viewer’s stdin connection-file contract, never argv or a persistent profile. TLS ports, CA trust, host subject, view-only, audio, USB, and a credential-free HTTP CONNECT proxy are supported; unverified certificates, clipboard-off, and generic app routes fail closed. Remote authentication, pixels, and input remain native-client owned. |
src/components/protocol/SpiceClient.tsx, src/hooks/protocol/useSpiceClient.ts, src-tauri/crates/sorng-spice |
| XDMCP | External handoff, insecure transport | Launches and monitors an installed local X server such as VcXsrv, Xephyr, or Xming. XDMCP has no transport authentication or encryption and requires explicit risk acknowledgement. The app verifies only the local X server process, not a remote login screen. Generic routes fail closed and the handoff uses the portable 24-bit display default. | src/components/protocol/XdmcpClient.tsx, src/hooks/protocol/useXdmcpClient.ts, src-tauri/crates/sorng-xdmcp |
| X2Go | External handoff | Launches installed X2Go Client and monitors its local process. Saved session, geometry, link, keyboard, audio, printing, clipboard, and local-folder options use an exclusive temporary profile: mode 0600 on Unix and the current-user temp-directory ACL on Windows. Passwords, passphrases, host trust, and MFA remain native prompts; remote authentication and pixels are not claimed. Generic app routes fail closed. | src/components/protocol/X2goNativeClient.tsx, src/hooks/protocol/useX2goNativeSession.ts, src-tauri/crates/sorng-x2go |
| NX / NoMachine | External handoff | Launches installed NoMachine Client nxplayer with an exclusive temporary NXS profile—mode 0600 on Unix and the current-user temp-directory ACL on Windows—and monitors its local process. The native window owns password, passphrase, host-trust, MFA, framebuffer, and input. NX or SSH transport, safe session types, geometry, fullscreen, and audio are represented; unsupported proxy sessions, clipboard-off, resource details, and app routes fail closed. |
src/components/protocol/NxNativeClient.tsx, src/hooks/protocol/useNxNativeSession.ts, src-tauri/crates/sorng-nx |
| FTP / FTPS | Interactive client, direct-route only | Native file browser with list, upload/download, mkdir, rename, chmod, and recursive delete. It supports passive PASV/EPSV only; active mode, routes, queues, resume, and live progress are not exposed. Plain FTP is unencrypted; FTPS certificate validation is configurable. | src/components/protocol/FTPClient.tsx, src/hooks/protocol/useFTPSession.ts, src-tauri/crates/sorng-ftp |
| SFTP | Interactive client | Native SFTP file browser and operations. Direct sessions pass the saved host, port, username, password or private-key data, passphrase, host policy, timeout, initial path, and label. | src/components/protocol/SFTPClient.tsx, src/hooks/protocol/useSFTPClient.ts, src-tauri/crates/sorng-sftp |
| SCP | Interactive client, direct-route only | Native SSH file browser with file and recursive-directory transfer, mkdir/delete, stat, and checksum. Host keys are checked against the Trust Center first and then the configured/default known_hosts file; Ask fails closed without a prompt, TOFU accepts new keys, and Strict requires a known key. Routes, cancellation/progress, resume, agent auth, and rename/chmod are not exposed. | src/components/protocol/ScpClient.tsx, src/hooks/protocol/useScpClient.ts, src-tauri/crates/sorng-scp |
PowerShell Remoting (winrm) |
Interactive client | Persistent PSRP session over WSMan/WinRM or SSH, with a dedicated terminal-like viewer, truthful capability checks, reconnect/reattach, and native close. This is separate from the Windows management tool panels. | src/components/protocol/PowerShellSessionViewer.tsx, src/hooks/protocol/usePowerShellSession.ts, src-tauri/crates/sorng-powershell |
| RustDesk | External handoff | Uses the saved RustDesk ID and credential, launches the installed RustDesk process, and verifies the backend session before reporting success. It does not embed RustDesk’s framebuffer. | src/components/protocol/RustDeskClient.tsx, src/hooks/protocol/useRustDeskClient.ts, src-tauri/crates/sorng-rustdesk |
| SMB | Interactive client | Connects with the saved host, port, domain/workgroup, share, and credentials, then exposes share and directory browsing plus file operations. | src/components/protocol/SMBClient.tsx, src/hooks/protocol/useSMBClient.ts, src-tauri/crates/sorng-smb |
| VoIP Phone (Yealink T2x) | Interactive management panel | Logs in to the phone’s web admin (SIP-T20P / T21P / T21P E2), auto-detects the legacy-CGI or servlet firmware generation, shows model/firmware/MAC/IP/uptime and SIP account registration, opens the web UI in an embedded browser tab with same-origin auto-login, and reboots via Action URI with a web-form fallback. Credentials stay on the saved connection and never on the session object. See VoIP Phone (Yealink T2x). | src/components/voipPhone/VoipPhoneSessionPanel.tsx, src/hooks/voipPhone/useVoipPhone.ts, src-tauri/crates/sorng-voip-phone |
SSH-family host keys and known_hosts
SSH, SFTP, and SCP resolve host keys through the Trust Center rather than through OpenSSH’s known_hosts file. Records are keyed by host:port with a SHA-256 fingerprint, so one accepted key covers the terminal, the file browser, and SCP for the same endpoint, and they are stored per database in databases/<id>.trust.json — encrypted whenever the database is. A key already trusted for that database is accepted with no prompt; a changed key always takes the mismatch path, even when known_hosts still matches the old one; a revoked record is refused outright.
known_hosts remains an import source. An unknown key that matches the configured or default known_hosts file is adopted into the Trust Center and accepted instead of re-prompting, and Settings → Trust Center can import the whole file on demand. Hashed (|1|…) entries, wildcard and negation patterns, and undecodable keys are reported as skipped rather than guessed at, and an endpoint already recorded is never overwritten — an import cannot re-trust a key you rejected or revoked.
Accepting a new key still appends it to known_hosts by default so other tools sharing that file keep working. also_write_known_hosts — a per-connection option on SSH, SFTP, and SCP connections, defaulting to true, so connections saved before this behavior existed are unchanged — turns the dual write off and keeps the decision inside the database. The shared file is written before the Trust Center record, so a failure to write it aborts the connection with nothing memorized in either place.
With no database open there is nothing to consult: host-key verification fails closed with an error naming the fix rather than falling back to known_hosts. See Security for the storage, encryption, and migration details.
VoIP Phone (Yealink T2x)
The voip-phone protocol manages Yealink desk phones through their web-admin interface. It is modelled with a vendor field (yealink today) so other vendors can be added as drivers later without touching the protocol registry. Verified targets are the SIP-T20P and SIP-T21P, including the T21P E2. Other Yealink models that share the T2x web admin may work but are not verified.
Firmware generations
Yealink changed the web admin between firmware lines. The driver probes the phone on connect and picks the matching path; the detected generation is shown as a badge in the session panel and can be forced through Login mode in the editor if detection fails.
| Generation | Typical models / firmware | Login | Status source | Reboot path |
|---|---|---|---|---|
| Legacy CGI | SIP-T20P, SIP-T21P on v7x firmware | HTTP Basic (admin/admin by default) |
cgi-bin/ConfigManApp.com status page |
Action URI (?key=Reboot), then the CGI reboot form |
| Servlet | SIP-T21P E2 and later T2x on v8x+ firmware | servlet?m=mod_login form; plain or RSA-encrypted password + JSESSIONID |
servlet?m=mod_data&p=status |
Action URI (?key=Reboot), then the servlet reboot form |
Both generations report the same normalised status shape (model, firmware, hardware, MAC, IP, uptime, per-account registration); unknown fields are kept in rawFields for diagnostics.
Enable Action URI for reboot
Reboot tries the phone’s Action URI first (http://<phone>/servlet?key=Reboot or the legacy cgi-bin/ConfigManApp.com?key=Reboot). Yealink phones reject Action URI calls (HTTP 403) unless remote control is enabled and the caller’s IP is allowed. On the phone’s web admin:
- Open Features → Remote Control.
- Set Action URI Allow IP List to this computer’s IP address (or
anyon a trusted network). - Save and, on older firmware, reboot once for the setting to take effect.
- Tick Action URI enabled on the phone in the connection’s Advanced tab so the panel reports the expected method.
If the Action URI is refused or disabled, the reboot falls back to the authenticated web-admin reboot form, so the button still works; the completion toast names the method that was accepted (action-uri or web-form).
Transport and credentials
- Default port is 80 over plain HTTP. Enable Use HTTPS (and usually change the port to 443) for phones with TLS turned on. Phones ship self-signed certificates, so the first HTTPS connection is pinned (trust on first use) and later certificate changes are rejected unless Verify server certificate is disabled for that connection.
- Username and password live on the saved connection (Basics). Opening the web UI creates an
http/httpssession through a runtime-registered connection with auto-login selectors; the password is never copied onto the session object, logs, or serialized status types.
Serial device selection
A Serial connection stores a device selection mode in serialSettings.portSelection alongside the line settings. fixed (the default, and what every connection saved before this field existed reopens as) uses the saved device path exactly as typed. The three automatic modes exist because USB serial adapters get a different COMn / ttyUSBn name on every machine and USB socket:
| Mode | Picks |
|---|---|
firstAny |
The first detected device, preferring USB adapters, then native/PCI ports, then Bluetooth, and virtual ports only when nothing else exists. |
firstUsb |
The first USB serial device only (UsbPort from the OS, or name-classified ttyUSB* / ttyACM* / usbmodem*). |
match |
The first device satisfying every filter given: USB vendor ID, USB product ID, and/or a case-insensitive substring over the port name, manufacturer, description, and serial number. |
Resolution happens in the native backend on every connect and reconnect, from a fresh port enumeration, so hot-plugging and re-seating an adapter needs no edit to the connection. Candidates are ordered by natural name (COM3 before COM10, /dev/ttyUSB0 before /dev/ttyUSB1) so “first” is stable regardless of the OS enumeration order; ports already held by another session in this app are skipped, so two automatic connections never silently share one device. The resolver never opens candidate ports while choosing (probing would toggle DTR and reset devices such as Arduinos); a port held by another program fails at open time as before. When nothing matches, the session fails with No serial device is attached that matches "<mode>" plus a summary of the devices that were seen, so “nothing plugged in” is distinguishable from “wrong filter”; Reconnect re-resolves. The chosen port replaces the placeholder in the session header (Serial · COM7 with an auto · first USB badge whose tooltip is the full device description) and in the session status line (SERIAL to COM7); the saved connection keeps its auto:first-usb / auto:first-device / auto:match placeholder. The editor’s Preview button runs the same resolution without opening the port.
ARD and Apple Account authentication
ARD presents three distinct authentication paths, not three interchangeable password formats. A portable profile can keep the macOS-only handoff and one embedded fallback together while preserving that separation:
- An embedded session can authenticate with an account authorized by the remote Mac, including an eligible local or directory-backed account.
- An embedded VNC-compatible session can use the dedicated password configured for VNC viewers on the remote Mac. That password must be unique and must not reuse an Apple Account password, a local-user password, or a Remote Desktop administrator password.
- An Apple Account connection is a macOS-only external handoff. sortOfRemoteNG saves the non-secret Apple Account identifier, opens Screen Sharing.app, and leaves password entry, two-factor authentication, connection approval, and the remote session inside Apple’s process. On Windows, Linux, or a Mac where the native handoff is unavailable, a portable profile resolves to its explicitly selected embedded fallback; without a valid fallback it fails closed.
Sign in with Apple identity tokens are scoped to the application or web service requesting them; they are not ARD/RFB credentials. Apple app-specific passwords likewise do not authenticate ARD/RFB. Apple documents entering an Apple Account in Screen Sharing.app, but does not document a public URL scheme or API for pre-filling an Apple Account connection, so the handoff does not attempt to automate Apple’s authentication UI.
Credential-bearing, full-fidelity JSON exports preserve the saved identifier, fallback selection, and embedded credentials according to the selected storage/export policy. Credential-free JSON exports retain the non-secret fallback selection but omit the Apple Account identifier and generic username/password, so setup may be required after import. Neither JSON export path can contain an Apple Account password or two-factor authentication code because sortOfRemoteNG never receives those values.
Embedded ARD connects directly to the saved host and port. A system VPN can supply reachability, but the protocol does not manage that VPN and rejects app proxy, SSH-hop, and tunnel-chain routing rather than silently bypassing it.
See Apple Screen Sharing and portable ARD access for setup, security boundaries, and the supporting Apple documentation.
Import mappings versus runtime support
The native and vendor importers normalize recognized names into saved connection protocols. For example, RAW variants map to raw, RLogin maps to rlogin, and PowerShell-like entries map to winrm. The shared persistence boundary also maps the legacy postgres alias to canonical postgresql. Those destinations now have interactive clients, but conversion can preserve only fields represented by the source format. Review transport, authentication, trust, and protocol-specific settings after import.
Recognizing a protocol during import still does not widen its runtime capabilities: imported FTP remains passive/EPSV and direct-route only, imported SCP retains its explicit host-key policy and direct-route boundary, and imported VNC settings still require review of the target, credentials, and any legacy-security exceptions before use. Imported AnyDesk and RustDesk entries still require their installed native clients. See Import, Export & Clone for the review workflow.
Cloud and Lights-Out management panels
The active picker now offers twelve saved management connections in the
Cloud Platforms and Lights-Out & BMC groups. Each has a dedicated
SessionViewer panel, native command registration, validation, and teardown.
They are interactive management panels, not interchangeable terminal or
desktop transports.
| Entries | Classification | Important runtime boundary |
|---|---|---|
| Dell iDRAC, HPE iLO, Lenovo XClarity, Supermicro BMC | Interactive management panel | Native connect attempts a device transport and authentication. Final capability still depends on reachable hardware, firmware, credentials, and the selected Redfish/legacy/IPMI path. |
| Microsoft Azure | Interactive cloud management panel | Connect requests an Azure authentication token, but inventory and permissions still require live resource calls. |
| Google Cloud, DigitalOcean, IBM Cloud, Heroku, Scaleway, Linode, OVHcloud | Interactive cloud management panel | A successful connect can mean local client/session initialization only. It does not prove live provider authentication, authorization, or inventory access. |
Required fields, protected credential boundaries, legacy migration, lease behavior, rollback, and recovery are documented in Cloud & Lights-Out Connections.
Service integrations use the separate integration:* descriptor contract and route through src/components/integrations/IntegrationPanelHost.tsx. Their support level belongs to each integration panel and is not inferred from this direct-session matrix.
Audited implementations not exposed as saved direct sessions
These implementations are included in the audit because their hooks, backend crates, or templates can otherwise look like finished protocols.
| Surface | Current truth |
|---|---|
| Linux MAC controls | useMacClient and sorng-mac expose SELinux/AppArmor management operations, not a remote terminal. |
| IPMI | useIPMIClient and sorng-ipmi expose BMC management operations, not a generic interactive session. |
| Kubernetes | Backend management commands exist in sorng-k8s; Kubernetes is not a generic connection tab. |
Verification boundaries
The protocol matrix is checked at three layers:
BuiltInConnectionProtocolis exhaustively mapped at compile time. Adding a persisted protocol without declaring its runtime truth fails TypeScript compilation.tests/session/protocolAvailability.test.tsverifies that every primary editor option is client-owned, every built-in direct protocol appears exactly once, and all management-only identities remain absent from the picker.tests/session/SessionViewer.test.tsxverifies that dedicated clients mount during connecting and reconnecting states, before any runtime can honestly report success.
Focused protocol tests cover the transport-specific behavior. FTP verifies native DTOs, redacted credential logging, lifecycle, direct file operations, and fail-closed routing/modes. SCP verifies host-key policy mapping, known_hosts handling, lifecycle, direct file/directory operations, and fail-closed routing. PostgreSQL verifies DTO construction, SSL validation, secret redaction, direct-route rejection, lifecycle/reconnect, typed native values, and command registration. SPICE, XDMCP, X2Go, and NoMachine verify exact native-process launch contracts, secret handling, fail-closed options/routes, reattach, polling, and final close without claiming remote readiness. Raw Socket and RLogin have native Rust end-to-end tests; Telnet verifies native connect/events/exact input; Serial verifies configuration, byte streaming, echo, controls, and cleanup; ARD verifies framebuffer/input and command parity; and PowerShell verifies PSRP over SSH and WSMan. Live WinRM, SSH, FTP/SCP, PostgreSQL, VNC, native-client, and hardware-backed Serial checks remain environment-dependent because they require reachable targets, credentials, local applications, devices, or drivers—an ignored live fixture is not counted as a passing connection.
Choosing a path
- Prefer SSH, RDP, ARD, or PowerShell Remoting for their intended interactive workloads.
- Prefer SFTP for the broadest in-app file-management surface; use FTP/FTPS or SCP when the target specifically requires them and the direct-route limits fit.
- Use PostgreSQL for an isolated native database workbench when a direct target and the configured SSL policy fit.
- Use VNC for native TCP/RFB endpoints, keeping legacy transport and authentication exceptions disabled unless a trusted isolated environment requires them. VeNCrypt/TLS and Tight security negotiation are not yet supported.
- Treat AnyDesk and RustDesk as native application handoffs and install their clients first.
- Install virt-viewer, X2Go Client, or NoMachine Client before using SPICE, X2Go, or NX; use their native authentication prompts and treat app status as local-process status only.
- Use XDMCP only on a trusted isolated network after accepting its unauthenticated, unencrypted transport boundary and installing a supported local X server.
- Use Telnet and RLogin only when a legacy system requires them; both expose credentials and traffic unless the surrounding network supplies protection.
- Use Raw Socket only when you understand the target framing and security model.
For routing compatibility, continue to Network Paths. For source boundaries and backend layering, see Architecture.