2021 字
10 分钟

SSH 隧道完全指南:本地端口转发 / 远程转发 / 动态 SOCKS 代理 / 内网穿透实战

SSH 隧道是 Linux 运维和开发中最被低估的功能之一——它能让你在不改变任何服务器防火墙规则的前提下,安全地访问远端数据库、将本地服务暴露到公网、或者搭建一个临时 SOCKS5 代理。

本文用真实场景驱动,完整讲解 SSH 三种端口转发模式,附带 ~/.ssh/config 持久化写法和 AutoSSH 自动重连配置。


一、SSH 隧道三种模式速览#

本地转发 -L [本地端口] → [SSH服务器] → [目标主机:目标端口]
↑ 解决:安全访问远端内网服务(数据库、Redis...)
远程转发 -R [SSH服务器端口] → [SSH服务器] → [本地端口]
↑ 解决:将本地服务暴露到公网(内网穿透)
动态转发 -D [本地SOCKS端口] → [SSH服务器] → 任意目标
↑ 解决:临时 SOCKS5 代理(不需要安装代理软件)
参数名称流量方向典型场景
-L 本地端口:目标主机:目标端口本地端口转发本地 → 远端访问远端内网数据库
-R 远端端口:本地主机:本地端口远程端口转发远端 → 本地内网穿透,暴露本地服务
-D 本地端口动态转发(SOCKS代理)本地 → 远端(任意目标)临时代理上网

二、本地端口转发(-L):安全访问远端数据库#

2.1 场景:远端数据库只绑定 127.0.0.1#

生产数据库通常不对外开放端口(防火墙封锁 5432),只能在服务器本地访问。通过 SSH 本地转发,可以在你的笔记本上直接连接:

Terminal window
# 命令格式
# ssh -L [本地端口]:[目标主机]:[目标端口] [SSH用户]@[SSH服务器]
# 场景:将本地 15432 端口转发到服务器上的 PostgreSQL(127.0.0.1:5432)
ssh -L 15432:localhost:5432 yourname@your-server.ip -N
# 参数说明:
# -L 15432:localhost:5432 本地15432 → 服务器上的 localhost:5432
# -N 不执行远程命令,纯转发用途
# localhost 这个 localhost 是相对于 SSH 服务器的!
# 连接建立后,在另一个终端用本地客户端连接:
psql -h 127.0.0.1 -p 15432 -U appuser -d mydb
# 或用 DBeaver / TablePlus 等 GUI 工具连接 127.0.0.1:15432

2.2 转发到远端内网的其他服务器#

SSH 跳板机场景:服务器 A(有公网 IP)→ 服务器 B(内网,无公网 IP,跑着数据库)

Terminal window
# 通过跳板机 A 访问内网 B 上的数据库
# B 的内网 IP 为 192.168.1.100,端口 3306(MySQL)
ssh -L 13306:192.168.1.100:3306 yourname@A的公网IP -N
# 本地连接:
mysql -h 127.0.0.1 -P 13306 -u dbuser -p

2.3 写入 ~/.ssh/config(持久化)#

~/.ssh/config
Host prod-db-tunnel
HostName your-server.ip
User yourname
IdentityFile ~/.ssh/id_ed25519
LocalForward 15432 localhost:5432 # PostgreSQL
LocalForward 16379 localhost:6379 # Redis
LocalForward 18080 localhost:8080 # Web 服务
ServerAliveInterval 60
ServerAliveCountMax 3
# 使用方式(一条命令开启所有隧道):
# ssh -N prod-db-tunnel

三、远程端口转发(-R):内网穿透#

3.1 场景:将本地开发服务器暴露到公网#

你的开发机没有公网 IP,但你有一台境外 VPS。通过 SSH 远程转发,外部用户可以通过访问 VPS 的某个端口来访问你本地的服务:

Terminal window
# 命令格式
# ssh -R [远端端口]:[本地主机]:[本地端口] [SSH用户]@[SSH服务器]
# 将本地 3000 端口(前端开发服务器)暴露到 VPS 的 8080 端口
ssh -R 8080:localhost:3000 yourname@your-vps.ip -N
# 现在外部用户访问 http://your-vps.ip:8080 就能访问你的本地服务

3.2 让远端监听公网地址(GatewayPorts)#

默认情况下,远程转发只绑定 VPS 的 127.0.0.1(只有 VPS 本机能访问),要让外部网络也能访问,需要修改 VPS 的 SSH 配置:

Terminal window
# 在 VPS 上修改 /etc/ssh/sshd_config
GatewayPorts yes # 或 GatewayPorts clientspecified
systemctl restart sshd
# 然后在本地指定绑定到全部地址
ssh -R 0.0.0.0:8080:localhost:3000 yourname@your-vps.ip -N
# 0.0.0.0 表示绑定 VPS 的所有网络接口(公网可访问)

3.3 结合 Nginx:让内网穿透看起来更专业#

/etc/nginx/conf.d/dev-tunnel.conf
# VPS 上的 Nginx 配置:将域名指向 SSH 隧道
server {
listen 80;
server_name dev.your-domain.com;
location / {
proxy_pass http://127.0.0.1:8080; # SSH 远程转发的本地端口
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade"; # 支持 WebSocket
}
}

四、动态端口转发(-D):临时 SOCKS5 代理#

4.1 基本用法#

Terminal window
# 在本地 1080 端口创建 SOCKS5 代理,出口为 SSH 服务器
ssh -D 1080 yourname@your-server.ip -N
# 后台运行(加 -f)
ssh -fN -D 1080 yourname@your-server.ip

4.2 让浏览器走 SOCKS 代理#

Chrome / Firefox 安装 SwitchyOmega 插件:

  1. 新建情景模式 → 类型:代理服务器
  2. 代理协议:SOCKS5,代理服务器:127.0.0.1,端口:1080
  3. 切换到此情景模式即可

4.3 让命令行工具走 SOCKS 代理(proxychains)#

Terminal window
# 安装 proxychains
apt install -y proxychains4
# 配置文件 /etc/proxychains4.conf
# 在末尾 [ProxyList] 部分添加:
# socks5 127.0.0.1 1080
# 使用:在命令前加 proxychains
proxychains curl https://ipinfo.io # 查看出口 IP(应为 SSH 服务器的 IP)
proxychains git clone https://github.com/... # git 走代理
proxychains pip install package-name # pip 走代理

4.4 macOS 系统代理设置#

Terminal window
# 临时设置终端代理变量
export ALL_PROXY=socks5://127.0.0.1:1080
export HTTP_PROXY=socks5://127.0.0.1:1080
export HTTPS_PROXY=socks5://127.0.0.1:1080
# 验证
curl -s https://ipinfo.io/ip
# 取消
unset ALL_PROXY HTTP_PROXY HTTPS_PROXY

五、AutoSSH:保持隧道连接稳定#

SSH 隧道遇到网络抖动会断开,AutoSSH 自动检测并重连:

Terminal window
apt install -y autossh
# 用 autossh 替代 ssh(其余参数相同)
# -M 0:不使用 AutoSSH 的监控端口,改用 SSH 自带的 ServerAlive 机制
autossh -M 0 -fN \
-L 15432:localhost:5432 \
-o "ServerAliveInterval 30" \
-o "ServerAliveCountMax 3" \
yourname@your-server.ip

5.1 systemd 服务(开机自启)#

Terminal window
# 创建 systemd 服务文件
cat > /etc/systemd/system/ssh-tunnel-db.service << 'EOF'
[Unit]
Description=SSH Tunnel to Production DB
After=network.target
[Service]
Type=simple
User=yourname # 运行用户(有 SSH 密钥的用户)
ExecStart=/usr/bin/autossh -M 0 -N \
-L 15432:localhost:5432 \
-o "ServerAliveInterval=30" \
-o "ServerAliveCountMax=3" \
-o "ExitOnForwardFailure=yes" \
-i /home/yourname/.ssh/id_ed25519 \ # 明确指定密钥路径
yourname@your-server.ip
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable --now ssh-tunnel-db.service
systemctl status ssh-tunnel-db.service

六、ProxyJump:通过跳板机连接深层服务器#

传统的跳板机方式需要先 SSH 到跳板机,再从跳板机 SSH 到目标服务器。ProxyJump(-J)可以一步完成:

Terminal window
# 命令格式
# ssh -J 跳板机 目标服务器
# 通过跳板机 A 连接内网服务器 B
ssh -J yourname@jumphost.ip yourname@192.168.1.100
# 多级跳板(A → B → C)
ssh -J yourname@A,yourname@B yourname@C

~/.ssh/config 写法(推荐)#

~/.ssh/config
# 跳板机
Host jumphost
HostName jumphost.ip
User yourname
IdentityFile ~/.ssh/id_ed25519
# 内网服务器(通过跳板机访问)
Host inner-server
HostName 192.168.1.100
User yourname
ProxyJump jumphost # 通过 jumphost 跳转
IdentityFile ~/.ssh/id_ed25519
# 另一台内网服务器,同时建立 DB 隧道
Host inner-db-server
HostName 192.168.1.200
User yourname
ProxyJump jumphost
LocalForward 15432 localhost:5432
Terminal window
# 使用(和直连一样简单)
ssh inner-server
ssh -N inner-db-server # 开启 DB 隧道

七、实用技巧与注意事项#

7.1 后台运行与终止#

Terminal window
# 后台运行 SSH 隧道(-f 后台,-N 不执行命令)
ssh -fN -L 15432:localhost:5432 yourname@server.ip
# 查找并终止后台 SSH 隧道进程
ps aux | grep 'ssh.*-[LRD]'
# 找到 PID 后
kill <PID>
# 或一键关闭所有 SSH 转发进程(谨慎使用)
pkill -f "ssh.*-N"

7.2 ControlMaster:复用 SSH 连接#

Terminal window
# ~/.ssh/config 添加(同一主机多次连接复用一个 TCP 连接)
Host *
ControlMaster auto
ControlPath ~/.ssh/control/%h_%p_%r # 需要手动创建目录
ControlPersist 10m # 主连接关闭后保持 10 分钟
mkdir -p ~/.ssh/control

7.3 常见错误排查#

错误信息原因解决
channel 3: open failed: connect failed目标端口未开放或服务未运行检查目标服务器的服务是否启动
bind: Address already in use本地端口已被占用换一个本地端口,或 kill 占用进程
Warning: remote port forwarding failedVPS 上 GatewayPorts 未开启sshd_config 设置 GatewayPorts yes
隧道经常断开长时间无数据传输被断开添加 ServerAliveInterval 60
Permission denied (publickey)密钥未上传或权限错误ssh-copy-id 重传公钥,检查 ~/.ssh 权限

相关文章

SSH 是现代服务器运维的基石,熟练掌握 SSH 隧道可以解决大量实际问题,而无需安装额外的工具或开放额外的防火墙端口。

SSH 隧道完全指南:本地端口转发 / 远程转发 / 动态 SOCKS 代理 / 内网穿透实战
https://971918.xyz/posts/docs/ssh-tunnel-port-forward-guide/
作者
九所长
发布于
2026-07-22
许可协议
CC BY-NC-SA 4.0