本文詳解SSH隧道的三種轉發模式,掌握這個技能能解決很多網絡訪問問題。
前言
SSH不只是遠程登錄工具,它還是強大的網絡隧道工具。
通過SSH端口轉發,你可以:
- 訪問內網服務
- 加密不安全的連接
- 繞過防火牆限制
- 實現簡易的代理
今天來詳解SSH的三種端口轉發模式。
一、SSH端口轉發概述
1.1 三種轉發模式
| 模式 | 命令參數 | 方向 | 用途 |
|---|---|---|---|
| 本地轉發 | -L |
本地→遠程 | 訪問遠程內網服務 |
| 遠程轉發 | -R |
遠程→本地 | 暴露本地服務到遠程 |
| 動態轉發 | -D |
SOCKS代理 | 通用代理 |
1.2 準備工作
# 確保SSH服務端允許轉發
# /etc/ssh/sshd_config
AllowTcpForwarding yes
GatewayPorts yes # 遠程轉發需要
二、本地端口轉發(-L)
2.1 原理
┌─────────────────────────────────────────────────────────┐
│ 本地端口轉發 (-L) │
│ │
│ 本地電腦 SSH服務器 目標服務 │
│ ┌─────┐ ┌─────┐ ┌─────┐ │
│ │:8080│ ──SSH──→ │ │ ────────→ │:3306│ │
│ └─────┘ └─────┘ └─────┘ │
│ │
│ 訪問 localhost:8080 = 訪問 目標服務:3306 │
└─────────────────────────────────────────────────────────┘
2.2 命令格式
ssh -L [本地地址:]本地端口:目標地址:目標端口 用户@SSH服務器
# 簡化
ssh -L 本地端口:目標地址:目標端口 用户@SSH服務器
2.3 實戰場景
場景1:訪問遠程MySQL
# 遠程服務器有MySQL,但只允許本地訪問
# 通過SSH隧道訪問
ssh -L 3307:localhost:3306 user@remote-server
# 本地連接
mysql -h 127.0.0.1 -P 3307 -u root -p
場景2:訪問內網Web服務
# 內網有個Web服務 192.168.1.100:8080
# 通過跳板機訪問
ssh -L 8080:192.168.1.100:8080 user@jump-server
# 瀏覽器訪問
http://localhost:8080
場景3:訪問Redis
ssh -L 6380:localhost:6379 user@redis-server
# 本地連接
redis-cli -h 127.0.0.1 -p 6380
2.4 後台運行
# -f 後台運行
# -N 不執行遠程命令
# -T 不分配終端
ssh -fNT -L 3307:localhost:3306 user@remote-server
# 查看隧道進程
ps aux | grep ssh
# 關閉隧道
kill <pid>
三、遠程端口轉發(-R)
3.1 原理
┌─────────────────────────────────────────────────────────┐
│ 遠程端口轉發 (-R) │
│ │
│ 本地服務 SSH服務器 遠程訪問 │
│ ┌─────┐ ┌─────┐ ┌─────┐ │
│ │:3000│ ←──SSH── │:8080│ ←───────── │用户 │ │
│ └─────┘ └─────┘ └─────┘ │
│ │
│ 訪問 SSH服務器:8080 = 訪問 本地:3000 │
└─────────────────────────────────────────────────────────┘
3.2 命令格式
ssh -R [遠程地址:]遠程端口:本地地址:本地端口 用户@SSH服務器
3.3 實戰場景
場景1:暴露本地開發環境
# 本地跑了個Web應用在3000端口
# 想讓外網能訪問(用於演示/測試)
ssh -R 8080:localhost:3000 user@public-server
# 外網訪問
http://public-server:8080
場景2:讓外網訪問本地服務
# 本地有個API服務
ssh -R 0.0.0.0:9000:localhost:8000 user@vps
# 注意:需要服務器配置 GatewayPorts yes
3.4 實現簡易內網穿透
# 本地電腦沒有公網IP
# 但有一台公網VPS
# 本地執行
ssh -R 2222:localhost:22 user@vps
# 外網通過VPS訪問本地SSH
ssh -p 2222 localuser@vps
四、動態端口轉發(-D)
4.1 原理
┌─────────────────────────────────────────────────────────┐
│ 動態端口轉發 (-D) = SOCKS5代理 │
│ │
│ 本地應用 SSH服務器 任意目標 │
│ ┌─────┐ ┌─────┐ ┌─────┐ │
│ │SOCKS│ ──SSH──→ │ │ ─────────→ │任意 │ │
│ │:1080│ └─────┘ └─────┘ │
│ └─────┘ │
│ │
│ 配置代理 127.0.0.1:1080 後,所有流量走SSH │
└─────────────────────────────────────────────────────────┘
4.2 命令格式
ssh -D [本地地址:]端口 用户@SSH服務器
# 示例
ssh -D 1080 user@remote-server
4.3 使用方法
# 啓動SOCKS代理
ssh -D 1080 user@remote-server
# 配置瀏覽器/系統代理
# SOCKS5 代理:127.0.0.1:1080
# 或命令行使用
curl --socks5 127.0.0.1:1080 http://example.com
# 配合proxychains
proxychains curl http://example.com
五、SSH配置文件
5.1 簡化命令
# ~/.ssh/config
# 跳板機
Host jump
HostName jump.example.com
User admin
IdentityFile ~/.ssh/jump_key
# 內網服務器(通過跳板)
Host internal
HostName 192.168.1.100
User root
ProxyJump jump
# 帶端口轉發的連接
Host mysql-tunnel
HostName db-server.example.com
User admin
LocalForward 3307 localhost:3306
Host dev-proxy
HostName vps.example.com
User root
DynamicForward 1080
5.2 使用簡化後的命令
# 直接連接內網服務器
ssh internal
# 建立MySQL隧道
ssh -fNT mysql-tunnel
# 啓動SOCKS代理
ssh -fNT dev-proxy
六、autossh保持連接
6.1 安裝
# Ubuntu/Debian
sudo apt install autossh
# macOS
brew install autossh
6.2 使用
# 自動重連的隧道
autossh -M 0 -fNT -L 3307:localhost:3306 user@remote-server
# 參數説明
# -M 0:禁用監控端口,使用SSH自身的保活
# -f:後台運行
# -N:不執行遠程命令
# -T:不分配終端
6.3 開機自啓(systemd)
# /etc/systemd/system/ssh-tunnel.service
[Unit]
Description=SSH Tunnel to MySQL
After=network.target
[Service]
User=youruser
ExecStart=/usr/bin/autossh -M 0 -NL 3307:localhost:3306 user@remote-server
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
sudo systemctl enable ssh-tunnel
sudo systemctl start ssh-tunnel
七、實際應用案例
7.1 案例:安全訪問生產數據庫
# 需求:本地IDE連接生產MySQL
# 生產MySQL不對外開放
# 方案:通過跳板機建立隧道
ssh -L 3307:prod-mysql.internal:3306 user@jump-server
# IDE連接配置
# Host: 127.0.0.1
# Port: 3307
7.2 案例:遠程調試內網服務
# 需求:訪問內網的測試環境Web服務
# 測試環境:192.168.1.50:8080
ssh -L 8080:192.168.1.50:8080 user@office-server
# 瀏覽器訪問
http://localhost:8080
7.3 案例:臨時暴露本地服務
# 需求:給客户演示本地開發的應用
ssh -R 80:localhost:3000 user@demo-server
# 客户訪問
http://demo-server
八、SSH隧道的侷限性
8.1 問題
1. 需要SSH服務器
- 你得有一台可SSH的機器
2. 單點故障
- SSH斷了,隧道就斷了
3. 配置較繁瑣
- 每個服務都要配置
4. 不適合大流量
- SSH開銷較大
8.2 更優方案
對於長期、多服務的遠程訪問需求,可以考慮:
- 內網穿透工具:frp、ngrok等
- 組網軟件:如星空組網,配置更簡單,所有端口直接互通
SSH隧道適合臨時、單一服務的場景。
九、安全注意事項
9.1 限制轉發
# /etc/ssh/sshd_config
# 禁止所有轉發
AllowTcpForwarding no
# 只允許本地轉發
AllowTcpForwarding local
# 限制可轉發的地址
PermitOpen host1:port1 host2:port2
9.2 使用密鑰認證
# 生成密鑰
ssh-keygen -t ed25519 -C "tunnel-key"
# 複製到服務器
ssh-copy-id -i ~/.ssh/tunnel-key.pub user@server
# 使用密鑰連接
ssh -i ~/.ssh/tunnel-key user@server
十、總結
| 轉發類型 | 參數 | 場景 |
|---|---|---|
| 本地轉發 | -L |
訪問遠程內網服務 |
| 遠程轉發 | -R |
暴露本地服務到公網 |
| 動態轉發 | -D |
SOCKS代理 |
常用命令速查:
# 本地轉發
ssh -L 本地端口:目標:端口 user@server
# 遠程轉發
ssh -R 遠程端口:localhost:本地端口 user@server
# SOCKS代理
ssh -D 1080 user@server
# 後台運行
ssh -fNT -L ...
# 保持連接
autossh -M 0 -fNT -L ...
參考資料
- SSH手冊:https://man.openbsd.org/ssh
- OpenSSH官網:https://www.openssh.com/
💡 SSH隧道是運維必備技能,但對於複雜的遠程訪問需求,專業的組網工具會更方便。