作为开发者或运维人员,日常工作中难免会遇到这些场景:想访问公司内网的数据库却无法直接连接、需要在外部安全调试本地开发的服务、担心明文传输的数据被窃取……而 SSH 隧道,就是解决这些问题的“神器”。
很多人对 SSH 的认知还停留在“远程登录服务器”,却不知道它自带的端口转发功能,能搭建起一条加密、安全的“隐形通道”,无需额外安装软件,就能实现内网穿透、流量加密、绕过防火墙等需求。今天就从基础到实战,手把手教你用 SSH 建立隧道,新手也能快速上手~
一、先搞懂:SSH 隧道到底是什么?
SSH(Secure Shell)本身是一种用于远程登录的加密协议,而 SSH 隧道(也叫 SSH 端口转发),就是借助 SSH 协议的加密特性,将本地或远程的网络端口“转发”到目标主机,让原本无法直接通信的两台设备,通过这条加密隧道实现数据传输。
简单来说,SSH 隧道就像一条“加密的水管”,数据从一端的端口流入,经过 SSH 加密后,通过隧道传输到另一端的端口,全程安全且不易被监听、篡改。它的核心优势的是:无需额外工具、加密传输、配置简单,适合临时场景下的安全访问需求。
在开始实操前,先做好准备工作:确保本地设备安装了 SSH 客户端(Linux/macOS 自带,Windows 可安装 Xshell、Putty),且能正常登录一台可访问公网的 SSH 服务器(或内网跳板机);同时需要在 SSH 服务端配置文件(/etc/ssh/sshd_config)中开启转发功能,确保以下参数为 yes(远程转发需额外开启 GatewayPorts):
# 开启 TCP 转发,三种隧道模式都需要
AllowTcpForwarding yes
# 远程转发需要开启,允许外部访问转发端口
GatewayPorts yes
配置完成后,重启 SSH 服务即可生效(sudo systemctl restart sshd)。
二、核心实战:三种 SSH 隧道模式(必学)
SSH 隧道主要分为三种模式,对应不同的使用场景,掌握这三种,就能覆盖绝大多数日常需求。每种模式都先讲“用途+命令+实操示例”,全程复制命令就能用~
1. 本地端口转发(-L):本地 → SSH 服务器 → 目标服务
适用场景:本地设备无法直接访问目标服务(如公司内网数据库、内网 Web 服务),但能登录一台内网跳板机(SSH 服务器),通过跳板机转发流量,实现本地访问内网服务。
命令格式:
ssh -L [本地IP:]本地端口:目标主机IP:目标端口 用户名@SSH服务器IP
参数说明:
- -L:指定本地端口转发
- 本地IP(可选):不写则默认 127.0.0.1,仅本地可访问;写 0.0.0.0 则局域网内其他设备可访问
- 本地端口:本地设备用于接收请求的端口(自定义,如 3307、8080)
- 目标主机IP+目标端口:需要访问的内网服务地址(如内网数据库 192.168.1.100:3306)
实操示例:本地通过跳板机访问公司内网 MySQL 数据库(内网地址 192.168.1.50:3306),跳板机 IP 为 47.xxx.xxx.xxx,用户名为 root。
# 建立本地转发隧道
ssh -L 3307:192.168.1.50:3306 root@47.xxx.xxx.xxx
执行命令后,输入跳板机密码登录,隧道即建立成功。此时本地访问 127.0.0.1:3307,就相当于直接访问内网的 192.168.1.50:3306,用本地 IDE 连接数据库时,主机填 127.0.0.1,端口填 3307 即可。
2. 远程端口转发(-R):远程 SSH 服务器 → 本地 → 本地服务
适用场景:本地开发了一个 Web 服务(如 localhost:3000),想让外部用户(或远程服务器)访问,但本地设备处于内网(无公网 IP),此时可通过远程 SSH 服务器,将远程端口转发到本地服务。
命令格式:
ssh -R [远程IP:]远程端口:本地主机IP:本地端口 用户名@SSH服务器IP
参数说明:
- -R:指定远程端口转发
- 远程IP(可选):不写则默认 127.0.0.1,仅 SSH 服务器可访问;写 0.0.0.0 则公网可访问(需开启 GatewayPorts yes)
- 远程端口:SSH 服务器用于接收请求的端口(自定义,如 8080)
- 本地主机IP+本地端口:本地需要暴露的服务地址(如 localhost:3000)
实操示例:本地开发的 Web 服务运行在 localhost:3000,让外部用户通过 SSH 服务器(IP 47.xxx.xxx.xxx)的 8080 端口访问该服务。
# 建立远程转发隧道(允许公网访问)
ssh -R 0.0.0.0:8080:localhost:3000 root@47.xxx.xxx.xxx
隧道建立后,外部用户访问 47.xxx.xxx.xxx:8080,流量会通过 SSH 隧道转发到本地的 localhost:3000,即可看到本地开发的 Web 页面。适合给客户演示本地项目、远程调试本地服务等场景。
3. 动态端口转发(-D):本地 SOCKS 代理 → SSH 服务器 → 任意目标
适用场景:需要让本地所有应用(浏览器、命令行工具等)的流量,通过 SSH 服务器转发出去(类似 VPN),比如访问某些需要特定网络环境的资源、加密本地所有网络请求。
这种模式会在本地建立一个 SOCKS5 代理端口,所有发送到该端口的流量,都会通过 SSH 隧道转发到 SSH 服务器,再由服务器转发到目标地址,实现“全局代理”效果。
命令格式:
ssh -D [本地IP:]本地代理端口 用户名@SSH服务器IP
实操示例:在本地建立 SOCKS5 代理,端口为 1080,通过 SSH 服务器转发所有流量。
# 建立动态转发隧道
ssh -D 1080 root@47.xxx.xxx.xxx
隧道建立后,在浏览器(或系统)中配置 SOCKS5 代理:主机 127.0.0.1,端口 1080,此时浏览器的所有访问请求,都会通过 SSH 隧道加密传输,既安全又能绕过部分网络限制。命令行工具可配合 proxychains 使用,强制流量走代理:
# 安装 proxychains(Ubuntu/Debian)
sudo apt install proxychains
# 使用代理访问目标地址
proxychains curl http://example.com
三、实用技巧:让 SSH 隧道更易用、更稳定
掌握基础模式后,这几个技巧能帮你提升效率,避免频繁操作和隧道中断。
1. 后台运行隧道,不占用终端
默认情况下,建立隧道后终端不能关闭,关闭则隧道中断。加上 -fNT 参数,可让隧道在后台运行,解放终端:
# 后台运行本地转发隧道
ssh -fNT -L 3307:192.168.1.50:3306 root@47.xxx.xxx.xxx
# 关闭后台隧道(先查看进程,再 kill)
ps aux | grep ssh
kill -9 进程ID
参数说明:-f(后台运行)、-N(不执行远程命令)、-T(不分配终端)。
2. 配置 SSH config,简化命令
每次输入冗长的隧道命令很麻烦,可在本地 ~/.ssh/config 文件中配置别名,后续直接输入别名即可建立隧道:
# 编辑 config 文件
vim ~/.ssh/config
# 配置内容(按需修改)
# 跳板机配置
Host jump
HostName 47.xxx.xxx.xxx # SSH服务器IP
User root # 登录用户名
IdentityFile ~/.ssh/id_rsa # 密钥文件(可选,免密码登录)
# 本地转发(访问内网MySQL)
Host mysql-tunnel
HostName 47.xxx.xxx.xxx
User root
LocalForward 3307 192.168.1.50:3306
# 动态代理
Host dev-proxy
HostName 47.xxx.xxx.xxx
User root
DynamicForward 1080
配置完成后,直接输入以下命令即可快速建立对应隧道:
# 访问内网MySQL
ssh -fNT mysql-tunnel
# 启动动态代理
ssh -fNT dev-proxy
3. 用 autossh 保持隧道稳定(自动重连)
网络波动可能导致 SSH 隧道中断,autossh 工具可实现隧道断开后自动重连,适合长期运行的隧道。
# 安装 autossh(Ubuntu/Debian)
sudo apt install autossh
# macOS 用 brew install autossh
# 自动重连的本地转发隧道
autossh -M 0 -fNT -L 3307:192.168.1.50:3306 root@47.xxx.xxx.xxx
参数说明:-M 0(禁用监控端口,使用 SSH 自身保活),其他参数和普通 SSH 隧道一致。如果需要开机自启,可配置 systemd 服务(参考下方命令):
# 创建服务文件
sudo vim /etc/systemd/system/ssh-tunnel.service
# 服务内容
[Unit]
Description=SSH Tunnel to MySQL
After=network.target
[Service]
User=root
ExecStart=/usr/bin/autossh -M 0 -NL 3307:192.168.1.50:3306 root@47.xxx.xxx.xxx
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
# 启用并启动服务
sudo systemctl enable ssh-tunnel
sudo systemctl start ssh-tunnel
四、常见问题排查(新手必看)
建立隧道后无法访问?大概率是以下几个问题,逐一排查即可解决:
- SSH 服务端未开启转发:检查 /etc/ssh/sshd_config 中的 AllowTcpForwarding 和 GatewayPorts(远程转发需开启),重启 SSH 服务。
- 端口被占用:本地或远程端口已被其他程序占用,更换一个未使用的端口(如 3308、8081),可通过 netstat -tuln 查看端口占用情况。
- 目标服务未启动:确认目标服务(如 MySQL、Web 服务)已正常启动,且能被 SSH 服务器访问(可在 SSH 服务器上 ping 目标 IP、telnet 目标端口)。
- 防火墙限制:检查本地、SSH 服务器、目标主机的防火墙,放行对应的端口(如本地 3307、远程 8080)。
- 动态代理无法使用:确认浏览器/系统代理配置正确(SOCKS5 协议,主机 127.0.0.1,端口 1080),可通过 curl –socks5 127.0.0.1:1080 http://example.com 测试。
五、安全注意事项 & 适用场景总结
1. 安全注意事项
- 优先使用密钥认证:避免使用密码登录 SSH 服务器,配置 SSH 密钥(ssh-keygen 生成密钥,ssh-copy-id 上传到服务器),禁用密码登录(修改 /etc/ssh/sshd_config 中 PasswordAuthentication no)。
- 限制转发权限:根据需求开启对应转发模式,无需转发时可设置 AllowTcpForwarding no,避免滥用。
- 定期更新 SSH 服务:及时修复 SSH 协议的安全漏洞,确保服务安全。
- 不暴露敏感端口:远程转发时,避免将内网敏感服务(如数据库)暴露到公网,必要时限制访问 IP。
2. 适用场景总结
| 隧道模式 | 核心用途 | 关键词 |
|---|---|---|
| 本地转发(-L) | 本地访问内网服务(数据库、Web 服务) | 内网穿透、跳板机 |
| 远程转发(-R) | 外部访问本地服务(演示、远程调试) | 反向代理、无公网 IP |
| 动态转发(-D) | 本地流量全局代理(加密、绕过限制) | SOCKS 代理、安全浏览 |
六、最后总结
SSH 隧道是一种轻量、安全的端口转发工具,无需额外部署软件,仅通过简单的命令就能实现内网穿透、流量加密等需求,是开发者和运维人员的必备技能。
本文讲解的三种隧道模式,覆盖了绝大多数日常场景,新手可以先从本地转发入手,熟悉命令后再尝试远程转发和动态转发。配合 config 配置和 autossh 工具,能大幅提升使用效率,让隧道更稳定、更易用。
如果在实操中遇到问题,欢迎在评论区留言,一起交流解决~ 觉得有用的话,别忘了点赞收藏,转发给需要的朋友哦!
ssh -gNfL 0.0.0.0:8000:172.17.0.46:80 zhangchunsheng@124.250.26.88