博客 / 詳情

返回

SSH隧道與端口轉發完全指南

本文詳解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 ...

參考資料

  1. SSH手冊:https://man.openbsd.org/ssh
  2. OpenSSH官網:https://www.openssh.com/

💡 SSH隧道是運維必備技能,但對於複雜的遠程訪問需求,專業的組網工具會更方便。
user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.