SSH 端口转发与内网穿透技术

2026-02-03T11:55:00

1. 概述 (Overview)

SSH 端口转发(Port Forwarding),俗称“SSH 隧道”,是 OpenSSH 协议提供的一种将 TCP 流量封装在加密的 SSH 连接中传输的技术。

核心价值

  1. 安全性:通过加密通道传输明文流量(如 HTTP, Telnet, 早期 MySQL 协议)。
  2. 穿透性:能够绕过防火墙限制,访问仅监听在内网(localhost/127.0.0.1)的服务。
  3. 双向性:既可以将远程服务映射到本地(Local),也可以将本地服务暴露给远程(Remote)。

2. 本地端口转发 (Local Port Forwarding)

方向:将远程服务器的端口“拉”到本地。

适用场景:访问生产环境数据库、访问内网运维后台(如 XXL-JOB, RabbitMQ Management)、绕过防火墙限制。

2.1 标准命令语法

Bash

ssh -N -L [本地监听IP:]本地端口:目标地址:目标端口 用户名@跳板机IP
  • -N: 不执行远程命令(仅建立连接,不打开 Shell 终端)。
  • -L: 标识 Local Forwarding。
  • 本地监听IP: 可选。默认为 127.0.0.1。若需局域网内其他人访问你的电脑,需指定为 0.0.0.0
  • 目标地址: 相对于跳板机而言的地址。通常是 127.0.0.1(指跳板机自己)或跳板机所在内网的其它 IP。

2.2 典型实战案例

场景 A:连接生产环境 MySQL

生产数据库 (3306) 仅允许 localhost 访问,你需要用本地 IDEA/Navicat 连接。

Bash

# 将远程 3306 映射到本地 13306
ssh -N -L 13306:127.0.0.1:3306 root@192.168.1.232
  • 本地连接地址: localhost:13306

场景 B:访问内网 XXL-JOB 调度中心

调度中心运行在远程服务器 8080 端口,且有防火墙拦截外部 HTTP 请求。

Bash

# 将远程 8080 映射到本地 18080
ssh -N -L 18080:127.0.0.1:8080 root@192.168.1.232
  • 浏览器访问: http://localhost:18080/xxl-job-admin

3. 远程端口转发 (Remote Port Forwarding)

方向:将本地端口“推”到远程服务器。

适用场景:内网穿透、本地开发环境演示(给异地同事看)、调试第三方 Webhook 回调(微信支付/GitHub)。

3.1 标准命令语法

Bash

ssh -N -R [远程监听IP:]远程端口:本地地址:本地端口 用户名@跳板机IP
  • -R: 标识 Remote Forwarding。
  • 远程监听IP: ⚠️ 默认情况下 SSH 服务端只允许绑定 127.0.0.1。若需绑定 0.0.0.0(公网访问),需修改服务器配置(详见 3.3 节)。

3.2 典型实战案例

场景 C:让服务器访问我本地的 Java 服务

我在本地启动了 Spring Boot (8080),需要服务器上的脚本调用我的接口。

Bash

# 将本地 8080 映射到服务器的 9090
ssh -N -R 9090:127.0.0.1:8080 root@192.168.1.232
  • 服务器端调用: curl http://localhost:9090 -> 流量直达你本地电脑。

场景 D:公网演示 (需服务器配置支持)

我在本地开发了网页,想发个 URL 给异地产品经理体验。

Bash

# 假设服务器公网 IP 为 1.2.3.4,且已开启 GatewayPorts
ssh -N -R 0.0.0.0:80:127.0.0.1:8080 root@1.2.3.4
  • 外部访问: 产品经理访问 http://1.2.3.4 即可看到你本地的内容。

3.3 关键配置说明 (GatewayPorts)

默认情况下,使用 -R 映射的远程端口仅监听在 127.0.0.1。如果需要让其他人通过服务器 IP 访问该端口,必须修改服务器端的 /etc/ssh/sshd_config

Bash

# 1. 编辑配置
vim /etc/ssh/sshd_config

# 2. 修改或添加以下参数
GatewayPorts yes

# 3. 重启 SSHD
systemctl restart sshd

4. 生产环境高级技巧 (Pro Tips)

在日常高频使用中,为了保证隧道的稳定性和易用性,建议采用以下方案。

4.1 自动重连 (Autossh)

原生 ssh 命令在网络波动断开后不会自动重连。推荐使用 autossh 工具。

  • 安装: brew install autossh (Mac) / apt install autossh (Ubuntu)
  • 命令模版:

    Bash

    # -M 0: 关闭监控端口(依赖 SSH 自身的保活机制)
    # -o "ServerAliveInterval 30": 每 30 秒发送心跳包
    # -o "ServerAliveCountMax 3": 3 次心跳失败则重连
    autossh -M 0 -o "ServerAliveInterval 30" -o "ServerAliveCountMax 3" -N -L 3306:127.0.0.1:3306 root@server

4.2 后台静默运行

如果不想占用一个终端窗口,可以添加 -f 参数。

Bash

ssh -N -f -L 3306:127.0.0.1:3306 root@server
  • 注意: 第一次运行时如果需要输密码,-f 可能会导致输入困难。建议配置 SSH Key 免密登录 后再配合 -f 使用。

4.3 多级跳板 (ProxyJump)

如果目标服务器在内网深处,需要经过跳板机(Bastion Host)才能访问。

  • 拓扑: 本地 -> 跳板机(1.1.1.1) -> 目标机(10.0.0.2)
  • 命令:

    Bash

    # -J 指定跳板机
    ssh -N -L 3306:127.0.0.1:3306 -J root@1.1.1.1 root@10.0.0.2

5. 常见问题排查 (Troubleshooting)

现象可能原因检查步骤
Connection Refused1. 目标服务没启动 2. 目标端口写错在服务器执行 netstat -tulpn 确认目标端口处于 LISTEN 状态。
端口被占用本地端口已被其他程序使用本地执行 lsof -i :端口号 查看占用进程。
远程转发外部连不上服务器未开启 GatewayPorts检查 /etc/ssh/sshd_config,或只能在服务器本机通过 localhost 访问。
闲置一会就断开防火墙切断了空闲连接增加 SSH 心跳参数 -o ServerAliveInterval=60

6. 总结速查表 (Cheat Sheet)

需求采用模式命令口诀记忆法
我想访问服务器的服务本地转发 (-L)ssh -L 本地端口:目标IP:目标端口Local (拉过来)
我想让服务器访问我的服务远程转发 (-R)ssh -R 远程端口:本地IP:本地端口Remote (推过去)
后台运行不占终端后台模式加上 -N -fNo Shell, Fork
当前页面是本站的「Baidu MIP」版。发表评论请点击:完整版 »