# 通过 SSH 隧道连接您的数据库

Source: https://support.kapsulehost.com/zh-cn/database-ssh-tunnel

您网站的数据库只在服务器自身的回环地址上监听，因此像 TablePlus、Sequel Ace、DBeaver 或 MySQL Workbench 这样的桌面工具无法直接连接到它。SSH 隧道可以为这些工具提供一个转发到数据库的本地端口，这正是在不将 MySQL 暴露到公网的情况下，为您的数据接入一个合适的图形界面工具的方法。

## 为什么需要隧道

打开**网站**，点击该网站，然后点击**数据库**。**连接详情**卡片显示主机为 `127.0.0.1`，端口为 `3306`。这不是一个占位符：该数据库确实只接受来自其自身运行所在机器的连接。公网上的任何设备都无法访问 3306 端口，这从根本上消除了一整类攻击。

SSH 隧道能够安全地弥补这一缺口。您的 SSH 客户端会在您的笔记本电脑上打开一个端口，对您发送到该端口的所有内容进行加密，然后从服务器内部将其交给数据库，效果就如同本地进程直接建立了连接一样。

![KPanel 中显示连接详情的数据库选项卡](https://support.kapsulehost.com/help/screenshots/database-ssh-tunnel.84df4ba6.webp)

## 您首先需要准备的内容

> **Note:** 隧道本质上是一条 SSH 连接，因此在进行以下任何操作之前，您需要先为该网站注册一个 SSH 密钥。请先按照[为网站添加 SSH 密钥](https://support.kapsulehost.com/zh-cn/adding-ssh-keys)中的步骤操作，然后再回到本文。

请准备好以下四项信息：

- **SSH 主机、端口和用户名**：在**设置**，然后**SSH 密钥**中的**连接详情**卡片内查看。
- **数据库名称、用户名和密码**：在**数据库**中查看。点击眼睛图标可显示密码，点击复制图标可将其复制到剪贴板。

如果数据库选项卡显示**该网站类型未配置数据库**，说明该网站没有数据库。静态网站和部分 Node.js 网站创建时不包含数据库。

## 从终端打开隧道

基本思路是：将一个本地端口转发到 SSH 连接远端的 `127.0.0.1:3306`。

```sh
ssh -N -L 3307:127.0.0.1:3306 <ssh-username>@<ssh-host> -p <ssh-port>
```

- `-L 3307:127.0.0.1:3306` 会在您的本机上打开 3307 端口，并将其转发到服务器回环接口的 3306 端口。
- `-N` 表示不运行 shell，只是保持隧道开启。
- 如果该网站所用的密钥不是您的默认密钥，请加上 `-i /path/to/key`。

请保持该终端窗口持续运行。只要它处于打开状态，您笔记本电脑上的 `127.0.0.1:3307` 就等同于该网站的数据库。

> **Tip:** 请在本地使用 3307 而非 3306。如果您自己的机器上已安装了 MySQL 或 MariaDB，那么 3306 端口很可能已被占用，隧道会因“地址已被占用”的错误而无法绑定。使用任意一个空闲的本地端口即可。

## 将数据库客户端指向隧道

在您的图形界面客户端中，创建一个普通的 MySQL 连接，并填入以下值：

| 字段 | 值 |
|---|---|
| 主机 | `127.0.0.1` |
| 端口 | `3307`（您转发的本地端口） |
| 用户 | 数据库选项卡中的**用户名** |
| 密码 | 数据库选项卡中的**密码** |
| 数据库 | 数据库选项卡中的**数据库**名称 |

请不要在“主机”字段中填入 SSH 主机。就客户端而言，它连接的其实是您自己机器上的数据库。

### 内置 SSH 选项卡的客户端

TablePlus、Sequel Ace、DBeaver 和 MySQL Workbench 都可以自行管理隧道，省去了保持终端开启的麻烦。请填写以下两组字段：

- **SSH 部分**：主机、端口、用户名以及来自 SSH 密钥页面的私钥文件。
- **数据库部分**：主机 `127.0.0.1`、端口 `3306`，以及数据库选项卡中的数据库名称、用户名和密码。

当客户端建立隧道时，数据库部分请使用 `3306`，而非您本地转发的端口。因为客户端是从服务器的视角进行连接的，所以它看到的是真实端口。

## 改用 phpMyAdmin

如果您只是想快速查看某个表，其实完全不需要隧道。数据库选项卡中有一个 **phpMyAdmin** 卡片，带有**打开 phpMyAdmin** 按钮。它会通过 KPanel 为您完成登录，因此无需记住另外的密码，并且会在新标签页中打开，自动指向该网站的数据库。

对于浏览数据、执行一次性查询或核对某个数值，phpMyAdmin 是更快捷的选择。而对于大型导出、架构调整，以及任何您想要编写脚本处理的工作，通过隧道使用桌面客户端会更合适。浏览器方式请参阅[使用 phpMyAdmin](https://support.kapsulehost.com/zh-cn/sites-phpmyadmin)。

## 通过隧道执行查询与导出

隧道开启后，标准的命令行工具可以照常使用，只需指向您本地转发的端口：

```sh
mysql -h 127.0.0.1 -P 3307 -u <db-user> -p <db-name>

mysqldump -h 127.0.0.1 -P 3307 -u <db-user> -p <db-name> > backup.sql
```

> **Warning:** 手动导出只是一份便捷备份，并不能替代真正的备份策略。它只能反映您运行该操作那一刻的数据状态，并且只保存在您当时所用的那台笔记本电脑上。KapsuleHost 本身已经每天为网站自动创建备份，并保留 30 天。在依赖本地的 `.sql` 文件之前，请先参阅[创建备份](https://support.kapsulehost.com/zh-cn/taking-a-backup)。

## 故障排查

**打开隧道时提示“地址已被占用”。** 说明您机器上的该本地端口已被其他程序占用。请换一个端口，例如 `-L 3399:127.0.0.1:3306`，并在客户端中将端口改为与之一致。

**数据库客户端提示“连接被拒绝”。** 说明隧道尚未建立。请检查 SSH 终端是否仍在运行、是否没有报错，并确认客户端中填写的端口与 `-L` 参数中的本地端口一致。

**SSH 已连接，但客户端仍然超时。** 请确认您转发的目标是 `127.0.0.1:3306`，而不是公开主机名。转发到公开主机名会要求服务器通过公网访问数据库，而这正是被阻止的行为。

**提示“用户访问被拒绝”。** 说明 SSH 登录已经成功，但 MySQL 凭据有误。请使用复制图标重新从数据库选项卡中复制用户名和密码，而不要手动输入，并确认您连接的数据库名称是否正确。

**在尚未连接到 MySQL 之前就提示“Permission denied (publickey)”。** 这属于 SSH 层面的问题，而非数据库问题。请参阅[为网站添加 SSH 密钥](https://support.kapsulehost.com/zh-cn/adding-ssh-keys)中的故障排查部分进行处理。

## 后续可查阅内容

- [使用 SFTP 上传文件](https://support.kapsulehost.com/zh-cn/sftp-access)使用与文件传输相同的 SSH 凭据。
- [使用 phpMyAdmin](https://support.kapsulehost.com/zh-cn/sites-phpmyadmin)，用于基于浏览器的数据库操作。
- [从备份恢复](https://support.kapsulehost.com/zh-cn/restoring-from-backup)，适用于某次查询造成的影响超出预期的情况。
