远程办公或跨网络访问内网资源时,如何安全地连接到公司内部的数据库、缓存或Web服务?通过SSH端口转发(SSH隧道)技术,可以轻松实现。本文将详细解析SSH端口转发的三种核心模式:本地转发(-L)、远程转发(-R)和动态转发(-D),并附上真实应用场景与命令示例,助你彻底掌握这一实用技能。
一、本地端口转发:将远程服务映射到本地
适用场景:从本地计算机访问位于远程内网中的服务,例如数据库、Redis等。
原理示意图:

基础命令格式:
ssh -L [本地绑定端口]:[目标主机]:[目标端口] [用户名]@[跳板机地址]
实战案例1:访问内网MySQL数据库
假设公司内网MySQL服务器IP为192.168.1.100,端口为3306,跳板机地址为jump.company.com。
ssh -L 3307:192.168.1.100:3306 zhangsan@jump.company.com
执行此命令后,即可在本地使用mysql -h 127.0.0.1 -P 3307连接公司的内网MySQL。
实战案例2:访问内网Redis
ssh -L 6380:192.168.1.101:6379 zhangsan@jump.company.com
本地通过redis-cli -p 6380即可连接。
高级用法:后台运行隧道
ssh -fN -L 3307:192.168.1.100:3306 zhangsan@jump.company.com
-f:使SSH在后台运行。
-N:不执行远程命令,仅建立隧道。
-C:启用数据压缩(可选)。
常见问题与解决方案:
- 端口占用:若本地端口(如3307)已被占用,命令会失败。可使用
lsof -i:3307查看占用进程。
- 监听地址限制:默认仅绑定
127.0.0.1。若需让局域网内其他机器访问,需使用0.0.0.0:
ssh -L 0.0.0.0:3307:192.168.1.100:3306 zhangsan@jump.company.com
同时,需要在跳板机的/etc/ssh/sshd_config中设置GatewayPorts yes并重启SSH服务。
- 连接不稳定:网络波动可能导致SSH断开,隧道失效。推荐使用
autossh工具自动重连:
autossh -M 0 -fN -L 3307:192.168.1.100:3306 zhangsan@jump.company.com
二、远程端口转发:将本地服务暴露到远程
适用场景:将本地开发环境临时暴露给外网同事访问,或进行远程调试。这在某些运维/DevOps场景中尤为有用。
原理示意图:

基础命令格式:
ssh -R [远程绑定端口]:[目标主机]:[目标端口] [用户名]@[跳板机地址]
实战案例1:共享本地Web服务
本地有一个运行在8080端口的服务,希望同事通过跳板机jump.company.com的8081端口访问。
ssh -R 8081:127.0.0.1:8080 zhangsan@jump.company.com
执行后,同事访问http://jump.company.com:8081即可看到你的本地服务。
实战案例2:远程Java应用调试
本地Java应用开启调试端口5005,将其转发到远程:
ssh -R 5005:127.0.0.1:5005 zhangsan@jump.company.com
远程的IDE便可连接jump.company.com:5005进行调试。
常见问题与解决方案:
- 远程监听限制:跳板机默认只将
-R转发的端口绑定在127.0.0.1。若需从外部访问,需在其/etc/ssh/sshd_config中设置GatewayPorts yes并重启SSH服务。
- 端口权限:普通用户可能无法绑定
1024以下端口。建议使用1024以上端口。
- 防火墙:确保跳板机的防火墙开放了对应的远程绑定端口。
三、动态端口转发:建立SOCKS5代理隧道
适用场景:需要访问远程内网中多个不同主机和端口的服务,无需为每个服务单独配置转发规则。
原理示意图:

基础命令格式:
ssh -D [本地SOCKS5代理端口] [用户名]@[跳板机地址]
实战案例:访问整个内网段服务
ssh -D 1080 zhangsan@jump.company.com
执行后,本地1080端口会启动一个SOCKS5代理服务器。
配置使用代理:
扩展应用:此模式也常用于授权范围内的安全/渗透测试,测试人员可通过代理工具访问内网资源进行安全评估。
ssh -D 1080 zhangsan@jump.company.com
随后配置nmap、sqlmap等工具使用该SOCKS5代理进行内网扫描。
常见问题:
- DNS解析:默认使用本地DNS,可能无法解析内网域名。可通过复杂配置或代理工具的域名解析功能解决。
- 性能:所有流量经过代理加密解密,速度较直接转发稍慢,适合临时性多服务访问。
四、高阶技巧:多级跳转与稳定化部署
场景:目标服务器处于多层内网之后,需连续穿越多个跳板机。
方法1:命令嵌套
ssh -L 3307:db2.internal:3306 user@jump1 -t ssh -L 3307:db2.internal:3306 user@jump2
方法2:使用~/.ssh/config配置(推荐)
配置~/.ssh/config文件,利用ProxyJump指令简化操作:
Host jump1
HostName jump1.company.com
User zhangsan
Host jump2
HostName jump2.internal.company.com
User zhangsan
ProxyJump jump1
Host db-server
HostName 192.168.10.100
User root
ProxyJump jump2
配置后,只需一条命令即可建立多级转发:
ssh -L 3307:localhost:3306 db-server
五、保持隧道稳定:autossh与Systemd服务
为确保SSH隧道在网络不稳定时能自动重连,可进行以下部署。
方案一:使用autossh
# 安装
sudo apt-get install autossh
# 建立稳定隧道
autossh -M 0 -fN -o ServerAliveInterval=60 -o ServerAliveCountMax=3 \
-L 3307:192.168.1.100:3306 zhangsan@jump.company.com
方案二:配置Systemd服务(Linux)
创建服务文件/etc/systemd/system/ssh-tunnel.service:
[Unit]
Description=SSH Tunnel for MySQL
After=network.target
[Service]
Type=simple
ExecStart=/usr/bin/ssh -NT -o ServerAliveInterval=60 -o ServerAliveCountMax=3 \
-L 3307:192.168.1.100:3306 zhangsan@jump.company.com
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
启用并启动服务:
sudo systemctl enable ssh-tunnel
sudo systemctl start ssh-tunnel
总结与最佳实践
| 核心模式速查: |
场景 |
命令示例 |
| 访问内网数据库 |
ssh -fN -L 3307:db:3306 user@jump |
| 暴露本地服务 |
ssh -R 8081:localhost:8080 user@jump |
| 全局SOCKS5代理 |
ssh -D 1080 user@jump |
| 稳定化连接 |
autossh -M 0 -fN -L ... user@jump |
安全与实践建议:
- 避免使用
root账户建立隧道。
- 跳板机应启用密钥认证及双因素认证。
- 隧道映射尽量使用非特权端口(>1024)。
- 定期检查隧道连接状态与日志。
附录:SSH配置优化示例
在~/.ssh/config中预定义主机和转发规则,是提升效率的网络/系统管理习惯。
Host jump-prod
HostName jump.company.com
User zhangsan
Port 22
ServerAliveInterval 60
ServerAliveCountMax 3
Host internal-db via-jump
HostName 192.168.1.100
User root
ProxyJump jump-prod
LocalForward 3307 localhost:3306
# 使用 `ssh internal-db` 即可自动建立隧道并登录
一键部署脚本示例:
#!/bin/bash
# deploy_tunnels.sh
TUNNELS=(
"3307:192.168.1.100:3306"
"6380:192.168.1.101:6379"
"8081:192.168.1.102:8080"
)
for tunnel in "${TUNNELS[@]}"; do
autossh -M 0 -fN -L $tunnel zhangsan@jump.company.com
done
echo "所有隧道已建立。"