跳转到内容

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 标记,请自行核实服务条款、价格和可用性,并遵守当地法律法规。