Skip to content

SSH 隧道

利用 SSH 协议实现端口转发,支持多级跳板机连接,安全可靠。

基础使用

bash
ssh -L 3307:123.123.14.120:3306 username@223.223.14.220 -N

image-20251019131901009

参数解释:

  • -L 3307:123.123.14.120:3306:设置端口转发。将你本地电脑的3307端口映射到目标服务器A(123.123.14.120)的MySQL端口(3306)。
  • username@223.223.14.220:这是服务器B的SSH登录用户名和公网IP。
  • -N:表示不执行远程命令,仅建立隧道。

执行后,系统会提示你输入服务器B的SSH密码。连接成功后,这个SSH隧道就在后台运行了。

🗄️ 连接MySQL数据库

SSH隧道建立后,你的电脑(192.168.3.1)上连接本机3307端口,SSH隧道就会将请求转发到服务器A的3306端口。

进阶使用

image-20260410121749201

场景:要实现从电脑 A 连接到 SFTP 服务器 D,目前的链路是:A (Windows) --[OpenVPN]--> B (CentOS) --[白名单]--> C (CentOS) --[白名单]--> D (SFTP)

使用 SSH 配置文件(推荐)

  1. 在 Windows A 上打开目录 %USERPROFILE%.ssh\(通常是 C:\Users\你的用户名.ssh\)。

  2. 新建或编辑一个名为 config 的文件(无后缀),写入以下内容:

    shell
    # 第一跳:中转机器 B
    Host serverB 		# 服务器别名,可以随便取
        HostName [B的内网VPN IP] [外网ip,如果有的话]
        User [B的用户名,登录服务器的用户名一般为root]
        IdentityFile ~/.ssh/key.pem 		# 如果是非密码登录而是通过密钥登录,指定密钥位置
    	PreferredAuthentications publickey 	# 指定登录方式为密钥
    
    # 第二跳:中转机器 C
    Host serverC
        HostName [C的IP]
        User [C的用户名]
        ProxyJump serverB # 通过 B 跳转
    
    # 最终目标:SFTP 服务器 D
    Host serverD
        HostName [D的IP]
        User [D的SFTP用户名]
        Port 22  # 如果SFTP不是22端口请修改
        ProxyJump serverC # 通过 C 跳转
  3. 配置完成后只需要执行命令 sftp serverD 即可链接,但是这种是命令行里面的,如果要使用工具还得继续。

  4. 要通过 Xftp 连接 D,最稳定且简单的方法是:先用命令行建立一个"本地隧道",然后让 Xftp 走这个隧道。

    第一步在 PowerShell 建立隧道(打通 A 到 D 的大桥)

    利用我们之前配置好的 config 文件(确保你已经按上一条回答配置好了 serverB, serverC, serverD)。

    powershell
    # 这条命令的意思是:把本地的 2022 端口,通过跳转直接映射到 D 的 SFTP 端口
    ssh -L 2022:localhost:2022 serverD -N

    如果你没配 config,或者想一行命令解决,可以用这个长命令,并保持这个窗口不要关闭

    ssh -L 2022:[D的IP]:[D的端口] [B用户]@[B_IP] -t ssh -L [D的端口]:[D的IP]:[D的端口] [C用户]@[C_IP] -N

    第二步配置 Xftp 连接

    现在,对于 Xftp 来说,服务器 D 就像是在你本地电脑的 2022端口上一样。

    1. 打开 Xftp,点击"新建"会话。

    2. 常规设置: 主机 (Host): 127.0.0.1 (代表你本地)协议: SFTP端口号 (Port): 2022(对应上面命令里的本地端口)

    3. 身份验证 (Authentication):

      用户名: 输入 服务器 D 的登录用户名。

      密码/密钥: 输入 服务器 D 的登录密码或私钥。

    4. 点击"连接"。

    如果遇到连接失败

    1. 隧道命令的逻辑错误:你使用的 ssh -L 2022:localhost:2022 serverD 意思是"连接到 D,并将 D 自己的 2022端口转发到 A"。但你的目的是"通过 C 访问 D"。
    2. SFTP 权限限制:如果服务器 D 做了安全限制(比如只允许 SFTP 不允许执行 Shell 命令),那么 -N 参数建立隧道可能会被 D 拒绝。
  5. 推荐的最稳妥方案:通过 C 建立隧道

    不要尝试直接把隧道打到 D,而是把隧道打到 C,让 C 帮你转发流量到 D。这样你只需要输入 B 和 C 的密码/密钥,而 D 的密码是在 Xftp 登录时才输入的

    powershell
    # 注意:这里我们只连到 serverC
    ssh -L 2022:[D的实际IP]:[D的端口] serverC -N -v
    • 2022: 是你 A 电脑上监听的端口。
    • [D的实际IP]: 注意! 这里填的是在 C 机器看来,D 的 IP 地址。
    • [D的端口]: D 的 SFTP 端口(通常是 22)。
    • serverC: 使用你 config 里配置的跳转规则(A -> B -> C)。
    • -v: 开启调试模式,你可以看到具体卡在哪里。

    此时你会依次:

    1. 自动使用密钥登录 B。

    2. 提示输入 C 的密码。

    3. 成功后窗口会静止(没有新输出),这代表隧道通了。

    4. 现在隧道已经把 A 电脑的 2022端口直接通向了 D 的 SFTP 端口。配置 Xftp

      1. 主机: 127.0.0.1
      2. 端口: 2022
      3. 用户名: D 的用户名
      4. 密码: D 的密码

配置技巧

你的 config 文件可以写得非常庞大,包含几十个服务器和复杂的跳转逻辑。SSH 会根据你输入的 Host 别名,自动在内存中勾画出那条跳转路径。

你现在可以直接把 D、E 的各种路径都写进去,它们互不干扰。 想连哪个就 sftp 别名 即可。

shell
# ==========================================
# 基础节点:B (所有的流量入口)
# ==========================================
Host serverB
    HostName 20.8.0.1           # B 的 VPN 内网 IP
    User root
    IdentityFile ~/.ssh/id_rsa_b
    PreferredAuthentications publickey

# ==========================================
# 分支节点:C (从 B 跳到 C)
# ==========================================
Host serverC
    HostName 192.168.1.10       # C 的 IP
    User root
    ProxyJump serverB

# ==========================================
# 路径 1: A -> B -> C -> D
# ==========================================
Host serverD
    HostName 10.0.0.5           # D 的 IP
    User sftpuser
    Port 2222
    ProxyJump serverC           # 这一行决定了它是从 C 跳过去的

# ==========================================
# 路径 2: A -> B -> C -> E (目标 E 通过 C 访问)
# ==========================================
Host serverE_viaC
    HostName 10.0.0.6           # E 的 IP
    User root
    ProxyJump serverC           # 这一行指定路径经过 C

# ==========================================
# 路径 3: A -> B -> E (目标 E 直接从 B 访问)
# ==========================================
Host serverE_direct
    HostName 10.0.0.6           # 同样的 E IP
    User root
    ProxyJump serverB           # 这一行改从 B 跳,不经过 C

原理解读

  • ProxyJump 的链式递归

当你执行 sftp serverD 时,SSH 会查看 serverD 的配置:

  1. 发现 ProxyJump serverC。
  2. 于是它去找 Host serverC。
  3. 发现 serverC 也有 ProxyJump serverB。
  4. 于是它去找 Host serverB。
  5. serverB 没有 ProxyJump,它会直接发起连接。
  6. 建立连接顺序:A -> B -> C -> D。
  7. 数据传输顺序:数据被层层封装加密,对 B 来说它只知道自己在帮 A 传数据给 C,它看不见发给 D 的内容。
  • 别名(Alias)的力量

    注意我在配置 E 时用了两个名字:serverE_viaC 和 serverE_direct。

    • 你可以为同一物理 IP 设置不同的逻辑路径
    • 如果你输入 ssh serverE_viaC,它就走 C 跳。
    • 如果你输入 ssh serverE_direct,它就直接从 B 跳。 这在其中一台机器(比如 C)临时宕机时非常有用。