SSH Tunnel Connections in DBX: Key and Password Authentication Methods

DBX supports four SSH tunnel authentication methods—private key files, plaintext passwords, SSH agent sockets, and automatic probing—controlled by the auth_method field in the SshTunnelConfig struct.

DBX implements SSH tunneling as a first-class transport layer, enabling database drivers to reach remote servers through secure bastion hops. The tunnel configuration is defined in crates/dbx-core/src/models/connection.rs and processed by the TunnelManager in crates/dbx-core/src/db/ssh_tunnel.rs, supporting both explicit authentication selection and legacy fallback behavior.

Core SSH Tunnel Configuration Structure

The SshTunnelConfig struct stores all parameters required to establish an SSH tunnel, including host details, timeouts, and authentication credentials.

pub struct SshTunnelConfig {
    pub id: String,
    pub name: String,
    pub enabled: bool,
    pub host: String,                 // SSH server
    pub port: u16,                    // default 22
    pub user: String,                 // SSH login name
    pub password: String,             // password (if used)
    pub key_path: String,             // path to private key file
    pub key_passphrase: String,       // optional passphrase for the key
    pub connect_timeout_secs: u64,
    pub expose_lan: bool,
    pub use_ssh_agent: bool,
    pub ssh_agent_sock_path: String,
    /// Login method: `"password"`, `"key"`, `"agent"`, or `"none"`.
    pub auth_method: String,
}

Source: crates/dbx-core/src/models/connection.rs (lines 138-176)

The auth_method field determines which credential type the backend attempts during connection. When left empty, DBX probes credentials in the order key → password → agent for backward compatibility.

SSH Authentication Methods in DBX

DBX supports four distinct authentication strategies via the auth_method string:

  • ** "key" ** – Loads the private key file specified in key_path and decrypts it using key_passphrase if provided.
  • ** "password" ** – Transmits the plaintext password stored in the password field to the SSH daemon.
  • ** "agent" ** – Connects to an SSH agent using ssh_agent_sock_path or the $SSH_AUTH_SOCK environment variable when use_ssh_agent is enabled.
  • ** "none" or empty ** – Triggers automatic probing of non-empty credential fields in fallback order.

The authentication selection logic in crates/dbx-core/src/db/ssh_tunnel.rs evaluates these conditions:

let try_key = auth_method.is_empty() && !ssh_key_path.is_empty() || auth_method == "key";
let try_password = auth_method.is_empty() && !ssh_password.is_empty() || auth_method == "password";
let try_agent = auth_method.is_empty() && use_ssh_agent || auth_method == "agent";

Source: crates/dbx-core/src/db/ssh_tunnel.rs (lines 101-104)

The UI enforces explicit selection through the Tunnel / Proxy → SSH Tunnel dialog, presenting tabs for "Private Key (Recommended)" and "Password" as documented in docs/content/docs/ssh-tunnel.mdx.

How DBX Establishes SSH Tunnel Connections

The tunnel creation process follows a structured flow from configuration to local port binding:

  1. Configuration Input – The user supplies host, port, user, and authentication credentials through the UI or programmatic config.
  2. Chain Planning – For multi-hop bastion setups, the plan_chain function walks each hop and returns a vector of PlannedTunnel structs describing the connection path. Source: crates/dbx-core/src/db/ssh_tunnel.rs (lines 8-19)
  3. Client Initialization – The TunnelManager opens an SSH client (ssh_client_config) for each hop, applying the selected auth_method using the russh library.
  4. Port Binding – Once authenticated, DBX binds a local port and points the database driver at 127.0.0.1:<local-port>, forwarding all traffic through the encrypted tunnel to the target host.

The high-level open_ssh_tunnel method orchestrates this process, accepting a connection identifier, configuration array, and target database host/port.

SSH Tunnel Configuration Examples

Key-Based Authentication

Configure a tunnel using a private key with optional passphrase protection:

use dbx_core::models::connection::SshTunnelConfig;

let ssh_cfg = SshTunnelConfig {
    id: "my_ssh".into(),
    name: "Bastion".into(),
    enabled: true,
    host: "bastion.example.com".into(),
    port: 22,
    user: "alice".into(),
    password: "".into(),               // not used
    key_path: "~/.ssh/id_rsa".into(),
    key_passphrase: "my‑passphrase".into(),
    connect_timeout_secs: 5,
    expose_lan: false,
    use_ssh_agent: false,
    ssh_agent_sock_path: "".into(),
    auth_method: "key".into(),        // forces key authentication
};

Password-Based Authentication

Configure a tunnel using plaintext password authentication:

let ssh_cfg = SshTunnelConfig {
    id: "my_ssh".into(),
    name: "Bastion".into(),
    enabled: true,
    host: "bastion.example.com".into(),
    port: 22,
    user: "bob".into(),
    password: "s3cr3t".into(),
    key_path: "".into(),
    key_passphrase: "".into(),
    connect_timeout_secs: 5,
    expose_lan: false,
    use_ssh_agent: false,
    ssh_agent_sock_path: "".into(),
    auth_method: "password".into(),
};

Opening the Tunnel

Use TunnelManager to establish the connection and bind the local port:

use dbx_core::db::ssh_tunnel::TunnelManager;

#[tokio::main]
async fn main() {
    let manager = TunnelManager::new();
    // `connection_id` is an arbitrary identifier for the DBX connection.
    manager
        .open_ssh_tunnel("my_connection", &[ssh_cfg], "db.internal", 5432)
        .await
        .expect("failed to open SSH tunnel");
}

Connecting Through the Tunnel

Point your database driver at the local bound port to route through the SSH tunnel:

let pg_conn_str = "postgresql://alice@127.0.0.1:54321/mydb";
let (client, connection) = tokio_postgres::connect(pg_conn_str, tokio_postgres::NoTls).await?;

Summary

  • DBX supports four SSH authentication methods—key files, passwords, SSH agents, and automatic probing—configured via SshTunnelConfig.auth_method.
  • The auth_method field explicitly selects the strategy; when empty, DBX falls back to probing key, then password, then agent.
  • Core implementation resides in crates/dbx-core/src/db/ssh_tunnel.rs, using plan_chain for multi-hop routing and TunnelManager for connection handling.
  • Configuration structure is defined in crates/dbx-core/src/models/connection.rs with fields for keys, passphrases, passwords, and agent sockets.
  • Database connectivity is achieved by binding a local port that forwards through the established SSH tunnel to the remote database host.

Frequently Asked Questions

What authentication methods does DBX support for SSH tunnel connections?

DBX supports four methods: private key files ("key"), plaintext passwords ("password"), SSH agent sockets ("agent"), and automatic probing ("none" or empty string). The auth_method field in SshTunnelConfig explicitly selects the method, with the UI offering "Private Key" and "Password" tabs for user configuration.

How does DBX handle SSH authentication if I don't specify an auth_method?

When auth_method is empty, DBX implements backward-compatible probing logic that attempts authentication in the following order: private key (if key_path is non-empty), password (if password is non-empty), and finally SSH agent (if use_ssh_agent is true). This logic is implemented in crates/dbx-core/src/db/ssh_tunnel.rs.

Can DBX use SSH agent forwarding for tunnel authentication?

Yes, DBX supports SSH agent authentication by setting auth_method to "agent" and either specifying ssh_agent_sock_path or enabling use_ssh_agent to default to the $SSH_AUTH_SOCK environment variable. This allows keyless authentication using locally loaded SSH keys without exposing private key files to DBX.

Where is the SSH tunnel logic implemented in the DBX source code?

The primary implementation is in crates/dbx-core/src/db/ssh_tunnel.rs, containing the TunnelManager, plan_chain function for multi-hop routing, and authentication method selection logic. The configuration struct is defined in crates/dbx-core/src/models/connection.rs (lines 138-176), while transport layer orchestration appears in crates/dbx-core/src/db/transport_layer_tunnel.rs.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →