Skip to content

SSH tunnel support #2136

Open
Open
@jarczakpawel

Description

@jarczakpawel

Is your feature request related to a problem? Please describe.

I'm using the native Linux build of HeidiSQL, which currently does not support SSH tunneling like the Windows version does. Since many MySQL/MariaDB servers are accessible only via SSH, this becomes a limitation on Linux.

Describe the solution you'd like

It would be great to have SSH tunnel support integrated directly into the Linux version of HeidiSQL, similar to how it works on Windows. Native SSH tunneling or even integration with an existing SSH agent would be extremely helpful.

Describe alternatives you've considered

As a workaround, I created an external Bash script that manages SSH tunnels. It opens a local port (e.g. 127.0.0.1:13306) and forwards it to the MySQL port on the remote host via SSH. I connect HeidiSQL to the local port as if it were a local database.

This approach works very reliably and may be useful for other users too. Here's a sample configuration and script:

#!/bin/bash

# ========================================
# SSH Tunnel Manager on Linux
# ========================================
# This script creates or restarts SSH tunnels to remote MySQL servers.
# Useful for tools like HeidiSQL running on Linux.
#
# -------------------------------
# CONFIGURATION INSTRUCTIONS:
#
# Each server entry looks like this:
#   [your_key]="ssh_host;ssh_user;ssh_password;local_port;remote_host;remote_port"
#
# Meaning of fields:
# - ssh_host      : The address of the SSH server (e.g. myserver.com)
# - ssh_user      : Username used for SSH login
# - ssh_password  : Password used for SSH login (used with sshpass)
# - local_port    : Local port on your machine (e.g. 13306)
# - remote_host   : Host seen by the SSH server (e.g. 127.0.0.1, or internal IP)
# - remote_port   : Remote MySQL port (usually 3306)
#
# Example:
#   [mydb]="host.example.com;john;secret123;13306;127.0.0.1;3306"
#
# After setting up, connect HeidiSQL (or similar tool) to:
#   127.0.0.1:<local_port>
# with MySQL credentials as if it were a direct connection.
# -------------------------------

declare -A servers=(
  [s1]="host1.example.com;user1;pass1;13306;127.0.0.1;3306"
  [s2]="host2.example.com;user2;pass2;13307;192.168.0.5;3307"
  [s3]="host3.example.com;user3;pass3;13308;10.0.0.15;3306"
)

# -------------------------------
# Tunnel handling logic
# -------------------------------

for name in "${!servers[@]}"; do
  IFS=';' read -r ssh_host ssh_user ssh_pass local_port remote_host remote_port <<< "${servers[$name]}"

  echo "[$name] Checking for existing tunnel on port $local_port..."

  pid=$(pgrep -f "$local_port:$remote_host:$remote_port")

  if [ -n "$pid" ]; then
    echo "[$name] Found running tunnel (PID: $pid), stopping..."
    kill "$pid"
    sleep 1
    if kill -0 "$pid" 2>/dev/null; then
      echo "[$name] ❌ Failed to stop process (PID: $pid)"
      continue
    else
      echo "[$name] Tunnel stopped successfully."
    fi
  fi

  echo "[$name] Starting new tunnel to $ssh_user@$ssh_host"
  echo "        Local: 127.0.0.1:$local_port → Remote: $remote_host:$remote_port"

  sshpass -p "$ssh_pass" ssh \
    -o ServerAliveInterval=60 \
    -o ServerAliveCountMax=3 \
    -o StrictHostKeyChecking=no \
    -N -f -L "$local_port:$remote_host:$remote_port" "$ssh_user@$ssh_host"

  if [ $? -eq 0 ]; then
    echo "[$name] ✅ Tunnel established on 127.0.0.1:$local_port$remote_host:$remote_port"
  else
    echo "[$name] ❌ Error establishing tunnel!"
  fi

done

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions