共253行

服务器A-B-SSH隧道

2026-05-27 12:57:34

需求

  1. 建立持久 SSH 隧道
  2. 在 A 上直接连接 B 的数据库
  3. 隧道全程保持畅通
  4. 用完安全关闭隧道

一、方案说明(一句话看懂)

服务器A(上海) 上执行一条命令,建立一条后台常驻的 SSH 隧道,把 A 本地的一个端口(比如 3307)映射到 服务器B(杭州) 的数据库端口(3306)。
之后你在 A 上连接 localhost:3307 = 直接操作 B 的数据库,全程内网安全、不掉线


二、最终可用命令(直接复制执行)

1. 在服务器A 上执行:建立持久 SSH 隧道

ssh -fN -L 3307:127.0.0.1:3306 用户名@B的公网IP -o ServerAliveInterval=30 -o ServerAliveCountMax=3

命令解释(不用改,直接用)

执行后输入 B 服务器的密码,隧道就后台常驻了。


2. 在服务器A 上连接 B 的数据库

隧道建好后,直接在 A 上执行

MySQL 示例

mysql -h 127.0.0.1 -P 3307 -u数据库账号 -p

你也可以用程序连接(Python/Java/Go 等)

主机:127.0.0.1
端口:3307
账号:你的数据库账号
密码:你的数据库密码

这就是在操作服务器 B 上的数据库!


3. 保持隧道畅通

这条命令自带 保活机制


4. 结束操作 → 安全关闭隧道

第一步:查看隧道进程 ID

ps aux | grep "ssh -fN -L 3307"

第二步:杀死进程(关闭隧道)

kill 进程ID

三、超级简化版(你只需要记 3 条命令)

1. 开隧道(A 上执行)

ssh -fN -L 3307:127.0.0.1:3306 user@B公网IP -o ServerAliveInterval=30

2. 连数据库(A 上执行)

mysql -h127.0.0.1 -P3307 -u账号 -p

3. 关隧道

pkill -f "ssh -fN -L 3307"

四、必须满足的条件(非常简单)

  1. 服务器 B 开放 22 端口(SSH)(你本来就能 SSH 连接,所以已经满足)
  2. 服务器 B 的数据库只允许本地连接(更安全)
  3. 不需要开放数据库 3306 到公网!

五、相关脚本

这里提供一键启动、一键关闭脚本,附带使用说明、保活配置、异常处理,开箱即用(以MySQL 3306、本地映射端口3307为例)。

环境:CentOS / Ubuntu 通用;提前配置好SSH免密登录(避免反复输密码)


前置:配置SSH免密登录(必做)

服务器A执行,实现免密连接B,脚本才能后台自动运行:

# 1. 生成密钥(一路回车,无需设置密码)
ssh-keygen -t ed25519

# 2. 推送公钥到服务器B
ssh-copy-id 你的B服务器用户名@B公网IP

测试免密:ssh 用户名@B公网IP,无需输密码即成功。


一、一键启动隧道脚本 ssh_tunnel_start.sh

1. 创建脚本文件

vim ssh_tunnel_start.sh

粘贴以下内容,修改两处自定义参数

#!/bin/bash
# 配置项 请根据实际修改
LOCAL_PORT=3307          # A机器本地映射端口
REMOTE_DB_PORT=3306      # B机器数据库端口
SSH_USER="b_user"         # B服务器SSH用户名
SSH_IP="B的公网IP"        # B服务器公网IP

# 检查端口是否已被占用
if netstat -tulpn | grep -q ":$LOCAL_PORT " ;then
    echo "端口 $LOCAL_PORT 已占用,隧道已存在,无需重复启动"
    exit 0
fi

# 启动SSH隧道 + 保活(后台运行)
ssh -fN -L $LOCAL_PORT:127.0.0.1:$REMOTE_DB_PORT \
-o ServerAliveInterval=30 \
-o ServerAliveCountMax=3 \
$SSH_USER@$SSH_IP

# 校验启动结果
if [ $? -eq 0 ];then
    echo "✅ SSH隧道启动成功,本地端口:$LOCAL_PORT"
else
    echo "❌ SSH隧道启动失败"
fi

2. 授权 + 执行启动

# 添加执行权限
chmod +x ssh_tunnel_start.sh

# 启动隧道
./ssh_tunnel_start.sh

二、一键关闭隧道脚本 ssh_tunnel_stop.sh

1. 创建脚本文件

vim ssh_tunnel_stop.sh

粘贴内容(端口和上面保持一致即可):

#!/bin/bash
LOCAL_PORT=3307

# 匹配隧道进程并终止
pkill -f "ssh -fN -L $LOCAL_PORT"

if [ $? -eq 0 ];then
    echo "✅ SSH隧道已关闭"
else
    echo "ℹ️ 未找到运行中的隧道"
fi

2. 授权 + 执行关闭

chmod +x ssh_tunnel_stop.sh

# 关闭隧道
./ssh_tunnel_stop.sh

三、日常使用流程(完整操作)

  1. 开启隧道
./ssh_tunnel_start.sh

隧道后台常驻、自动保活,全程不断连。

  1. 在A服务器连接B的数据库
# MySQL 连接示例
mysql -h 127.0.0.1 -P 3307 -u 数据库账号 -p

也可用于代码、可视化工具(Navicat/DBeaver)连接 127.0.0.1:3307

  1. 操作完成,关闭隧道
./ssh_tunnel_stop.sh

四、补充常用命令 & 排错

1. 查看隧道是否在运行

ps aux | grep ssh
netstat -tulpn | grep 3307

2. 端口冲突处理

3307 被占用,修改脚本内 LOCAL_PORT 为任意未占用端口(如 3308、3309)。

3. PostgreSQL 适配(数据库端口改为5432)

只修改脚本内这一行即可:

REMOTE_DB_PORT=5432

连接命令:

psql -h 127.0.0.1 -p 3307 -U 数据库用户名 库名

4. 安全说明


五、可选:临时前台隧道(调试用)

如果想前台运行、实时看日志(关闭终端即断隧道),执行:

ssh -L 3307:127.0.0.1:3306 b_user@B公网IP

Ctrl+C 直接断开隧道。