Shellby Shellby指南Guides
全部指南All guides 文档Docs ← 返回首页← Home

指南Guides ·

SSH 端口转发怎么用?本地、远程、动态三种隧道讲清楚SSH Port Forwarding Explained: Local, Remote and Dynamic Tunnels

你在服务器上装了数据库,出于安全考虑它只监听 127.0.0.1——本机之外一律连不上。现在你想用电脑上的图形客户端连它,怎么办?开放公网端口是最糟的答案。正确答案是 SSH 端口转发:借你已经有的那条 SSH 连接,把流量捎过去。

三种转发,一句话区分

  • 本地转发 -L:把远端的服务搬到你本机的一个端口上。最常用,九成场景是它。
  • 远程转发 -R:反过来,把你本机的服务送到服务器那一侧。
  • 动态转发 -D:在本机开一个 SOCKS5 代理,目标不写死,由客户端逐个请求决定。

三者都只是给你自己有权限的机器之间搭一条通路,前提是你本来就能 SSH 登录那台服务器。

本地转发 -L:把远端服务搬到手边

典型场景:服务器上的 MySQL 监听 127.0.0.1:3306,你想用本机客户端连。

ssh -L 13306:127.0.0.1:3306 user@server

之后连本机的 127.0.0.1:13306,流量就会经 SSH 送到服务器上的 3306。数据库那边看到的来源是它自己的本地回环,规则一点不用改。

那四段参数怎么读

-L 13306:127.0.0.1:3306 拆开是「本地监听端口 : 目标地址 : 目标端口」。关键在于:目标地址是站在服务器的角度解析的。写 127.0.0.1 指的是服务器自己;要连服务器所在内网的另一台机器,就写那台机器的内网地址:

ssh -L 18080:192.168.1.50:80 user@server

这样访问本机 127.0.0.1:18080,实际到达的是内网 192.168.1.50 的 80 端口——服务器成了你进内网的入口。这也是内网后台、打印机面板、路由器管理页这类只在内网可达的服务的通用访问方式。

远程转发 -R:把本机服务送过去

典型场景:你在笔记本上跑着开发服务器(localhost:3000),想让服务器上的程序回调它。

ssh -R 8000:127.0.0.1:3000 user@server

服务器上访问它自己的 127.0.0.1:8000,请求就会回到你笔记本的 3000。参数顺序同理,只是监听端在远端。

注意:远端默认只绑回环地址,即只有服务器本机能用。想让同内网的其他机器也能访问,需要服务器的 sshd_config 打开 GatewayPorts——这属于扩大暴露面,改之前想清楚。

动态转发 -D:一条隧道,多个目标

ssh -D 11080 user@server

本机 11080 上出现一个 SOCKS5 代理。把开发工具、数据库客户端或浏览器的代理指向它,这些请求就都从服务器那一侧发出。适合运维时临时访问一批分散的内网地址——不用为每个目标单开一条 -L

跳板机 -J:目标不能直连时

目标机器只允许从堡垒机访问,那就串起来:

ssh -J user@bastion user@target

转发参数照常加,隧道会经整条链路建立。多跳就多写几个,用逗号分隔。

在手机上用隧道,有一点不一样

手机端的能力和命令行一致——Shellby 的「隧道」面板里选类型、填端口就行,三种转发和跳板机都支持。但有一条移动平台的硬约束值得先知道:

App 退到后台会被系统挂起,隧道随之暂停。iOS 是数十秒内,鸿蒙更快——退后台约 3 秒即冻结进程,SSH 连接跟着断。这不是某个 App 做得不好,是移动系统的后台策略,任何 SSH 客户端都一样。

所以手机上的隧道有两种现实用法:

  • App 内使用:在同一个 App 里经隧道做 SFTP 传输、看服务器监控——全程前台,不受影响。
  • 给别的 App 用(比如浏览器访问 127.0.0.1:8080):需要保持 SSH 客户端在前台,或分屏并排使用。

Shellby 在这件事上不粉饰:隧道列表会明确告诉你「退到后台会被系统挂起」,状态分「连接中 / 运行中 / 已断开」如实显示,断开原因一直留在条目上。回到前台时会自动重连恢复,不需要你手动停一次再启动——但我们不会把它写成「后台保活」,因为系统不允许。

常见问题

提示端口已被占用

本机监听端口被别的程序拿走了。换一个高位端口即可(如 13306、18080),本地端口号是你随便挑的,不必和目标端口一致。

隧道建起来了,但连不上

先确认目标地址是相对服务器写的。在服务器上执行 ss -lntp 看目标服务到底监听在哪个地址和端口——很多服务只绑 127.0.0.1,而你写成了内网 IP,自然不通。

该绑 127.0.0.1 还是 0.0.0.0

默认绑 127.0.0.1,只有本机能用,这是安全的默认值。绑 0.0.0.0 意味着同一网络里的任何设备都能经你这台机器进入隧道——在公共 Wi-Fi 下尤其危险,除非你清楚知道自己在做什么。

隧道会让连接更慢吗

多了一层加密与中转,会有开销,但对数据库客户端、Web 后台这类交互式使用基本无感。大流量传输才需要在意。

下一步

端口转发的前提是一条稳定的 SSH 连接。如果你还没配好密钥登录,先看SSH 密钥指南;在手机上第一次连服务器,看iPhone 连服务器鸿蒙连服务器

You installed a database on your server and, sensibly, it only listens on 127.0.0.1 — nothing outside the machine can reach it. Now you want to connect with a GUI client from your laptop. Opening a public port is the worst possible answer. The right one is SSH port forwarding: carry the traffic over the SSH connection you already have.

Three kinds, one line each

  • Local forwarding -L: brings a service on the remote side to a port on your machine. By far the most common.
  • Remote forwarding -R: the reverse — exposes a service on your machine to the server side.
  • Dynamic forwarding -D: opens a SOCKS5 proxy locally; the destination isn't fixed, each request decides.

All three simply build a path between machines you already control — the prerequisite is that you can SSH into that server in the first place.

Local forwarding: bring the remote service to you

The classic case: MySQL on the server listens on 127.0.0.1:3306 and you want your local client to reach it.

ssh -L 13306:127.0.0.1:3306 user@server

Point your client at 127.0.0.1:13306 and the traffic travels over SSH to port 3306 on the server. As far as the database is concerned the connection came from its own loopback — no rule changes needed.

How to read those four parts

-L 13306:127.0.0.1:3306 reads as "local port : destination host : destination port". The key detail: the destination is resolved from the server's point of view. 127.0.0.1 means the server itself. To reach another machine on the server's network, name that machine:

ssh -L 18080:192.168.1.50:80 user@server

Now 127.0.0.1:18080 on your laptop lands on port 80 of 192.168.1.50 inside that network — the server acts as your doorway. This is the general way to reach internal dashboards, printer panels and router pages that are only routable from inside.

Remote forwarding: send your service over there

The case: you're running a dev server on your laptop (localhost:3000) and something on the server needs to call back into it.

ssh -R 8000:127.0.0.1:3000 user@server

The server hits its own 127.0.0.1:8000 and the request arrives at port 3000 on your laptop. Same argument order; only the listening side moved.

Note that the remote side binds loopback only by default, so just the server itself can use it. Letting other machines on its network in requires GatewayPorts in the server's sshd_config — that widens your exposure, so decide deliberately.

Dynamic forwarding: one tunnel, many destinations

ssh -D 11080 user@server

A SOCKS5 proxy appears on local port 11080. Point a dev tool, database client or browser at it and those requests leave from the server's side instead. Handy for ops work that touches a scattered set of internal addresses — no need for a separate -L per target.

Jump hosts: when the target isn't directly reachable

If the target only accepts connections from a bastion, chain them:

ssh -J user@bastion user@target

Forwarding flags work as usual and the tunnel is built across the whole chain. Add more hops separated by commas.

Tunnelling from a phone is a little different

The capability matches the command line — in Shellby you pick a type in the Tunnels panel and fill in the ports; all three kinds plus jump hosts are supported. But one mobile-platform constraint is worth knowing up front:

When the app goes to the background the system suspends it, and tunnels pause with it. On iOS that takes tens of seconds; on HarmonyOS it is faster still — the process is frozen roughly 3 seconds after you leave, and the SSH connection drops with it. This isn't one app being sloppy; it's the platform's background policy, and every SSH client lives under it.

So there are two realistic ways to use tunnels on a phone:

  • Inside the app: SFTP transfers or server monitoring routed through the tunnel — all in the foreground, unaffected.
  • For other apps (a browser hitting 127.0.0.1:8080): keep the SSH client in the foreground, or run the two side by side in split screen.

Shellby doesn't paper over this: the tunnel list says plainly that the app is suspended in the background, status is shown honestly as connecting / running / disconnected, and the reason for a disconnect stays on the row. Coming back to the foreground reconnects automatically, so you never have to stop and start it by hand — but we won't call that "background keep-alive", because the system doesn't allow it.

FAQ

It says the port is already in use

Something else holds that local port. Pick another high one (13306, 18080 …) — the local port is yours to choose and needn't match the destination.

The tunnel is up but nothing connects

First check the destination is written from the server's perspective. Run ss -lntp on the server to see which address and port the service actually listens on — plenty of services bind 127.0.0.1 only, and naming their LAN IP simply won't reach them.

Should I bind 127.0.0.1 or 0.0.0.0?

127.0.0.1 is the default and the safe one: only your machine can use the tunnel. Binding 0.0.0.0 lets any device on the same network enter the tunnel through you — particularly dangerous on public Wi-Fi, so only do it knowing exactly why.

Does tunnelling slow things down?

There's encryption and an extra hop, so there is overhead, but interactive use — database clients, web dashboards — rarely feels it. It matters for bulk transfers.

Next

Port forwarding rests on a solid SSH connection. If key login isn't set up yet, start with the SSH keys guide; for a first connection from a phone see SSH from iPhone or SSH from HarmonyOS.