如何通过 SSH 隧道访问远程数据库?

数据库在内网不能直接访问,需要通过跳板机/SSH 隧道连接远程 MySQL/PostgreSQL/Redis

解决方案

本地端口转发访问远程数据库(推荐) 推荐

# MySQL(远程 3306 → 本地 3307)
ssh -fNL 3307:localhost:3306 user@db-server
mysql -h 127.0.0.1 -P 3307 -u dbuser -p

# PostgreSQL(远程 5432 → 本地 5433)
ssh -fNL 5433:localhost:5432 user@db-server
psql -h 127.0.0.1 -p 5433 -U dbuser -d mydb

# Redis(远程 6379 → 本地 6380)
ssh -fNL 6380:localhost:6379 user@db-server
redis-cli -h 127.0.0.1 -p 6380

-f 后台运行,-N 不开 shell,-L 本地端口:目标:目标端口。隧道建立后,用本地客户端连接 127.0.0.1:本地端口即可。这里 localhost 是相对于 SSH 服务器的。

适用场景:数据库和 SSH 服务器在同一台机器上,或 SSH 服务器可以直接访问数据库

通过跳板机访问内网数据库

# 数据库在内网 db.internal:3306,通过跳板机 bastion 访问
ssh -fNL 3307:db.internal:3306 user@bastion
mysql -h 127.0.0.1 -P 3307 -u dbuser -p

# 或在 ~/.ssh/config 中配置
# Host db-tunnel
#   HostName bastion.example.com
#   User jump-user
#   LocalForward 3307 db.internal:3306
#   LocalForward 5433 pg.internal:5432

# 然后直接:ssh -fN db-tunnel

当数据库不在 SSH 服务器本机时,目标地址填数据库的内网地址。SSH 服务器作为中转,将流量转发到内网数据库。

适用场景:数据库在内网,需要通过跳板机/堡垒机中转访问

使用 autossh 保持隧道稳定

# 安装 autossh
sudo apt install autossh  # Debian/Ubuntu
brew install autossh      # macOS

# 使用 autossh 建立自动重连的隧道
autossh -M 0 -fNL 3307:localhost:3306 user@db-server \
  -o ServerAliveInterval=30 \
  -o ServerAliveCountMax=3

# 配合 systemd 开机自启
# /etc/systemd/system/ssh-tunnel-db.service
# [Unit]
# Description=SSH Tunnel to DB
# After=network.target
# [Service]
# ExecStart=/usr/bin/autossh -M 0 -NL 3307:localhost:3306 user@db-server
# Restart=always
# [Install]
# WantedBy=multi-user.target

autossh 监控 SSH 连接状态,断开后自动重连。-M 0 表示使用 SSH 自身的心跳机制检测连接状态。配合 systemd 可以实现开机自启和崩溃重启。

适用场景:需要长期稳定的数据库隧道,不能容忍连接中断

注意事项

隧道断开后本地连接也会断开,生产环境建议用 autossh 或 systemd 保活
不要在本地端口使用和远程相同的端口号,避免与本地服务冲突
确保 SSH 服务器允许 TCP 转发(AllowTcpForwarding yes)

相关命令