跳轉到內容

SSH 隧道與端口轉發詳解 2026

SSH 隧道與端口轉發

💡 什麼是 SSH 端口轉發? SSH 端口轉發(也稱為 SSH 隧道)是一種通過加密的 SSH 連接來轉發網絡流量的技術,可以安全地訪問內網服務、繞過防火牆限制、加密傳輸數據。

本文將帶你從 0 到 1 掌握:

  • ✅ 本地端口轉發(Local Port Forwarding)
  • ✅ 遠程端口轉發(Remote Port Forwarding)
  • ✅ 動態端口轉發(Dynamic Port Forwarding)
  • ✅ 反向隧道與內網穿透
  • ✅ SSH 隧道配置與優化
  • ✅ 實戰應用場景

一、SSH 端口轉發基礎

1.1 端口轉發類型概述

類型命令參數用途數據流方向
本地端口轉發-L訪問遠程內網服務本地 → SSH Server → 目標服務
遠程端口轉發-R暴露本地服務到遠程遠程 → SSH Server → 本地服務
動態端口轉發-D創建 SOCKS 代理本地 → SOCKS 代理 → 目標
反向隧道-R + 反向內網穿透內網 → 公網服務器 → 外部

1.2 基本語法

bash
# 本地端口轉發
ssh -L [本地地址:]本地端口:目標地址:目標端口 user@ssh-server

# 遠程端口轉發
ssh -R [遠程地址:]遠程端口:目標地址:目標端口 user@ssh-server

# 動態端口轉發(SOCKS 代理)
ssh -D [本地地址:]本地端口 user@ssh-server

# 後臺運行
ssh -f -N -L 8080:localhost:80 user@ssh-server

1.3 常用選項說明

選項說明
-L本地端口轉發(Local)
-R遠程端口轉發(Remote)
-D動態端口轉發(Dynamic)
-f後臺運行(fork)
-N不執行遠程命令(No command)
-T禁用偽終端(Terminal)
-g允許其他主機連接(Gateway)
-C啟用壓縮(Compression)
-v詳細模式(Verbose)

二、本地端口轉發

2.1 基本概念

本地端口轉發允許你將本地端口的流量轉發到遠程服務器後面的目標服務。

┌──────────┐    SSH Tunnel    ┌──────────────┐    ┌──────────────┐
│  本地機器 │ ────────────────► │  SSH Server  │ ──► │  目標服務    │
│  localhost:8080 │              │ (公網可達)   │    │  target:80  │
└──────────┘                  └──────────────┘    └──────────────┘

2.2 典型應用場景

場景 1:訪問遠程內網數據庫

bash
# 通過 SSH 服務器訪問內網 MySQL
ssh -L 3306:db-server:3306 user@ssh-server

# 然後本地連接
mysql -h localhost -P 3306 -u username -p

場景 2:訪問遠程內網 Web 服務

bash
# 訪問遠程內網的 Jenkins
ssh -L 8080:jenkins-server:8080 user@ssh-server

# 瀏覽器訪問 http://localhost:8080

場景 3:訪問多層內網服務

bash
# 通過跳板機訪問更深層的內網服務
ssh -L 8080:deep-internal-server:80 user@jump-server

2.3 高級配置

bash
# 綁定特定地址(只允許本地訪問)
ssh -L 127.0.0.1:8080:target:80 user@server

# 綁定所有地址(允許局域網其他機器訪問)
ssh -L 0.0.0.0:8080:target:80 -g user@server

# 多個端口轉發
ssh -L 8080:web:80 -L 3306:db:3306 -L 6379:redis:6379 user@server

# 後臺運行 + 不執行命令
ssh -f -N -L 8080:target:80 user@server

# 啟用壓縮(適合慢速網絡)
ssh -C -L 8080:target:80 user@server

三、遠程端口轉發

3.1 基本概念

遠程端口轉發允許你將遠程服務器的端口流量轉發到本地服務。

┌──────────────┐    SSH Tunnel    ┌──────────┐
│  外部用戶    │ ──► │  SSH Server  │ ────────────────► │  本地服務    │
│ 訪問 server:8080 │              │ (公網可達)   │              │ localhost:80 │
└──────────────┘                  └──────────┘                  └──────────┘

3.2 典型應用場景

場景 1:暴露本地開發服務到公網

bash
# 將本地服務暴露到遠程服務器的 8080 端口
ssh -R 8080:localhost:3000 user@public-server

# 外部用戶可以通過 http://public-server:8080 訪問

場景 2:穿透 NAT 訪問內網服務

bash
# 在內網機器上執行,將內網服務暴露到公網服務器
ssh -R 8080:192.168.1.100:80 user@public-server

場景 3:多端口轉發

bash
# 同時暴露多個服務
ssh -R 8080:localhost:80 -R 8443:localhost:443 user@public-server

3.3 網關模式配置

bash
# 允許遠程服務器上的其他用戶訪問轉發的端口
ssh -R 0.0.0.0:8080:localhost:3000 -g user@public-server

# 需要在 sshd_config 中開啟 GatewayPorts
# GatewayPorts yes

四、動態端口轉發(SOCKS 代理)

4.1 基本概念

動態端口轉發創建一個 SOCKS 代理服務器,允許所有流量通過 SSH 隧道轉發。

┌──────────┐    SOCKS    ┌──────────────┐    ┌──────────────┐
│  本地應用 │ ─────────► │  SSH Server  │ ──► │  目標網站    │
│  (瀏覽器) │              │ (代理服務器) │    │  (任意網站) │
└──────────┘              └──────────────┘    └──────────────┘

4.2 配置方法

bash
# 創建 SOCKS 代理(默認 SOCKS5)
ssh -D 1080 user@ssh-server

# 後臺運行
ssh -f -N -D 1080 user@ssh-server

# 指定綁定地址
ssh -D 127.0.0.1:1080 user@ssh-server

4.3 瀏覽器配置

Chrome 配置:

bash
# 使用命令行啟動 Chrome 並使用 SOCKS 代理
google-chrome --proxy-server="socks5://localhost:1080"

# 或使用 SwitchyOmega 擴展

Firefox 配置:

  1. 打開 about:preferences#general
  2. 找到「網絡設置」
  3. 選擇「手動配置代理」
  4. SOCKS 主機:localhost,端口:1080
  5. 選擇 SOCKS v5

4.4 使用 proxychains

bash
# 安裝 proxychains
sudo apt install proxychains4  # Ubuntu/Debian
brew install proxychains-ng    # macOS

# 配置 /etc/proxychains.conf
socks5  127.0.0.1 1080

# 使用 proxychains 執行命令
proxychains curl https://example.com
proxychains git clone https://github.com/repo.git

五、反向隧道與內網穿透

5.1 反向隧道原理

反向隧道允許內網機器主動連接到公網服務器,建立一個從公網到內網的連接。

內網機器 ──► 公網服務器 (保持連接) ◄── 外部用戶


              流量通過隧道轉發

5.2 永久反向隧道配置

bash
# 創建永久反向隧道(使用 autossh)
autossh -M 0 -f -N -R 8080:localhost:3000 user@public-server

# -M 0: 禁用監控端口(使用 ServerAliveInterval)
# -f: 後臺運行
# -N: 不執行命令
# -R: 遠程端口轉發

5.3 配置 autossh 自動重連

bash
# 安裝 autossh
sudo apt install autossh  # Ubuntu/Debian
brew install autossh      # macOS

# 創建 systemd 服務
cat > /etc/systemd/system/reverse-tunnel.service << 'EOF'
[Unit]
Description=SSH Reverse Tunnel
After=network.target

[Service]
User=username
ExecStart=/usr/bin/autossh -M 0 -f -N \
  -o "ServerAliveInterval 30" \
  -o "ServerAliveCountMax 3" \
  -R 8080:localhost:3000 \
  user@public-server
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF

# 啟動並啟用服務
sudo systemctl daemon-reload
sudo systemctl start reverse-tunnel
sudo systemctl enable reverse-tunnel

5.4 多重反向隧道

bash
# 通過多個跳板機建立隧道
ssh -R 8080:localhost:8080 user@jump-server

# 在跳板機上繼續轉發
ssh -R 8080:localhost:8080 user@final-server

六、SSH 隧道安全配置

6.1 限制端口轉發

bash
# /etc/ssh/sshd_config

# 禁用端口轉發(全局)
AllowTcpForwarding no

# 只允許本地端口轉發
AllowTcpForwarding local

# 只允許特定用戶
AllowUsers user1 user2

# 禁用 X11 轉發
X11Forwarding no

# 禁用代理轉發
AllowAgentForwarding no

6.2 使用密鑰認證

bash
# 生成密鑰對
ssh-keygen -t ed25519 -C "tunnel-key"

# 複製公鑰到服務器
ssh-copy-id user@server

# 禁用密碼登錄(在服務器上)
# /etc/ssh/sshd_config
PasswordAuthentication no
ChallengeResponseAuthentication no

6.3 配置防火牆規則

bash
# 允許 SSH 連接
sudo ufw allow 22/tcp

# 允許轉發的端口(如果需要外部訪問)
sudo ufw allow 8080/tcp

# 限制訪問來源
sudo ufw allow from 192.168.1.0/24 to any port 22

七、實戰應用場景

7.1 場景一:遠程辦公訪問內網資源

bash
# 場景:在家訪問公司內網服務器
ssh -L 3306:db.company.com:3306 \
    -L 8080:intranet.company.com:80 \
    -L 8443:secure.company.com:443 \
    user@vpn.company.com

7.2 場景二:開發環境預覽

bash
# 場景:讓客戶預覽本地開發環境
ssh -R 8080:localhost:3000 user@preview.example.com

# 客戶訪問 http://preview.example.com:8080

7.3 場景三:安全訪問 Redis

bash
# 場景:通過 SSH 隧道訪問 Redis(不暴露到公網)
ssh -L 6379:redis-server:6379 user@ssh-server

# 本地連接
redis-cli -h localhost -p 6379

7.4 場景四:繞過網絡限制

bash
# 場景:通過 SOCKS 代理訪問受限網站
ssh -f -N -D 1080 user@proxy-server

# 配置瀏覽器使用 SOCKS5 代理 localhost:1080

7.5 場景五:數據庫遷移

bash
# 場景:通過隧道遷移數據庫
ssh -L 3307:remote-db:3306 user@ssh-server &

# 從本地遷移到遠程
mysqldump -h localhost -P 3307 -u root -p dbname | \
  mysql -h local-db -u root -p dbname

八、SSH 隧道優化

8.1 連接保持配置

bash
# ~/.ssh/config
Host *
  ServerAliveInterval 30
  ServerAliveCountMax 3
  TCPKeepAlive yes
  ClientAliveInterval 30

8.2 壓縮與加密

bash
# 啟用壓縮(適合慢速網絡)
ssh -C -L 8080:target:80 user@server

# 指定加密算法
ssh -c aes256-gcm@openssh.com -L 8080:target:80 user@server

# 禁用壓縮(快速網絡)
ssh -o Compression=no user@server

8.3 性能調優

bash
# 配置文件 ~/.ssh/config
Host tunnel-server
  HostName server.example.com
  User user
  Port 22
  Compression yes
  CompressionLevel 6
  ServerAliveInterval 15
  ServerAliveCountMax 3
  TCPKeepAlive yes
  IPQoS lowdelay throughput

九、常見問題與解決方案

Q1:端口被佔用

bash
# 查找佔用端口的進程
lsof -i :8080
netstat -tlnp | grep 8080

# 殺死進程
kill -9 <pid>

# 使用不同端口
ssh -L 8081:target:80 user@server

Q2:連接斷開

bash
# 使用 autossh 自動重連
autossh -M 0 -f -N -R 8080:localhost:3000 user@server

# 配置 ServerAliveInterval
ssh -o ServerAliveInterval=30 -o ServerAliveCountMax=3 user@server

Q3:GatewayPorts 問題

bash
# 在服務器端開啟 GatewayPorts
sudo sed -i 's/#GatewayPorts no/GatewayPorts yes/' /etc/ssh/sshd_config
sudo systemctl restart sshd

# 使用 -g 選項
ssh -R 0.0.0.0:8080:localhost:3000 -g user@server

Q4:防火牆阻止連接

bash
# 檢查防火牆狀態
sudo ufw status
sudo iptables -L

# 允許端口
sudo ufw allow 8080/tcp
sudo iptables -A INPUT -p tcp --dport 8080 -j ACCEPT

Q5:權限問題

bash
# 確保用戶有權限
ls -la /var/run/sshd/

# 使用正確的用戶
ssh -R 8080:localhost:3000 user@server

十、完整配置示例

10.1 開發環境預覽配置

bash
# 創建反向隧道腳本
cat > start-preview.sh << 'EOF'
#!/bin/bash
# 停止舊的隧道
pkill -f "autossh.*preview"

# 啟動新隧道
autossh -M 0 -f -N \
  -o "ServerAliveInterval 30" \
  -o "ServerAliveCountMax 3" \
  -R 8080:localhost:3000 \
  -R 8443:localhost:3443 \
  user@preview.example.com

echo "Preview tunnel started on port 8080 and 8443"
EOF

chmod +x start-preview.sh

10.2 遠程數據庫訪問配置

bash
# ~/.ssh/config
Host db-tunnel
  HostName ssh.example.com
  User db-user
  LocalForward 3306 db-internal.example.com:3306
  LocalForward 5432 pg-internal.example.com:5432
  Compression yes
  ServerAliveInterval 30
bash
# 使用配置
ssh db-tunnel

# 連接數據庫
mysql -h localhost -P 3306 -u user -p
psql -h localhost -P 5432 -U user -d database

10.3 自動啟動隧道服務

bash
# systemd 服務配置
cat > /etc/systemd/system/db-tunnel.service << 'EOF'
[Unit]
Description=Database SSH Tunnel
After=network.target

[Service]
User=appuser
ExecStart=/usr/bin/ssh -f -N db-tunnel
Restart=always
RestartSec=10

[Install]
WantedBy=multi-user.target
EOF

# 啟動服務
sudo systemctl daemon-reload
sudo systemctl start db-tunnel
sudo systemctl enable db-tunnel

結語

SSH 端口轉發是運維和開發人員必備的技能,它提供了一種安全、加密的方式來訪問內網服務、穿透防火牆、安全傳輸數據。通過本文的學習,你已經掌握了:

  1. 本地端口轉發:訪問遠程內網服務
  2. 遠程端口轉發:暴露本地服務到公網
  3. 動態端口轉發:創建 SOCKS 代理
  4. 反向隧道:內網穿透解決方案
  5. 安全配置:限制訪問、密鑰認證、防火牆
  6. 實戰應用:多種場景的實際配置

推薦閱讀:


🚀 提示: 在生產環境中使用 SSH 隧道時,務必配置密鑰認證、限制訪問權限,並使用 autossh 確保連接穩定性。


延伸阅读

免责声明

本文仅供技术交流和学习参考。涉及第三方服务的链接可能包含 sponsored 标记,请自行核实服务条款、价格和可用性,并遵守当地法律法规。

最後更新於: