logoDocs

开发者指南:通过 SSH 隧道访问内部服务

目的: 本指南说明如何安全地访问部署在 AWS EC2 服务器上、未直接暴露于公网的内部开发服务(如数据库、Registry UI)。我们使用 SSH 隧道技术,通过已建立的安全 SSH 连接来转发网络流量。

背景: 为了安全起见,只有 Docker Registry 通过负载均衡器 (ELB) 对外提供 HTTPS 访问。其他服务(如 Registry UI、MongoDB、Redis、PostgreSQL)仅在服务器内部监听 127.0.0.1 地址,无法从外部直接访问。SSH 隧道允许你将本地计算机上的一个端口映射到服务器上的内部端口,从而安全地访问这些服务。

前提条件:

  1. SSH 客户端: 你的本地计算机需要安装 SSH 客户端 (Linux/macOS/WSL 通常自带 ssh 命令,Windows 可以使用 OpenSSH in PowerShell/CMD, PuTTY, 或 Windows Terminal)。
  2. SSH 私钥: 你需要拥有访问服务器 devadmin 用户的 SSH 私钥文件 (例如 ~/.ssh/id_ed25519 或 your_key.pem)。此密钥的公钥部分必须已添加到服务器上 devadmin 用户的 ~/.ssh/authorized_keys 文件中。
  3. 服务器信息:
    • 服务器的公网 IP 地址: <服务器IP> (由管理员提供)
    • 服务器的 SSH 端口 (非标准): <你的SSH端口> (由管理员提供, 通常不是 22)
    • SSH 用户名: devadmin

基本隧道命令格式:

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 隧道命令。保持该命令的终端窗口持续运行。

  1. 访问 Docker Registry UI
    • 远程服务端口: 8081

    • 建立隧道 (选择本地端口,例如也用 8081):

      ssh -N -L 8081:127.0.0.1:8081 devadmin@<服务器IP> -i <你的私钥文件路> -p <你的SSH端>
    • 访问方式: 在你的本地浏览器中打开 http://localhost:8081

  2. 访问 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 文件中设置)

  3. 访问 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 文件中设置)

  4. 访问 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 上) 来简化操作。

  1. 编辑或创建配置文件: 打开你的 SSH 配置文件 (如果文件不存在,则创建它)。

  2. 添加主机配置: 在文件中添加类似以下的配置块,替换尖括号中的占位符:

    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 60
    • Host dev-server: 这是你为这个连接设置的别名,可以自定义。
    • HostName, User, Port, IdentityFile: 对应你的服务器信息和私钥路径。
    • LocalForward <本地端口> 127.0.0.1:<远程端口>: 为每个需要转发的服务添加一行。
  3. 保存文件并设置权限 (Linux/macOS/WSL): 确保配置文件的权限安全:chmod 600 ~/.ssh/config

  4. 使用简化命令建立隧道: 现在,你只需要在终端运行以下命令即可建立所有配置好的隧道:

    ssh -N dev-server

    同样,保持这个终端窗口运行以维持隧道。

使用 PuTTY 设置隧道 (Windows)

如果你使用 PuTTY 而不是命令行 ssh

  1. 启动 PuTTY。
  2. Session 类别中:
    • 输入服务器的 IP 地址或主机名到 Host Name (or IP address) 字段。
    • 输入服务器的 SSH 端口到 Port 字段 (例如 2222)。
  3. 在左侧的 Category 树中,导航到 Connection -> SSH -> Auth
    • 点击 Browse... 按钮,选择你的 .ppk 私钥文件 (PuTTY 需要 .ppk 格式)。
      • 注意: 如果你只有 .pem 文件,需要先使用 PuTTYgen 工具进行转换:
        1. 打开 PuTTYgen。
        2. 点击 Load 按钮,选择你的 .pem 文件 (确保文件类型选择为 "All Files (.)")。
        3. PuTTYgen 会加载密钥信息。
        4. 点击 Save private key 按钮,将密钥保存为 .ppk 格式 (建议设置密码保护)。
  4. 在左侧的 Category 树中,导航到 Connection -> SSH -> Tunnels
    • Source port 字段中,输入你希望在本地使用的端口号 (例如 8081 用于 Registry UI)。
    • Destination 字段中,输入 127.0.0.1:<远程服务端口> (例如 127.0.0.1:8081)。
    • 确保选中 LocalAuto 单选按钮。
    • 点击 Add 按钮。你会看到转发规则出现在下方的列表中 (例如 L8081 127.0.0.1:8081)。
    • 重复此步骤 为你需要访问的其他服务添加隧道规则 (例如,Source port 27017, Destination 127.0.0.1:27017,然后点击 Add)。
  5. (可选) 返回到 Session 类别,在 Saved Sessions 字段中输入一个名称,然后点击 Save,以便下次快速加载这些设置。
  6. 点击 Open 按钮连接到服务器。输入用户名 devadmin (如果提示)。
  7. 一旦 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 命令中使用多个 -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端>
  • 需要帮助? 如果遇到问题,请联系设置服务器的管理员,并提供你尝试的命令和遇到的错误信息。