SSH 隧道:从本地访问远程计算服务

SSH 本地端口转发可以将本地应用发出的 TCP 请求,经 SSH 连接送到远端主机可访问的服务。例如,本地应用访问 127.0.0.1:11434,远端 SSH 服务器再连接它自己的 127.0.0.1:11434。业务代码在本地运行,推理服务在远端运行。

建立转发前

  1. 确认自己有远端 SSH 与目标服务的使用权限,并从可信渠道取得 SSH 主机密钥指纹。首次连接时先核对指纹,或让管理员提供已验证的 known_hosts 条目;主机密钥发生变化时应先核实原因。
  2. 确认本地 SSH 客户端、账号、私钥或 SSH agent 可用;远端服务正在运行,且监听地址和端口与实际配置一致。
  3. 确认本地端口未被占用。以下示例使用本地和远端的 11434,只是示意,实际值按服务配置替换。

使用 OpenSSH 建立本地转发

ssh -p 50001 -N \
  -o StrictHostKeyChecking=yes \
  -o ExitOnForwardFailure=yes \
  -L 127.0.0.1:11434:127.0.0.1:11434 \
  your_username@your.remote.server

-L 中第一个地址和端口是本机监听点;第二个地址和端口由远端 SSH 服务器连接,因此此处的 127.0.0.1 指远端本机。-N 表示不执行远程命令。StrictHostKeyChecking=yes 要求已核验的主机密钥;未知密钥或密钥变更会使连接失败。ExitOnForwardFailure=yes 在指定的转发监听无法建立时退出,但远端服务是否能接受连接仍需另行检查。OpenSSH ssh(1) · ssh_config(5)

命令以前台方式运行;在另一个终端使用本地应用访问 http://127.0.0.1:11434。如果服务提供健康检查接口,可按它的文档访问对应路径,例如:

curl --fail --show-error --max-time 5 http://127.0.0.1:11434/health

/health 并非所有服务都提供。HTTP 404、连接拒绝或超时都需要结合服务日志与实际 API 排查;监听建立成功不代表模型已就绪或请求成功。结束后回到 SSH 终端按 Ctrl+C 关闭隧道。

在 Python 中运行 SSH

需要由脚本管理进程时,可以调用本机 OpenSSH,将每个参数作为单独的列表元素传入,而不是拼接 shell 命令:

import subprocess
 
command = [
    "ssh", "-p", "50001", "-N",
    "-o", "StrictHostKeyChecking=yes",
    "-o", "ExitOnForwardFailure=yes",
    "-L", "127.0.0.1:11434:127.0.0.1:11434",
    "your_username@your.remote.server",
]
 
try:
    # 前台等待;SSH 退出码非零时抛出 CalledProcessError。
    subprocess.run(command, check=True)
except subprocess.CalledProcessError as exc:
    print(f"SSH 连接或本地转发失败,退出码:{exc.returncode}")
    raise SystemExit(exc.returncode) from exc

该示例持续等待 SSH 进程;应用应在另一个进程或终端运行。要实现后台管理、重连、超时和优雅关闭,需要在自己的程序中明确进程生命周期和错误处理,不要把固定等待时间当作就绪证明。

使用 Paramiko 时的身份校验

Paramiko 可用于 Python 中的 SSH 连接和通道管理。先加载已核验的主机密钥,并对未知密钥保持拒绝策略:

import paramiko
 
with paramiko.SSHClient() as client:
    client.load_system_host_keys()  # 读取用户的 known_hosts
    client.set_missing_host_key_policy(paramiko.RejectPolicy())
    client.connect(
        hostname="your.remote.server",
        port=50001,
        username="your_username",
        timeout=10,
    )
    print("已通过 SSH 主机密钥与用户身份验证")

Paramiko 默认会尝试本地密钥文件或 SSH agent;实际认证方式由环境配置决定。它的默认未知主机密钥策略是拒绝。此段只验证 SSH 连接,没有实现端口转发;如自行实现转发,还需正确处理双向部分写入、EOF、连接关闭、超时和并发,并单独测试。Paramiko SSHClient 文档

失败时先检查什么

  • 主机密钥错误:通过独立可信渠道核验指纹与主机身份,不关闭校验,也不盲目删除旧记录。
  • 本地端口占用:检查占用者,选用授权且空闲的端口;转发绑定到 127.0.0.1 可以避免默认把服务暴露给局域网。
  • SSH 已连接但请求失败:检查远端服务是否运行、目标地址是否可由 SSH 服务器访问,以及实际 API 路径和认证要求。
  • 凭据和数据:不要把密码、私钥或 API 密钥写入示例、日志和版本库;SSH 只保护隧道链路,服务本身的授权、日志和本地访问控制仍需单独考虑。

本文根据 OpenSSH 与 Paramiko 官方文档整理,未连接真实 SSH 服务器或验证任何具体模型服务。