当前位置:首页>Linux>Linux SSH 端口转发(下)——动态转发 -D 与实战场景

Linux SSH 端口转发(下)——动态转发 -D 与实战场景

  • 2026-09-10 13:29:53
Linux SSH 端口转发(下)——动态转发 -D 与实战场景

大家好,我是冯哥的缓存。

今天我们来聊一下动态转发-D,它是一种"万能"模式,也是很多人最容易忽视的。最后还会聊几个实战组合场景,以及 SSH 隧道 vs frp/ngrok 这类工具。

一、动态转发-D——SOCKS5 代理出口

1.1 原理

本机:本地端口(SOCKS5代理)→ SSH隧道 → 远端服务器 → 目标地址

-D和 -L的区别:

·-L是固定目标:转发到哪个地址和端口,建隧道时就写死了

·-D是动态目标:本机开一个 SOCKS5 代理端口,所有走这个代理的流量,由远端服务器决定最终去哪

说白了,-D就是用远端服务器做出口,在本机开了一个 SOCKS5 代理。

ssh -D 1080 -N user@远端服务器

·-D 1080:本机监听1080 端口,作为 SOCKS5 代理入口

·-N:不执行远端命令,只保持隧道

·所有走这个代理的流量,都从"远端服务器"出去 这个命令只开隧道,不打开终端,加 -f 可以后台运行。

1.2-L vs -D对比

对比项

本地转发 -L

动态转发 -D

目标地址

建隧道时写死

运行时动态决定

代理协议

透明 TCP 转发

SOCKS5

典型用途

访问特定数据库/Web管理界面

让浏览器、curl等一批工具走代理出口

配置复杂度

简单

客户端需配置代理

1.3 后台运行

# 后台运行,不占终端

ssh -D 1080 -N -f user@远端服务器

# 如果 1080 被占用,查看是谁占用了,或换一个端口

ss -tlnp | grep 1080

# 查看是否在运行

ps aux | grep ssh

# 如果想让局域网内其他设备也用这个代理,加 -g参数,SSH 会监听所有网卡

ssh -g -D 1080 user@远端

二、让软件走SOCKS5 代理

-D开起来之后,代理本身已经就绪了。但各个软件走不走这个代理,需要单独配置。

2.1 浏览器(Firefox)

Firefox 可以单独设置代理,不影响系统网络:

1.设置 → 网络设置 → 手动代理

2.SOCKS 主机:127.0.0.1,端口:1080

3.选SOCKS v5,勾选"通过代理服务器发送 DNS 查询"

Chrome/Chromium 不支持单独设置代理,需要启动时加参数:

google-chrome --proxy-server="socks5://127.0.0.1:1080"

设置完后,访问http://ifconfig.me 看看 IP 是否变成了远端服务器的 IP,确认代理生效

2.2 curl

# 单次请求走代理

curl --socks5-hostname 127.0.0.1:1080 https://example.com

# 或者设置环境变量(本终端会话生效)

export ALL_PROXY=socks5://127.0.0.1:1080

curl https://example.com

--socks5-hostname 在远端解析域名,避免 DNS 泄漏; --socks5 在本地解析域名。

2.3 git

# 针对某个仓库

git config http.proxy socks5://127.0.0.1:1080

git config https.proxy socks5://127.0.0.1:1080

# 全局生效

git config --global http.proxy socks5://127.0.0.1:1080

git config --global https.proxy socks5://127.0.0.1:1080

# 用完取消

git config --global --unset http.proxy

git config --global --unset https.proxy

2.4 apt(系统包管理器)

# 临时走代理安装

sudo -E apt-get install -o Acquire::http::proxy="socks5h://127.0.0.1:1080/" 包名

# 或者写进配置文件(永久生效)

echo 'Acquire::http::Proxy "socks5h://127.0.0.1:1080/";' | sudo tee /etc/apt/apt.conf.d/proxy.conf

# 如果程序只支持 HTTP 代理而不支持 SOCKS,可以用 proxychains 将 SOCKS 转为 HTTP 代理

sudo apt install proxychains4

# 配置/etc/proxychains4.conf 里的 SOCKS5 代理地址。

⚠️注意:socks5h中的 h表示 DNS 也走代理解析,推荐用 socks5h而不是 socks5,避免 DNS 泄漏。

2.5 系统全局代理(环境变量)

# 临时设置,只对当前终端生效

export http_proxy=socks5://127.0.0.1:1080

export https_proxy=socks5://127.0.0.1:1080

export ALL_PROXY=socks5://127.0.0.1:1080

# 取消

unset http_proxy https_proxy ALL_PROXY

💡提示:不是所有程序都读环境变量的,图形界面程序一般不读。浏览器、curl、git、pip 等命令行工具大多支持。

三、autossh——让隧道不断线

普通ssh -D断线了就没了,需要手动重连。autossh会自动重连。

3.1 安装

sudo apt install autossh

3.2 基本用法

# 动态转发,断线自动重连

autossh -M 0 -o "ServerAliveInterval 30" -o "ServerAliveCountMax 3" \

-D 1080 -N user@远端服务器

参数说明:

参数

含义

-M 0

不用监控端口(推荐,用 ServerAlive 代替)

ServerAliveInterval 30

每 30 秒发心跳包

ServerAliveCountMax 3

心跳包失败 3 次后重连

3.3 systemd 开机自启

新建/etc/systemd/system/ssh-socks.service:

[Unit]

Description=SSH SOCKS5 Proxy

After=network.target

[Service]

User=自己的用户名

ExecStart=/usr/bin/autossh -M 0 \

-o "ServerAliveInterval 30" \

-o "ServerAliveCountMax 3" \

-o "ExitOnForwardFailure yes" \

-o "StrictHostKeyChecking no" \

-D 1080 -N user@远端服务器

Restart=always

RestartSec=5

[Install]

WantedBy=multi-user.target

sudo systemctl daemon-reload

sudo systemctl enable ssh-socks

sudo systemctl start ssh-socks

# 检查状态

sudo systemctl status ssh-socks

四、多跳转发——隧道套隧道

有时候目标服务器不能直接连,需要先跳一台跳板机,再连目标。

4.1 场景描述

本机→ 跳板机A(有公网IP)→ 内网服务器B → 数据库:3306

4.2 一条命令多跳

# 通过A跳到B,把B上3306映射到本机3306

ssh -L 3306:数据库IP:3306 -J userA@跳板机A userB@内网服务器B -N

数据库IP:例如 127.0.0.1-J是 ProxyJump,上篇详细讲过。

4.3 配置文件方式

# ~/.ssh/config

Host 内网服务器B

HostName 192.168.1.100

User userB

ProxyJump userA@跳板机A

Host 数据库隧道

HostName 内网服务器B

User userB

LocalForward 3306 127.0.0.1:3306

ProxyJump userA@跳板机A

然后:

ssh -N 数据库隧道

# 本机localhost:3306 就能访问到内网数据库了

4.4 动态转发多跳

# 通过A跳到B,以B为出口开SOCKS5代理

ssh -D 1080 -J userA@跳板机A -N userB@内网服务器B

这样出口是内网服务器B,能访问只有B能到的资源。

五、实战场景汇总

5.1 在家访问公司内网系统

公司有一台可以 SSH 的跳板机(对外开放22端口)

公司内网有各种服务(Gitlab/Jenkins/数据库/监控面板)

方案:

# 方案A:用-L逐个映射(每个服务一条命令)

ssh -L 8080:jenkins内网IP:8080 -L 3306:mysql内网IP:3306 -N user@跳板机 &

# 方案B:用-D开SOCKS5代理,浏览器配代理,所有公司内网都能访问

ssh -D 1080 -N user@跳板机 &

# 然后浏览器配代理127.0.0.1:1080,直接访问内网IP

💡提示:服务多的时候,方案B(-D)更省事,不用一个个列端口;服务固定的时候,方案A(-L)更精准。

5.2 把家里 NAS 暴露到公网

家里有台 NAS,没有公网 IP

有一台有公网 IP 的 VPS

方案(-R远程转发):

# 在NAS上运行(把NAS的80端口映射到VPS的8080端口)

ssh -R 8080:localhost:80 -N user@VPS

VPS 上的 /etc/ssh/sshd_config需要加:

GatewayPorts yes

然后公网IP:8080就能访问到家里 NAS 的 80 端口了。

5.3 远程调试——把开发机的端口给同事看

在本地跑了个 Web 服务在 localhost:3000

想看效果,但没有公网 IP

方案(-R远程转发):

# 在机器上运行

ssh -R 3000:localhost:3000 -N user@有公网IP的服务器

同事访问服务器公网IP:3000就能看到本地的服务了。

⚠️注意:调试完记得断开,不要让生产服务长期暴露在这种临时隧道上。

六、SSH 隧道 vs frp/ngrok——怎么选?

SSH 端口转发能做的事,frp、ngrok 这类工具也能做。那什么时候用哪个?

对比项

SSH 隧道

frp / ngrok

前提条件

需要一台能 SSH 的服务器

需要服务端支持(frp自建/ngrok用官方)

配置复杂度

低(一行命令)

中(需要配置文件)

断线重连

需要 autossh

内置

支持协议

TCP(SSH本身)

TCP/UDP/HTTP/HTTPS

子域名/域名

不支持

ngrok 支持随机子域名

性能

一般(加密开销)

较好(专为转发优化)

适用场景

临时、已有SSH服务器、简单需求

长期稳定、需要域名/HTTPS、高并发

费用

零(用自己服务器)

frp自建免费;ngrok免费版有限制

决策建议:

·临时用一下、服务器已经有 SSH → 直接用 SSH 隧道,一行命令搞定

·长期稳定内网穿透、需要 HTTP/HTTPS 域名 → frp(自建)

·快速演示、不想折腾服务器 → ngrok 免费版(有连接数、域名和流量限制)

·企业级需求、高并发 → frp 或其他专业工具

七、常见问题排查

问题

原因

解决方法

bind: Address already in use

本地端口被占用

换一个本地端口号,或 kill 占用进程

隧道建好了但连不上

目标端口服务没起来

netstat -tlnp 检查目标服务状态

-R 只能本地访问,外网访问不了

GatewayPorts 未开启

远端 sshd_config 加 GatewayPorts yes

隧道频繁断线

网络不稳定 / 无心跳包

用 autossh,加 ServerAliveInterval

Channel 3: open failed

目标地址/端口不通

检查目标端口是否开放,防火墙规则

DNS 解析不走代理

用了 socks5 而非 socks5h

把 socks5 换成 socks5h

八、三种转发完整速查表

-L本地转发

# 基本格式

ssh -L 本地端口:目标地址:目标端口 user@跳板机 -N

# 常用示例

ssh -L 3306:127.0.0.1:3306 user@远端-N# 访问远端数据库

ssh -L 8080:内网IP:80 user@跳板机 -N# 访问内网Web服务

ssh -L 5432:db-server:5432 -J user@跳板机 user@内网 -N# 多跳

-R远程转发

# 基本格式

ssh -R 远端端口:本地地址:本地端口 user@远端 -N

# 常用示例

ssh -R 8080:localhost:80 user@VPS -N# 把本机80暴露到VPS:8080

ssh -R 3000:localhost:3000 user@服务器 -N# 调试端口给同事看

-D动态转发

# 基本格式

ssh -D 本地端口 user@远端 -N

# 常用示例

ssh -D 1080 user@服务器 -N# 开SOCKS5代理

autossh -M 0 -o "ServerAliveInterval 30" -D 1080 user@服务器 -N# autossh版

配合config 文件

# ~/.ssh/config

Host 隧道别名

HostName 服务器IP

User username

LocalForward 3306 127.0.0.1:3306

DynamicForward 1080

ServerAliveInterval 30

# 直接用别名建隧道

ssh -N 隧道别名

小结

覆盖了日常用到的绝大多数场景:

篇章

内容

SSH 基础篇

密钥免密、config 别名、scp/rsync 传文件、跳板机 ProxyJump

端口转发上篇

本地转发 -L(拉服务过来)、远程转发 -R(推服务出去)

端口转发下篇

动态转发 -D(SOCKS5 代理)、autossh 持久化、多跳场景、vs frp/ngrok 选择

SSH 这个工具已经 30 年了,但它能做的事到现在还是很多人没有充分挖掘。端口转发这块搞清楚之后,很多"访问不到"的问题就有了解法。

下一篇:《Linux UFW 防火墙配置——端口规则与服务保护》,从"进去"转到"守门",聊怎么用 UFW 保护自己的 Linux 机器。

最新文章

随机文章