开发者指南:通过 SSH 隧道访问内部服务
目的: 本指南说明如何安全地访问部署在 AWS EC2 服务器上、未直接暴露于公网的内部开发服务(如数据库、Registry UI)。我们使用 SSH 隧道技术,通过已建立的安全 SSH 连接来转发网络流量。
背景: 为了安全起见,只有 Docker Registry 通过负载均衡器 (ELB) 对外提供 HTTPS 访问。其他服务(如 Registry UI、MongoDB、Redis、PostgreSQL)仅在服务器内部监听 127.0.0.1 地址,无法从外部直接访问。SSH 隧道允许你将本地计算机上的一个端口映射到服务器上的内部端口,从而安全地访问这些服务。
前提条件:
- SSH 客户端: 你的本地计算机需要安装 SSH 客户端 (Linux/macOS/WSL 通常自带 ssh 命令,Windows 可以使用 OpenSSH in PowerShell/CMD, PuTTY, 或 Windows Terminal)。
- SSH 私钥: 你需要拥有访问服务器 devadmin 用户的 SSH 私钥文件 (例如 ~/.ssh/id_ed25519 或 your_key.pem)。此密钥的公钥部分必须已添加到服务器上 devadmin 用户的 ~/.ssh/authorized_keys 文件中。
- 服务器信息:
- 服务器的公网 IP 地址:
<服务器IP>(由管理员提供) - 服务器的 SSH 端口 (非标准):
<你的SSH端口>(由管理员提供, 通常不是 22) - SSH 用户名:
devadmin
- 服务器的公网 IP 地址:
基本隧道命令格式:
ssh -N -L <本地端口>:127.0.0.1:<远程服务端口> devadmin@<服务器IP> -i <你的私钥文件路径> -p <你的SSH端口>- -N: 告诉 SSH 不要执行远程命令,只建立端口转发。运行此命令后,终端看起来会“卡住”,这是正常的,保持此终端窗口打开状态以维持隧道。
- -L
<本地端口>:127.0.0.1:<远程服务端口>:<本地端口>: 你本地计算机上一个未被占用的端口号。你将通过访问 localhost:<本地端口>来访问远程服务。- 127.0.0.1: 这是指远程服务器的本地回环地址。
<远程服务端口>: 远程服务器上内部服务实际监听的端口。
- devadmin@
<服务器IP>: SSH 连接的目标。 - -i
<你的私钥文件路径>: 指定你的私钥文件。 - -p
<你的SSH端口>: 指定服务器的 SSH 端口。
访问具体服务:
重要: 对于每个需要访问的服务,你需要运行一个对应的 SSH 隧道命令。保持该命令的终端窗口持续运行。
- 访问 Docker Registry UI
-
远程服务端口: 8081
-
建立隧道 (选择本地端口,例如也用 8081):
ssh -N -L 8081:127.0.0.1:8081 devadmin@<服务器IP> -i <你的私钥文件路径> -p <你的SSH端口> -
访问方式: 在你的本地浏览器中打开
http://localhost:8081。
-
- 访问 MongoDB
-
远程服务端口: 27017
-
建立隧道 (选择本地端口,例如也用 27017):
ssh -N -L 27017:127.0.0.1:27017 devadmin@<服务器IP> -i <你的私钥文件路径> -p <你的SSH端口> -
访问方式 (使用 MongoDB Shell mongosh 或其他客户端):
# 使用管理员用户连接 (替换 <你的管理员用户名> 和 <极其复杂的密码>) mongosh "mongodb://<你的管理员用户名>:<极其复杂的密码>@localhost:27017/?authSource=admin" # 或使用应用用户连接 (替换 <myappuser>, <另一个复杂密码>, <myappdb>) # mongosh "mongodb://myappuser:<另一个复杂密码>@localhost:27017/myappdb"(请向管理员获取正确的用户名和密码,这些通常在服务器的
docker-compose-internal.yml文件中设置)
-
- 访问 Redis
-
远程服务端口: 6379
-
建立隧道 (选择本地端口,例如也用 6379):
ssh -N -L 6379:127.0.0.1:6379 devadmin@<服务器IP> -i <你的私钥文件路径> -p <你的SSH端口> -
访问方式 (使用 redis-cli 或其他客户端):
# 替换 <极其复杂的密码> redis-cli -h localhost -p 6379 -a <极其复杂的密码> # 连接后输入 PING,应返回 PONG(请向管理员获取正确的密码,这通常在服务器的
docker-compose-internal.yml文件中设置)
-
- 访问 PostgreSQL
-
远程服务端口: 5432
-
建立隧道 (选择本地端口,例如也用 5432):
ssh -N -L 5432:127.0.0.1:5432 devadmin@<服务器IP> -i <你的私钥文件路径> -p <你的SSH端口> -
访问方式 (使用 psql 或其他客户端):
# 使用 postgres 超级用户连接 (替换 <极其复杂的密码_用于postgres用户>) psql -h localhost -p 5432 -U postgres -W # 会提示输入密码 # 使用应用用户连接 (替换 <myappuser>, <myappdb>, <另一个极其复杂的密码>) psql -h localhost -p 5432 -U myappuser -d myappdb -W # 会提示输入密码(请向管理员获取正确的用户名、密码和数据库名,这些通常在服务器的
docker-compose-internal.yml文件中设置)
-
使用 SSH 配置文件简化连接 (可选)
对于经常需要连接和建立隧道的开发者,每次输入完整的 ssh 命令会很繁琐。你可以使用 SSH 客户端配置文件 (~/.ssh/config 在 Linux/macOS/WSL 上,或 %USERPROFILE%\\.ssh\\config 在 Windows 上) 来简化操作。
-
编辑或创建配置文件: 打开你的 SSH 配置文件 (如果文件不存在,则创建它)。
-
添加主机配置: 在文件中添加类似以下的配置块,替换尖括号中的占位符:
Host dev-server HostName <服务器IP> User devadmin Port <你的SSH端口> IdentityFile <你的私钥文件路径> # --- 隧道配置 --- # 将本地 8081 转发到远程 8081 (Registry UI) LocalForward 8081 127.0.0.1:8081 # 将本地 27017 转发到远程 27017 (MongoDB) LocalForward 27017 127.0.0.1:27017 # 将本地 6379 转发到远程 6379 (Redis) LocalForward 6379 127.0.0.1:6379 # 将本地 5432 转发到远程 5432 (PostgreSQL) LocalForward 5432 127.0.0.1:5432 # --- 可选: 保持连接活动 --- # ServerAliveInterval 60Host dev-server: 这是你为这个连接设置的别名,可以自定义。HostName,User,Port,IdentityFile: 对应你的服务器信息和私钥路径。LocalForward <本地端口> 127.0.0.1:<远程端口>: 为每个需要转发的服务添加一行。
-
保存文件并设置权限 (Linux/macOS/WSL): 确保配置文件的权限安全:
chmod 600 ~/.ssh/config。 -
使用简化命令建立隧道: 现在,你只需要在终端运行以下命令即可建立所有配置好的隧道:
ssh -N dev-server同样,保持这个终端窗口运行以维持隧道。
使用 PuTTY 设置隧道 (Windows)
如果你使用 PuTTY 而不是命令行 ssh:
- 启动 PuTTY。
- 在 Session 类别中:
- 输入服务器的 IP 地址或主机名到 Host Name (or IP address) 字段。
- 输入服务器的 SSH 端口到 Port 字段 (例如
2222)。
- 在左侧的 Category 树中,导航到 Connection -> SSH -> Auth。
- 点击 Browse... 按钮,选择你的
.ppk私钥文件 (PuTTY 需要.ppk格式)。- 注意: 如果你只有
.pem文件,需要先使用 PuTTYgen 工具进行转换:- 打开 PuTTYgen。
- 点击 Load 按钮,选择你的
.pem文件 (确保文件类型选择为 "All Files (.)")。 - PuTTYgen 会加载密钥信息。
- 点击 Save private key 按钮,将密钥保存为
.ppk格式 (建议设置密码保护)。
- 注意: 如果你只有
- 点击 Browse... 按钮,选择你的
- 在左侧的 Category 树中,导航到 Connection -> SSH -> Tunnels。
- 在 Source port 字段中,输入你希望在本地使用的端口号 (例如
8081用于 Registry UI)。 - 在 Destination 字段中,输入
127.0.0.1:<远程服务端口>(例如127.0.0.1:8081)。 - 确保选中 Local 和 Auto 单选按钮。
- 点击 Add 按钮。你会看到转发规则出现在下方的列表中 (例如
L8081 127.0.0.1:8081)。 - 重复此步骤 为你需要访问的其他服务添加隧道规则 (例如,Source port
27017, Destination127.0.0.1:27017,然后点击 Add)。
- 在 Source port 字段中,输入你希望在本地使用的端口号 (例如
- (可选) 返回到 Session 类别,在 Saved Sessions 字段中输入一个名称,然后点击 Save,以便下次快速加载这些设置。
- 点击 Open 按钮连接到服务器。输入用户名
devadmin(如果提示)。 - 一旦 SSH 会话建立并保持活动状态,你在第 4 步中配置的隧道就会生效。你可以通过访问
localhost:<本地端口>来访问相应的服务。
重要提示和故障排除:
- 保持隧道运行: 建立隧道的终端窗口 (或 PuTTY 会话) 必须保持打开状态。关闭将断开隧道。
- 保护私钥: 你的 SSH 私钥 (
.pem或.ppk文件) 是访问服务器的关键,请妥善保管,设置严格的文件权限,不要泄露给任何人。 - 本地端口冲突: 如果你选择的
<本地端口>已被占用,SSH 命令或 PuTTY 会失败。请更换一个本地端口号 (例如 8082 而不是 8081),并在访问时使用新的localhost:<新本地端口>地址。 - 连接失败?
- 确认你的 SSH 连接本身是否正常 (不带
-N -L参数直接 SSH 是否能登录)。 - 确认远程服务是否在服务器上正常运行 (
docker ps查看容器状态)。 - 确认你使用的
<远程服务端口>是否正确。 - 确认服务器的防火墙 (
firewalld) 没有意外阻止127.0.0.1上的连接 (通常不会)。 - 确认你的本地防火墙没有阻止你访问
localhost:<本地端口>。
- 确认你的 SSH 连接本身是否正常 (不带
- 多个隧道: 你可以在一个 SSH 命令中使用多个
-L参数来同时建立多个隧道,或者为每个隧道打开一个单独的终端窗口 (除非你使用了 SSH Config)。
示例:同时建立 UI 和 MongoDB 隧道
ssh -N -L 8081:127.0.0.1:8081 -L 27017:127.0.0.1:27017 devadmin@<服务器IP> -i <你的私钥文件路径> -p <你的SSH端口>- 需要帮助? 如果遇到问题,请联系设置服务器的管理员,并提供你尝试的命令和遇到的错误信息。