Electerm SSH 隧道:本地、远端与动态(SOCKS)转发,不用背参数
ssh -L、ssh -R、ssh -D 是最有用的几个参数,也是最容易搞混的:到底哪边监听?哪边被连?流量往哪边走?
electerm 把三者做进了书签编辑器,就是 L→R、R→L 和 动态(SOCKS 代理) 三行选项,还带实时提示把你填的 host 和端口画成流向图回显给你。看一眼上面的横幅——一个循环演示三种模式,这篇文章讲的就是这个循环。
基础文档:How to Use SSH Tunnel。总览篇:Electerm SSH 全解。
30 秒心智模型
所有 SSH 隧道都寄生在一条现成的 SSH 连接里,只问两个问题:谁监听、连到谁:
| electerm 里的模式 | CLI 对应 | 谁监听 | 你得到 | 什么时候用 |
|---|---|---|---|---|
L→R forwardLocalToRemote |
ssh -L [本地:]本地端口:远端:远端端口 |
你的电脑 | 服务器那边/附近的东西 | 远端数据库、管理后台、内网 API |
R→L forwardRemoteToLocal |
ssh -R [远端:]远端端口:本地:本地端口 |
服务器 | 你电脑上的东西 | 给同事看本地开发服务、收 webhook |
动态 dynamicForward(SOCKS 代理) |
ssh -D [本地:]本地端口 |
你的电脑(SOCKS5) | 任意主机,都经服务器出去 | 借服务器的网浏览、一次连多个内网主机 |
一句话版本:
- L→R:"在我电脑上开个地址,通向服务器那边的地址。"
- R→L:"在服务器上开个地址,通回我电脑的地址。"
- 动态:"在我电脑上开个 SOCKS5 代理,发进去的连接都从服务器出去。"
隧道里的
remoteHost是站在服务器的角度解析的。远端填127.0.0.1指的是"服务器自己",不是你的笔记本。记住这一条,一大半困惑就没了。
在 electerm 里哪里配隧道
打开任意 SSH 书签 → 拉到 SSH 隧道分区(src/client/components/bookmark-form/common/ssh-tunnels.jsx + ssh-tunnel-form.jsx):
- 选类型:L→R、R→L 或 dynamicForward(socks proxy),默认 L→R。
- 填本地 host + 端口,以及(动态模式除外)远端 host + 端口。默认值是本地
127.0.0.1:12200、远端127.0.0.1:12300,改成你真实要用的端口。 - 起个名字(比如
pg-prod、webhook、socks-home),列表多了才认得出来。 - 点添加按钮。隧道进列表显示为
→ 本地:… → 远端:…(动态显示socks5://…)。?悬浮提示会把你实际填的值画成流向图(renderSshTunnelFlow)。 - 保存书签并连接。 隧道随会话自动建立,不用再点,也不用在后台养
ssh -fN进程。
改配置点行里的铅笔,删除点减号。一个书签可以挂多条隧道(sshTunnels 是数组)——比如 Postgres + Redis + 管理后台,一条连接全带走。
底层实现(src/app/server/ssh-tunnel.js):
- L→R 在本机起 TCP 服务(
net.createServer),每个进来的连接经 SSH(conn.forwardOut)打出去。 - R→L 让服务器监听(
conn.forwardIn),进来的连接再管道回本机(net.connect)。 - 动态在本机起 SOCKS5 服务(
socksv5-server),每个 SOCKS 请求经 SSH(conn.forwardOut)转发。 - 每个连接相互隔离——一个 socket 挂了只关自己,不断整条隧道;SSH 断了隧道跟着收。
进阶:quick-connect 连接串也能带隧道,例如 ssh://user@host:22?opts={"sshTunnels":[{"sshTunnel":"forwardLocalToRemote","sshTunnelLocalPort":8080,"sshTunnelRemoteHost":"localhost","sshTunnelRemotePort":80}]}。
1. 本地 → 远端(-L):伸进服务器的世界
形状: electerm 在你的电脑上监听 localHost:localPort,发到这里的东西经 SSH 连接送到站在服务器角度看的 remoteHost:remotePort。
浏览器 → 127.0.0.1:5000(你的电脑)
│ SSH 连接
▼
服务器 → remoteHost:6000(服务器的网络)
配置示例:只监听 localhost 的远端 Postgres:
- 类型:L→R
- 本地:
127.0.0.1、5433(本地用 5433,别跟自己机器上的 5432 打架) - 远端:
127.0.0.1、5432 - 名字:
pg-prod
保存、连接,然后客户端连 127.0.0.1:5433:
psql -h 127.0.0.1 -p 5433 -U app prod
同形状的更多例子:
- 远端 3000 端口的管理后台 → 本地
127.0.0.1:5000,浏览器开http://127.0.0.1:5000。 - 只有服务器能访问的内网服务,比如远端
10.0.0.8:8080→ 本地127.0.0.1:8080。记住远端地址是服务器去解析的,VPC 内网地址这里直接能用。 - CLI 对应:
ssh -L 5433:127.0.0.1:5432 user@server。
视频:本地到远端的 SSH 隧道。
2. 远端 → 本地(-R):让服务器连回你
**形状:***服务器*监听 remoteHost:remotePort,连到那里的东西经 SSH 连接送回你电脑的 localHost:localPort。
同事 / webhook → server:6000
│ SSH 连接(反向)
▼
你的电脑 ← 127.0.0.1:5000
配置示例:把本地开发服务演示给能连上服务器的人看:
- 类型:R→L
- 远端:
127.0.0.1、6000 - 本地:
127.0.0.1、5000(npm run dev监听的地方) - 名字:
demo-friday
保存、连接,服务器上打开 http://127.0.0.1:6000 的人拿到的就是你本地 :5000 的内容。
其他用法:
- 经服务器公网地址在笔记本上收第三方 webhook。
- 不部署就把本地 API 暴露给远端测试机。
- CLI 对应:
ssh -R 6000:127.0.0.1:5000 user@server。
-R 专属两个坑:
- 想让别的机器也能连远端端口,远端 host 得填
0.0.0.0,且服务器sshd_config要开GatewayPorts yes,否则只监听 loopback——默认这样最安全。 - 远端端口在服务器上被占了就 bind 失败,换个端口。
视频:远端到本地的 SSH 隧道。
3. 动态(-D):从服务器出去的 SOCKS5 代理
形状: electerm 在你的电脑上监听 localHost:localPort 说 SOCKS5。任何支持 SOCKS 的应用指过来,每个连接都经 SSH 转发到应用要去的目的地,由服务器解析。
浏览器 --SOCKS5--> 127.0.0.1:1080(你的电脑)
│ SSH 连接
▼ 从服务器出去
互联网 / VPC 里的任意主机
配置:
- 类型:dynamicForward(socks proxy)——远端 host/端口会消失,因为没有单一目的地。
- 本地:
127.0.0.1、1080 - 名字:
socks-prod
保存、连接,然后:
- Firefox:设置 → 网络 → SOCKS5 填
127.0.0.1:1080(打开远程 DNS,域名也经服务器解析)。 - Chrome:
chrome --proxy-server="socks5://127.0.0.1:1080"。 - curl:
curl --socks5 127.0.0.1:1080 https://ifconfig.me——返回的是服务器的 IP,就证明流量从那出去。 - CLI 对应:
ssh -D 1080 user@server。
目的地很多、提前不知道、或域名只能在 VPC 内解析时,一个 SOCKS 顶一堆 -L,不用一条条配。
视频:动态 SOCKS 代理。
排错清单
- 本地"端口被占用"——
localPort被别的程序(或另一条隧道)占了。lsof -i :5433查一下换个空闲端口,1024 以下要 root,尽量别用。 - 隧道通了但 connection refused——隧道没问题,是站在服务器角度看
remoteHost:remotePort上根本没服务。先 SSH 上去在服务器里curl remoteHost:remotePort验证。 remoteHost视角搞反了——127.0.0.1指服务器自己。目标在你笔记本上说明方向选反了(该用 R→L 而不是 L→R)。- R→L 只能在服务器本机连到——没开
GatewayPorts yes+ 远端0.0.0.0就是这样,这是服务端sshd_config的事,不是 electerm 的 bug。 - 会话断了隧道跟着没——设计如此:隧道绑在 SSH 连接生命周期上(
conn.on('close')即回收)。重连即回来;真不能断的活儿放 tmux 里再加隧道看门。 - 服务器禁了转发——服务端
AllowTcpForwarding no(或DisableForwarding)会禁掉全部三种模式,得找管理员放开。 - SOCKS 配了没走代理——很多应用要单独设代理还要开远程 DNS,先拿
curl --socks5测一把,分清"隧道坏了"还是"应用没用隧道"。
速查
- 要够服务器附近的东西 → L→R(
ssh -L 本地端口:远端:远端端口),本地端口是你的,远端地址是服务器的视角。 - 要让服务器够你的电脑 → R→L(
ssh -R 远端端口:本地:本地端口),非 loopback 暴露要GatewayPorts。 - 要像服务器一样够很多东西 → 动态 SOCKS(
ssh -D 本地端口),应用挂socks5://127.0.0.1:本地端口。 - electerm 里:书签 → 隧道分区 → 类型 + host + 端口 + 名字 → 添加 → 保存 → 连接。铅笔改、减号删,一个书签挂多条没问题。
- 隧道随会话生随会话死——一条连接的事,不留满地
ssh -fN僵尸进程。
下一篇:Electerm SSH 全解看认证、跳板机和 NetBird 怎么跟隧道组队——长隧道总被闲置杀掉就看会话保活。
